diff options
1965 files changed, 54757 insertions, 31018 deletions
@@ -3101,7 +3101,7 @@ S: Minto, NSW, 2566 S: Australia N: Stephen Smalley -E: sds@epoch.ncsc.mil +E: sds@tycho.nsa.gov D: portions of the Linux Security Module (LSM) framework and security modules N: Chris Smith diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt index fcbcbc35b122..6221464d1a7e 100644 --- a/Documentation/RCU/RTFP.txt +++ b/Documentation/RCU/RTFP.txt @@ -90,16 +90,20 @@ at OLS. The resulting abundance of RCU patches was presented the following year [McKenney02a], and use of RCU in dcache was first described that same year [Linder02a]. -Also in 2002, Michael [Michael02b,Michael02a] presented techniques -that defer the destruction of data structures to simplify non-blocking -synchronization (wait-free synchronization, lock-free synchronization, -and obstruction-free synchronization are all examples of non-blocking -synchronization). In particular, this technique eliminates locking, -reduces contention, reduces memory latency for readers, and parallelizes -pipeline stalls and memory latency for writers. However, these -techniques still impose significant read-side overhead in the form of -memory barriers. Researchers at Sun worked along similar lines in the -same timeframe [HerlihyLM02,HerlihyLMS03]. +Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer" +techniques that defer the destruction of data structures to simplify +non-blocking synchronization (wait-free synchronization, lock-free +synchronization, and obstruction-free synchronization are all examples of +non-blocking synchronization). In particular, this technique eliminates +locking, reduces contention, reduces memory latency for readers, and +parallelizes pipeline stalls and memory latency for writers. However, +these techniques still impose significant read-side overhead in the +form of memory barriers. Researchers at Sun worked along similar lines +in the same timeframe [HerlihyLM02,HerlihyLMS03]. These techniques +can be thought of as inside-out reference counts, where the count is +represented by the number of hazard pointers referencing a given data +structure (rather than the more conventional counter field within the +data structure itself). In 2003, the K42 group described how RCU could be used to create hot-pluggable implementations of operating-system functions. Later that @@ -113,7 +117,6 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper describing how to make RCU safe for soft-realtime applications [Sarma04c], and a paper describing SELinux performance with RCU [JamesMorris04b]. - 2005 has seen further adaptation of RCU to realtime use, permitting preemption of RCU realtime critical sections [PaulMcKenney05a, PaulMcKenney05b]. diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt index e118a7c1a092..49e27cc19385 100644 --- a/Documentation/RCU/checklist.txt +++ b/Documentation/RCU/checklist.txt @@ -177,3 +177,9 @@ over a rather long period of time, but improvements are always welcome! If you want to wait for some of these other things, you might instead need to use synchronize_irq() or synchronize_sched(). + +12. Any lock acquired by an RCU callback must be acquired elsewhere + with irq disabled, e.g., via spin_lock_irqsave(). Failing to + disable irq on a given acquisition of that lock will result in + deadlock as soon as the RCU callback happens to interrupt that + acquisition's critical section. diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt index f8a54fa0d8ab..1fd175368a87 100644 --- a/Documentation/RCU/listRCU.txt +++ b/Documentation/RCU/listRCU.txt @@ -232,7 +232,7 @@ entry does not exist. For this to be helpful, the search function must return holding the per-entry spinlock, as ipc_lock() does in fact do. Quick Quiz: Why does the search function need to return holding the -per-entry lock for this deleted-flag technique to be helpful? + per-entry lock for this deleted-flag technique to be helpful? If the system-call audit module were to ever need to reject stale data, one way to accomplish this would be to add a "deleted" flag and a "lock" @@ -275,8 +275,8 @@ flag under the spinlock as follows: { struct audit_entry *e; - /* Do not use the _rcu iterator here, since this is the only - * deletion routine. */ + /* Do not need to use the _rcu iterator here, since this + * is the only deletion routine. */ list_for_each_entry(e, list, list) { if (!audit_compare_rule(rule, &e->rule)) { spin_lock(&e->lock); @@ -304,9 +304,12 @@ function to reject newly deleted data. Answer to Quick Quiz - -If the search function drops the per-entry lock before returning, then -the caller will be processing stale data in any case. If it is really -OK to be processing stale data, then you don't need a "deleted" flag. -If processing stale data really is a problem, then you need to hold the -per-entry lock across all of the code that uses the value looked up. + Why does the search function need to return holding the per-entry + lock for this deleted-flag technique to be helpful? + + If the search function drops the per-entry lock before returning, + then the caller will be processing stale data in any case. If it + is really OK to be processing stale data, then you don't need a + "deleted" flag. If processing stale data really is a problem, + then you need to hold the per-entry lock across all of the code + that uses the value that was returned. diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt index 6fa092251586..02e27bf1d365 100644 --- a/Documentation/RCU/rcu.txt +++ b/Documentation/RCU/rcu.txt @@ -111,6 +111,11 @@ o What are all these files in this directory? You are reading it! + rcuref.txt + + Describes how to combine use of reference counts + with RCU. + whatisRCU.txt Overview of how the RCU implementation works. Along diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt index 3f60db41b2f0..451de2ad8329 100644 --- a/Documentation/RCU/rcuref.txt +++ b/Documentation/RCU/rcuref.txt @@ -1,7 +1,7 @@ -Refcounter design for elements of lists/arrays protected by RCU. +Reference-count design 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: +Reference counting on elements of lists which are protected by traditional +reader/writer spinlocks or semaphores are straightforward: 1. 2. add() search_and_reference() @@ -28,12 +28,12 @@ release_referenced() delete() ... } -If this list/array is made lock free using rcu as in changing the -write_lock in add() and delete() to spin_lock and changing read_lock +If this list/array is made lock free using RCU as in changing the +write_lock() in add() and delete() to spin_lock and changing read_lock in search_and_reference to rcu_read_lock(), the atomic_get in search_and_reference could potentially hold reference to an element which -has already been deleted from the list/array. atomic_inc_not_zero takes -care of this scenario. search_and_reference should look as; +has already been deleted from the list/array. Use atomic_inc_not_zero() +in this scenario as follows: 1. 2. add() search_and_reference() @@ -51,17 +51,16 @@ add() search_and_reference() 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); delete_element + ... write_unlock(&list_lock); +} ... if (atomic_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 -is to be used in such cases. - +Sometimes, a reference to the element needs to be obtained in the +update (write) stream. In such cases, atomic_inc_not_zero() might be +overkill, since we hold the update-side spinlock. One might instead +use atomic_inc() in such cases. diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 15da16861fa3..5ed85af88789 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -200,10 +200,11 @@ rcu_assign_pointer() the new value, and also executes any memory-barrier instructions required for a given CPU architecture. - Perhaps more important, it serves to document which pointers - are protected by RCU. That said, rcu_assign_pointer() is most - frequently used indirectly, via the _rcu list-manipulation - primitives such as list_add_rcu(). + Perhaps just as important, it serves to document (1) which + pointers are protected by RCU and (2) the point at which a + given structure becomes accessible to other CPUs. That said, + rcu_assign_pointer() is most frequently used indirectly, via + the _rcu list-manipulation primitives such as list_add_rcu(). rcu_dereference() @@ -258,9 +259,11 @@ rcu_dereference() locking. As with rcu_assign_pointer(), an important function of - rcu_dereference() is to document which pointers are protected - by RCU. And, again like rcu_assign_pointer(), rcu_dereference() - is typically used indirectly, via the _rcu list-manipulation + rcu_dereference() is to document which pointers are protected by + RCU, in particular, flagging a pointer that is subject to changing + at any time, including immediately after the rcu_dereference(). + And, again like rcu_assign_pointer(), rcu_dereference() is + typically used indirectly, via the _rcu list-manipulation primitives, such as list_for_each_entry_rcu(). The following diagram shows how each API communicates among the @@ -327,7 +330,7 @@ for specialized uses, but are relatively uncommon. 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? This section shows a simple use of the core RCU API to protect a -global pointer to a dynamically allocated structure. More typical +global pointer to a dynamically allocated structure. More-typical uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt. struct foo { @@ -410,6 +413,8 @@ o Use synchronize_rcu() -after- removing a data element from an data item. See checklist.txt for additional rules to follow when using RCU. +And again, more-typical uses of RCU may be found in listRCU.txt, +arrayRCU.txt, and NMI-RCU.txt. 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? @@ -513,7 +518,7 @@ production-quality implementation, and see: for papers describing the Linux kernel RCU implementation. The OLS'01 and OLS'02 papers are a good introduction, and the dissertation provides -more details on the current implementation. +more details on the current implementation as of early 2004. 5A. "TOY" IMPLEMENTATION #1: LOCKING @@ -768,7 +773,6 @@ RCU pointer/list traversal: rcu_dereference list_for_each_rcu (to be deprecated in favor of list_for_each_entry_rcu) - list_for_each_safe_rcu (deprecated, not used) list_for_each_entry_rcu list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) @@ -807,7 +811,8 @@ Quick Quiz #1: Why is this argument naive? How could a deadlock Answer: Consider the following sequence of events: 1. CPU 0 acquires some unrelated lock, call it - "problematic_lock". + "problematic_lock", disabling irq via + spin_lock_irqsave(). 2. CPU 1 enters synchronize_rcu(), write-acquiring rcu_gp_mutex. @@ -894,7 +899,7 @@ Answer: Just as PREEMPT_RT permits preemption of spinlock ACKNOWLEDGEMENTS My thanks to the people who helped make this human-readable, including -Jon Walpole, Josh Triplett, Serge Hallyn, and Suzanne Wood. +Jon Walpole, Josh Triplett, Serge Hallyn, Suzanne Wood, and Alan Stern. For more information, see http://www.rdrop.com/users/paulmck/RCU. diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt new file mode 100644 index 000000000000..ff280e2e1613 --- /dev/null +++ b/Documentation/cputopology.txt @@ -0,0 +1,41 @@ + +Export cpu topology info by sysfs. Items (attributes) are similar +to /proc/cpuinfo. + +1) /sys/devices/system/cpu/cpuX/topology/physical_package_id: +represent the physical package id of cpu X; +2) /sys/devices/system/cpu/cpuX/topology/core_id: +represent the cpu core id to cpu X; +3) /sys/devices/system/cpu/cpuX/topology/thread_siblings: +represent the thread siblings to cpu X in the same core; +4) /sys/devices/system/cpu/cpuX/topology/core_siblings: +represent the thread siblings to cpu X in the same physical package; + +To implement it in an architecture-neutral way, a new source file, +driver/base/topology.c, is to export the 5 attributes. + +If one architecture wants to support this feature, it just needs to +implement 4 defines, typically in file include/asm-XXX/topology.h. +The 4 defines are: +#define topology_physical_package_id(cpu) +#define topology_core_id(cpu) +#define topology_thread_siblings(cpu) +#define topology_core_siblings(cpu) + +The type of **_id is int. +The type of siblings is cpumask_t. + +To be consistent on all architectures, the 4 attributes should have +deafult values if their values are unavailable. Below is the rule. +1) physical_package_id: If cpu has no physical package id, -1 is the +default value. +2) core_id: If cpu doesn't support multi-core, its core id is 0. +3) thread_siblings: Just include itself, if the cpu doesn't support +HT/multi-thread. +4) core_siblings: Just include itself, if the cpu doesn't support +multi-core and HT/Multi-thread. + +So be careful when declaring the 4 defines in include/asm-XXX/topology.h. + +If an attribute isn't defined on an architecture, it won't be exported. + diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt index 44662735cf81..ac4a7a737e43 100644 --- a/Documentation/driver-model/overview.txt +++ b/Documentation/driver-model/overview.txt @@ -1,50 +1,43 @@ The Linux Kernel Device Model -Patrick Mochel <mochel@osdl.org> +Patrick Mochel <mochel@digitalimplant.org> -26 August 2002 +Drafted 26 August 2002 +Updated 31 January 2006 Overview ~~~~~~~~ -This driver model is a unification of all the current, disparate driver models -that are currently in the kernel. It is intended to augment the +The Linux Kernel Driver Model is a unification of all the disparate driver +models that were previously used in the kernel. It is intended to augment the bus-specific drivers for bridges and devices by consolidating a set of data and operations into globally accessible data structures. -Current driver models implement some sort of tree-like structure (sometimes -just a list) for the devices they control. But, there is no linkage between -the different bus types. +Traditional driver models implemented some sort of tree-like structure +(sometimes just a list) for the devices they control. There wasn't any +uniformity across the different bus types. -A common data structure can provide this linkage with little overhead: when a -bus driver discovers a particular device, it can insert it into the global -tree as well as its local tree. In fact, the local tree becomes just a subset -of the global tree. - -Common data fields can also be moved out of the local bus models into the -global model. Some of the manipulations of these fields can also be -consolidated. Most likely, manipulation functions will become a set -of helper functions, which the bus drivers wrap around to include any -bus-specific items. - -The common device and bridge interface currently reflects the goals of the -modern PC: namely the ability to do seamless Plug and Play, power management, -and hot plug. (The model dictated by Intel and Microsoft (read: ACPI) ensures -us that any device in the system may fit any of these criteria.) - -In reality, not every bus will be able to support such operations. But, most -buses will support a majority of those operations, and all future buses will. -In other words, a bus that doesn't support an operation is the exception, -instead of the other way around. +The current driver model provides a comon, uniform data model for describing +a bus and the devices that can appear under the bus. The unified bus +model includes a set of common attributes which all busses carry, and a set +of common callbacks, such as device discovery during bus probing, bus +shutdown, bus power management, etc. +The common device and bridge interface reflects the goals of the modern +computer: namely the ability to do seamless device "plug and play", power +management, and hot plug. In particular, the model dictated by Intel and +Microsoft (namely ACPI) ensures that almost every device on almost any bus +on an x86-compatible system can work within this paradigm. Of course, +not every bus is able to support all such operations, although most +buses support a most of those operations. Downstream Access ~~~~~~~~~~~~~~~~~ Common data fields have been moved out of individual bus layers into a common -data structure. But, these fields must still be accessed by the bus layers, +data structure. These fields must still be accessed by the bus layers, and sometimes by the device-specific drivers. Other bus layers are encouraged to do what has been done for the PCI layer. @@ -53,7 +46,7 @@ struct pci_dev now looks like this: struct pci_dev { ... - struct device device; + struct device dev; }; Note first that it is statically allocated. This means only one allocation on @@ -64,9 +57,9 @@ the two. The PCI bus layer freely accesses the fields of struct device. It knows about the structure of struct pci_dev, and it should know the structure of struct -device. PCI devices that have been converted generally do not touch the fields -of struct device. More precisely, device-specific drivers should not touch -fields of struct device unless there is a strong compelling reason to do so. +device. Individual PCI device drivers that have been converted the the current +driver model generally do not and should not touch the fields of struct device, +unless there is a strong compelling reason to do so. This abstraction is prevention of unnecessary pain during transitional phases. If the name of the field changes or is removed, then every downstream driver diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt new file mode 100644 index 000000000000..d37191fe5681 --- /dev/null +++ b/Documentation/drivers/edac/edac.txt @@ -0,0 +1,673 @@ + + +EDAC - Error Detection And Correction + +Written by Doug Thompson <norsk5@xmission.com> +7 Dec 2005 + + +EDAC was written by: + Thayne Harbaugh, + modified by Dave Peterson, Doug Thompson, et al, + from the bluesmoke.sourceforge.net project. + + +============================================================================ +EDAC PURPOSE + +The 'edac' kernel module goal is to detect and report errors that occur +within the computer system. In the initial release, memory Correctable Errors +(CE) and Uncorrectable Errors (UE) are the primary errors being harvested. + +Detecting CE events, then harvesting those events and reporting them, +CAN be a predictor of future UE events. With CE events, the system can +continue to operate, but with less safety. Preventive maintainence and +proactive part replacement of memory DIMMs exhibiting CEs can reduce +the likelihood of the dreaded UE events and system 'panics'. + + +In addition, PCI Bus Parity and SERR Errors are scanned for on PCI devices +in order to determine if errors are occurring on data transfers. +The presence of PCI Parity errors must be examined with a grain of salt. +There are several addin adapters that do NOT follow the PCI specification +with regards to Parity generation and reporting. The specification says +the vendor should tie the parity status bits to 0 if they do not intend +to generate parity. Some vendors do not do this, and thus the parity bit +can "float" giving false positives. + +The PCI Parity EDAC device has the ability to "skip" known flakey +cards during the parity scan. These are set by the parity "blacklist" +interface in the sysfs for PCI Parity. (See the PCI section in the sysfs +section below.) There is also a parity "whitelist" which is used as +an explicit list of devices to scan, while the blacklist is a list +of devices to skip. + +EDAC will have future error detectors that will be added or integrated +into EDAC in the following list: + + MCE Machine Check Exception + MCA Machine Check Architecture + NMI NMI notification of ECC errors + MSRs Machine Specific Register error cases + and other mechanisms. + +These errors are usually bus errors, ECC errors, thermal throttling +and the like. + + +============================================================================ +EDAC VERSIONING + +EDAC is composed of a "core" module (edac_mc.ko) and several Memory +Controller (MC) driver modules. On a given system, the CORE +is loaded and one MC driver will be loaded. Both the CORE and +the MC driver have individual versions that reflect current release +level of their respective modules. Thus, to "report" on what version +a system is running, one must report both the CORE's and the +MC driver's versions. + + +LOADING + +If 'edac' was statically linked with the kernel then no loading is +necessary. If 'edac' was built as modules then simply modprobe the +'edac' pieces that you need. You should be able to modprobe +hardware-specific modules and have the dependencies load the necessary core +modules. + +Example: + +$> modprobe amd76x_edac + +loads both the amd76x_edac.ko memory controller module and the edac_mc.ko +core module. + + +============================================================================ +EDAC sysfs INTERFACE + +EDAC presents a 'sysfs' interface for control, reporting and attribute +reporting purposes. + +EDAC lives in the /sys/devices/system/edac directory. Within this directory +there currently reside 2 'edac' components: + + mc memory controller(s) system + pci PCI status system + + +============================================================================ +Memory Controller (mc) Model + +First a background on the memory controller's model abstracted in EDAC. +Each mc device controls a set of DIMM memory modules. These modules are +layed out in a Chip-Select Row (csrowX) and Channel table (chX). There can +be multiple csrows and two channels. + +Memory controllers allow for several csrows, with 8 csrows being a typical value. +Yet, the actual number of csrows depends on the electrical "loading" +of a given motherboard, memory controller and DIMM characteristics. + +Dual channels allows for 128 bit data transfers to the CPU from memory. + + + Channel 0 Channel 1 + =================================== + csrow0 | DIMM_A0 | DIMM_B0 | + csrow1 | DIMM_A0 | DIMM_B0 | + =================================== + + =================================== + csrow2 | DIMM_A1 | DIMM_B1 | + csrow3 | DIMM_A1 | DIMM_B1 | + =================================== + +In the above example table there are 4 physical slots on the motherboard +for memory DIMMs: + + DIMM_A0 + DIMM_B0 + DIMM_A1 + DIMM_B1 + +Labels for these slots are usually silk screened on the motherboard. Slots +labeled 'A' are channel 0 in this example. Slots labled 'B' +are channel 1. Notice that there are two csrows possible on a +physical DIMM. These csrows are allocated their csrow assignment +based on the slot into which the memory DIMM is placed. Thus, when 1 DIMM +is placed in each Channel, the csrows cross both DIMMs. + +Memory DIMMs come single or dual "ranked". A rank is a populated csrow. +Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above +will have 1 csrow, csrow0. csrow1 will be empty. On the other hand, +when 2 dual ranked DIMMs are similiaryly placed, then both csrow0 and +csrow1 will be populated. The pattern repeats itself for csrow2 and +csrow3. + +The representation of the above is reflected in the directory tree +in EDAC's sysfs interface. Starting in directory +/sys/devices/system/edac/mc each memory controller will be represented +by its own 'mcX' directory, where 'X" is the index of the MC. + + + ..../edac/mc/ + | + |->mc0 + |->mc1 + |->mc2 + .... + +Under each 'mcX' directory each 'csrowX' is again represented by a +'csrowX', where 'X" is the csrow index: + + + .../mc/mc0/ + | + |->csrow0 + |->csrow2 + |->csrow3 + .... + +Notice that there is no csrow1, which indicates that csrow0 is +composed of a single ranked DIMMs. This should also apply in both +Channels, in order to have dual-channel mode be operational. Since +both csrow2 and csrow3 are populated, this indicates a dual ranked +set of DIMMs for channels 0 and 1. + + +Within each of the 'mc','mcX' and 'csrowX' directories are several +EDAC control and attribute files. + + +============================================================================ +DIRECTORY 'mc' + +In directory 'mc' are EDAC system overall control and attribute files: + + +Panic on UE control file: + + 'panic_on_ue' + + An uncorrectable error will cause a machine panic. This is usually + desirable. It is a bad idea to continue when an uncorrectable error + occurs - it is indeterminate what was uncorrected and the operating + system context might be so mangled that continuing will lead to further + corruption. If the kernel has MCE configured, then EDAC will never + notice the UE. + + LOAD TIME: module/kernel parameter: panic_on_ue=[0|1] + + RUN TIME: echo "1" >/sys/devices/system/edac/mc/panic_on_ue + + +Log UE control file: + + 'log_ue' + + Generate kernel messages describing uncorrectable errors. These errors + are reported through the system message log system. UE statistics + will be accumulated even when UE logging is disabled. + + LOAD TIME: module/kernel parameter: log_ue=[0|1] + + RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ue + + +Log CE control file: + + 'log_ce' + + Generate kernel messages describing correctable errors. These + errors are reported through the system message log system. + CE statistics will be accumulated even when CE logging is disabled. + + LOAD TIME: module/kernel parameter: log_ce=[0|1] + + RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ce + + +Polling period control file: + + 'poll_msec' + + The time period, in milliseconds, for polling for error information. + Too small a value wastes resources. Too large a value might delay + necessary handling of errors and might loose valuable information for + locating the error. 1000 milliseconds (once each second) is about + right for most uses. + + LOAD TIME: module/kernel parameter: poll_msec=[0|1] + + RUN TIME: echo "1000" >/sys/devices/system/edac/mc/poll_msec + + +Module Version read-only attribute file: + + 'mc_version' + + The EDAC CORE modules's version and compile date are shown here to + indicate what EDAC is running. + + + +============================================================================ +'mcX' DIRECTORIES + + +In 'mcX' directories are EDAC control and attribute files for +this 'X" instance of the memory controllers: + + +Counter reset control file: + + 'reset_counters' + + This write-only control file will zero all the statistical counters + for UE and CE errors. Zeroing the counters will also reset the timer + indicating how long since the last counter zero. This is useful + for computing errors/time. Since the counters are always reset at + driver initialization time, no module/kernel parameter is available. + + RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset + + This resets the counters on memory controller 0 + + +Seconds since last counter reset control file: + + 'seconds_since_reset' + + This attribute file displays how many seconds have elapsed since the + last counter reset. This can be used with the error counters to + measure error rates. + + + +DIMM capability attribute file: + + 'edac_capability' + + The EDAC (Error Detection and Correction) capabilities/modes of + the memory controller hardware. + + +DIMM Current Capability attribute file: + + 'edac_current_capability' + + The EDAC capabilities available with the hardware + configuration. This may not be the same as "EDAC capability" + if the correct memory is not used. If a memory controller is + capable of EDAC, but DIMMs without check bits are in use, then + Parity, SECDED, S4ECD4ED capabilities will not be available + even though the memory controller might be capable of those + modes with the proper memory loaded. + + +Memory Type supported on this controller attribute file: + + 'supported_mem_type' + + This attribute file displays the memory type, usually + buffered and unbuffered DIMMs. + + +Memory Controller name attribute file: + + 'mc_name' + + This attribute file displays the type of memory controller + that is being utilized. + + +Memory Controller Module name attribute file: + + 'module_name' + + This attribute file displays the memory controller module name, + version and date built. The name of the memory controller + hardware - some drivers work with multiple controllers and + this field shows which hardware is present. + + +Total memory managed by this memory controller attribute file: + + 'size_mb' + + This attribute file displays, in count of megabytes, of memory + that this instance of memory controller manages. + + +Total Uncorrectable Errors count attribute file: + + 'ue_count' + + This attribute file displays the total count of uncorrectable + errors that have occurred on this memory controller. If panic_on_ue + is set this counter will not have a chance to increment, + since EDAC will panic the system. + + +Total UE count that had no information attribute fileY: + + 'ue_noinfo_count' + + This attribute file displays the number of UEs that + have occurred have occurred with no informations as to which DIMM + slot is having errors. + + +Total Correctable Errors count attribute file: + + 'ce_count' + + This attribute file displays the total count of correctable + errors that have occurred on this memory controller. This + count is very important to examine. CEs provide early + indications that a DIMM is beginning to fail. This count + field should be monitored for non-zero values and report + such information to the system administrator. + + +Total Correctable Errors count attribute file: + + 'ce_noinfo_count' + + This attribute file displays the number of CEs that + have occurred wherewith no informations as to which DIMM slot + is having errors. Memory is handicapped, but operational, + yet no information is available to indicate which slot + the failing memory is in. This count field should be also + be monitored for non-zero values. + +Device Symlink: + + 'device' + + Symlink to the memory controller device + + + +============================================================================ +'csrowX' DIRECTORIES + +In the 'csrowX' directories are EDAC control and attribute files for +this 'X" instance of csrow: + + +Total Uncorrectable Errors count attribute file: + + 'ue_count' + + This attribute file displays the total count of uncorrectable + errors that have occurred on this csrow. If panic_on_ue is set + this counter will not have a chance to increment, since EDAC + will panic the system. + + +Total Correctable Errors count attribute file: + + 'ce_count' + + This attribute file displays the total count of correctable + errors that have occurred on this csrow. This + count is very important to examine. CEs provide early + indications that a DIMM is beginning to fail. This count + field should be monitored for non-zero values and report + such information to the system administrator. + + +Total memory managed by this csrow attribute file: + + 'size_mb' + + This attribute file displays, in count of megabytes, of memory + that this csrow contatins. + + +Memory Type attribute file: + + 'mem_type' + + This attribute file will display what type of memory is currently + on this csrow. Normally, either buffered or unbuffered memory. + + +EDAC Mode of operation attribute file: + + 'edac_mode' + + This attribute file will display what type of Error detection + and correction is being utilized. + + +Device type attribute file: + + 'dev_type' + + This attribute file will display what type of DIMM device is + being utilized. Example: x4 + + +Channel 0 CE Count attribute file: + + 'ch0_ce_count' + + This attribute file will display the count of CEs on this + DIMM located in channel 0. + + +Channel 0 UE Count attribute file: + + 'ch0_ue_count' + + This attribute file will display the count of UEs on this + DIMM located in channel 0. + + +Channel 0 DIMM Label control file: + + 'ch0_dimm_label' + + This control file allows this DIMM to have a label assigned + to it. With this label in the module, when errors occur + the output can provide the DIMM label in the system log. + This becomes vital for panic events to isolate the + cause of the UE event. + + DIMM Labels must be assigned after booting, with information + that correctly identifies the physical slot with its + silk screen label. This information is currently very + motherboard specific and determination of this information + must occur in userland at this time. + + +Channel 1 CE Count attribute file: + + 'ch1_ce_count' + + This attribute file will display the count of CEs on this + DIMM located in channel 1. + + +Channel 1 UE Count attribute file: + + 'ch1_ue_count' + + This attribute file will display the count of UEs on this + DIMM located in channel 0. + + +Channel 1 DIMM Label control file: + + 'ch1_dimm_label' + + This control file allows this DIMM to have a label assigned + to it. With this label in the module, when errors occur + the output can provide the DIMM label in the system log. + This becomes vital for panic events to isolate the + cause of the UE event. + + DIMM Labels must be assigned after booting, with information + that correctly identifies the physical slot with its + silk screen label. This information is currently very + motherboard specific and determination of this information + must occur in userland at this time. + + +============================================================================ +SYSTEM LOGGING + +If logging for UEs and CEs are enabled then system logs will have +error notices indicating errors that have been detected: + +MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0, +channel 1 "DIMM_B1": amd76x_edac + +MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0, +channel 1 "DIMM_B1": amd76x_edac + + +The structure of the message is: + the memory controller (MC0) + Error type (CE) + memory page (0x283) + offset in the page (0xce0) + the byte granularity (grain 8) + or resolution of the error + the error syndrome (0xb741) + memory row (row 0) + memory channel (channel 1) + DIMM label, if set prior (DIMM B1 + and then an optional, driver-specific message that may + have additional information. + +Both UEs and CEs with no info will lack all but memory controller, +error type, a notice of "no info" and then an optional, +driver-specific error message. + + + +============================================================================ +PCI Bus Parity Detection + + +On Header Type 00 devices the primary status is looked at +for any parity error regardless of whether Parity is enabled on the +device. (The spec indicates parity is generated in some cases). +On Header Type 01 bridges, the secondary status register is also +looked at to see if parity ocurred on the bus on the other side of +the bridge. + + +SYSFS CONFIGURATION + +Under /sys/devices/system/edac/pci are control and attribute files as follows: + + +Enable/Disable PCI Parity checking control file: + + 'check_pci_parity' + + + This control file enables or disables the PCI Bus Parity scanning + operation. Writing a 1 to this file enables the scanning. Writing + a 0 to this file disables the scanning. + + Enable: + echo "1" >/sys/devices/system/edac/pci/check_pci_parity + + Disable: + echo "0" >/sys/devices/system/edac/pci/check_pci_parity + + + +Panic on PCI PARITY Error: + + 'panic_on_pci_parity' + + + This control files enables or disables panic'ing when a parity + error has been detected. + + + module/kernel parameter: panic_on_pci_parity=[0|1] + + Enable: + echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity + + Disable: + echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity + + +Parity Count: + + 'pci_parity_count' + + This attribute file will display the number of parity errors that + have been detected. + + + +PCI Device Whitelist: + + 'pci_parity_whitelist' + + This control file allows for an explicit list of PCI devices to be + scanned for parity errors. Only devices found on this list will + be examined. The list is a line of hexadecimel VENDOR and DEVICE + ID tuples: + + 1022:7450,1434:16a6 + + One or more can be inserted, seperated by a comma. + + To write the above list doing the following as one command line: + + echo "1022:7450,1434:16a6" + > /sys/devices/system/edac/pci/pci_parity_whitelist + + + + To display what the whitelist is, simply 'cat' the same file. + + +PCI Device Blacklist: + + 'pci_parity_blacklist' + + This control file allows for a list of PCI devices to be + skipped for scanning. + The list is a line of hexadecimel VENDOR and DEVICE ID tuples: + + 1022:7450,1434:16a6 + + One or more can be inserted, seperated by a comma. + + To write the above list doing the following as one command line: + + echo "1022:7450,1434:16a6" + > /sys/devices/system/edac/pci/pci_parity_blacklist + + + To display what the whitelist current contatins, + simply 'cat' the same file. + +======================================================================= + +PCI Vendor and Devices IDs can be obtained with the lspci command. Using +the -n option lspci will display the vendor and device IDs. The system +adminstrator will have to determine which devices should be scanned or +skipped. + + + +The two lists (white and black) are prioritized. blacklist is the lower +priority and will NOT be utilized when a whitelist has been set. +Turn OFF a whitelist by an empty echo command: + + echo > /sys/devices/system/edac/pci/pci_parity_whitelist + +and any previous blacklist will be utililzed. + diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b4a1ea762698..b730d765b525 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -148,3 +148,26 @@ Why: The 8250 serial driver now has the ability to deal with the differences brother on Alchemy SOCs. The loss of features is not considered an issue. Who: Ralf Baechle <ralf@linux-mips.org> + +--------------------------- + +What: Legacy /proc/pci interface (PCI_LEGACY_PROC) +When: March 2006 +Why: deprecated since 2.5.53 in favor of lspci(8) +Who: Adrian Bunk <bunk@stusta.de> + +--------------------------- + +What: pci_module_init(driver) +When: January 2007 +Why: Is replaced by pci_register_driver(pci_driver). +Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de> + +--------------------------- + +What: I2C interface of the it87 driver +When: January 2007 +Why: The ISA interface is faster and should be always available. The I2C + probing is also known to cause trouble in at least one case (see + bug #5889.) +Who: Jean Delvare <khali@linux-fr.org> diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c index f3c6e4946f98..3d4713a6c207 100644 --- a/Documentation/filesystems/configfs/configfs_example.c +++ b/Documentation/filesystems/configfs/configfs_example.c @@ -320,6 +320,7 @@ static struct config_item_type simple_children_type = { .ct_item_ops = &simple_children_item_ops, .ct_group_ops = &simple_children_group_ops, .ct_attrs = simple_children_attrs, + .ct_owner = THIS_MODULE, }; static struct configfs_subsystem simple_children_subsys = { @@ -403,6 +404,7 @@ static struct config_item_type group_children_type = { .ct_item_ops = &group_children_item_ops, .ct_group_ops = &group_children_group_ops, .ct_attrs = group_children_attrs, + .ct_owner = THIS_MODULE, }; static struct configfs_subsystem group_children_subsys = { diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index f2595caf052e..4389c684a80a 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt @@ -35,6 +35,7 @@ Features which OCFS2 does not support yet: be cluster coherent. - quotas - cluster aware flock + - cluster aware lockf - Directory change notification (F_NOTIFY) - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease) - POSIX ACLs diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f new file mode 100644 index 000000000000..28c5b7d1eb90 --- /dev/null +++ b/Documentation/hwmon/f71805f @@ -0,0 +1,105 @@ +Kernel driver f71805f +===================== + +Supported chips: + * Fintek F71805F/FG + Prefix: 'f71805f' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Provided by Fintek on request + +Author: Jean Delvare <khali@linux-fr.org> + +Thanks to Denis Kieft from Barracuda Networks for the donation of a +test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and +for providing initial documentation. + +Thanks to Kris Chen from Fintek for answering technical questions and +providing additional documentation. + +Thanks to Chris Lin from Jetway for providing wiring schematics and +anwsering technical questions. + + +Description +----------- + +The Fintek F71805F/FG Super I/O chip includes complete hardware monitoring +capabilities. It can monitor up to 9 voltages (counting its own power +source), 3 fans and 3 temperature sensors. + +This chip also has fan controlling features, using either DC or PWM, in +three different modes (one manual, two automatic). The driver doesn't +support these features yet. + +The driver assumes that no more than one chip is present, which seems +reasonable. + + +Voltage Monitoring +------------------ + +Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported +range is thus from 0 to 2.040 V. Voltage values outside of this range +need external resistors. An exception is in0, which is used to monitor +the chip's own power source (+3.3V), and is divided internally by a +factor 2. + +The two LSB of the voltage limit registers are not used (always 0), so +you can only set the limits in steps of 32 mV (before scaling). + +The wirings and resistor values suggested by Fintek are as follow: + + pin expected + name use R1 R2 divider raw val. + +in0 VCC VCC3.3V int. int. 2.00 1.65 V +in1 VIN1 VTT1.2V 10K - 1.00 1.20 V +in2 VIN2 VRAM 100K 100K 2.00 ~1.25 V (1) +in3 VIN3 VCHIPSET 47K 100K 1.47 2.24 V (2) +in4 VIN4 VCC5V 200K 47K 5.25 0.95 V +in5 VIN5 +12V 200K 20K 11.00 1.05 V +in6 VIN6 VCC1.5V 10K - 1.00 1.50 V +in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1) +in8 VIN8 VSB5V 200K 47K 1.00 0.95 V + +(1) Depends on your hardware setup. +(2) Obviously not correct, swapping R1 and R2 would make more sense. + +These values can be used as hints at best, as motherboard manufacturers +are free to use a completely different setup. As a matter of fact, the +Jetway K8M8MS uses a significantly different setup. You will have to +find out documentation about your own motherboard, and edit sensors.conf +accordingly. + +Each voltage measured has associated low and high limits, each of which +triggers an alarm when crossed. + + +Fan Monitoring +-------------- + +Fan rotation speeds are reported as 12-bit values from a gated clock +signal. Speeds down to 366 RPM can be measured. There is no theoretical +high limit, but values over 6000 RPM seem to cause problem. The effective +resolution is much lower than you would expect, the step between different +register values being 10 rather than 1. + +The chip assumes 2 pulse-per-revolution fans. + +An alarm is triggered if the rotation speed drops below a programmable +limit or is too low to be measured. + + +Temperature Monitoring +---------------------- + +Temperatures are reported in degrees Celsius. Each temperature measured +has a high limit, those crossing triggers an alarm. There is an associated +hysteresis value, below which the temperature has to drop before the +alarm is cleared. + +All temperature channels are external, there is no embedded temperature +sensor. Each channel can be used for connecting either a thermal diode +or a thermistor. The driver reports the currently selected mode, but +doesn't allow changing it. In theory, the BIOS should have configured +everything properly. diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 7f42e441c645..9555be1ed999 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 @@ -9,7 +9,7 @@ Supported chips: http://www.ite.com.tw/ * IT8712F Prefix: 'it8712' - Addresses scanned: I2C 0x28 - 0x2f + Addresses scanned: I2C 0x2d from Super I/O config space (8 I/O ports) Datasheet: Publicly available at the ITE website http://www.ite.com.tw/ diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 764cdc5480e7..a0d0ab24288e 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -179,11 +179,12 @@ temp[1-*]_auto_point[1-*]_temp_hyst **************** temp[1-3]_type Sensor type selection. - Integers 1, 2, 3 or thermistor Beta value (3435) + Integers 1 to 4 or thermistor Beta value (typically 3435) Read/Write. 1: PII/Celeron Diode 2: 3904 transistor 3: thermal diode + 4: thermistor (default/unknown Beta) Not all types are supported by all chips temp[1-4]_max Temperature max value. @@ -261,6 +262,21 @@ alarms Alarm bitmask. of individual bits. Bits are defined in kernel/include/sensors.h. +alarms_in Alarm bitmask relative to in (voltage) channels + Read only + A '1' bit means an alarm, LSB corresponds to in0 and so on + Prefered to 'alarms' for newer chips + +alarms_fan Alarm bitmask relative to fan channels + Read only + A '1' bit means an alarm, LSB corresponds to fan1 and so on + Prefered to 'alarms' for newer chips + +alarms_temp Alarm bitmask relative to temp (temperature) channels + Read only + A '1' bit means an alarm, LSB corresponds to temp1 and so on + Prefered to 'alarms' for newer chips + beep_enable Beep/interrupt enable 0 to disable. 1 to enable. diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis96x index b88953dfd580..00a009b977e9 100644 --- a/Documentation/i2c/busses/i2c-sis69x +++ b/Documentation/i2c/busses/i2c-sis96x @@ -7,7 +7,7 @@ Supported adapters: Any combination of these host bridges: 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746 and these south bridges: - 961, 962, 963(L) + 961, 962, 963(L) Author: Mark M. Hoffman <mhoffman@lightlink.com> @@ -29,7 +29,7 @@ The command "lspci" as root should produce something like these lines: or perhaps this... -00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 +00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961 00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index c406ce67edd0..c65233d430f0 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -45,10 +45,10 @@ How to extract the documentation If you just want to read the ready-made books on the various subsystems (see Documentation/DocBook/*.tmpl), just type 'make -psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your -preference. If you would rather read a different format, you can type -'make sgmldocs' and then use DocBook tools to convert -Documentation/DocBook/*.sgml to a format of your choice (for example, +psdocs', or 'make pdfdocs', or 'make htmldocs', depending on your +preference. If you would rather read a different format, you can type +'make sgmldocs' and then use DocBook tools to convert +Documentation/DocBook/*.sgml to a format of your choice (for example, 'db2html ...' if 'make htmldocs' was not defined). If you want to see man pages instead, you can do this: @@ -124,6 +124,36 @@ patterns, which are highlighted appropriately. Take a look around the source tree for examples. +kernel-doc for structs, unions, enums, and typedefs +--------------------------------------------------- + +Beside functions you can also write documentation for structs, unions, +enums and typedefs. Instead of the function name you must write the name +of the declaration; the struct/union/enum/typedef must always precede +the name. Nesting of declarations is not supported. +Use the argument mechanism to document members or constants. + +Inside a struct description, you can use the "private:" and "public:" +comment tags. Structure fields that are inside a "private:" area +are not listed in the generated output documentation. + +Example: + +/** + * struct my_struct - short description + * @a: first member + * @b: second member + * + * Longer description + */ +struct my_struct { + int a; + int b; +/* private: */ + int c; +}; + + How to make new SGML template files ----------------------------------- @@ -147,4 +177,3 @@ documentation, in <filename>, for the functions listed. Tim. */ <twaugh@redhat.com> - diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1cbcf65b764b..84370363da80 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -452,6 +452,11 @@ running once the system is up. eata= [HW,SCSI] + ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode + Format: <int> + 0: polling mode + non-0: interrupt mode (default) + eda= [HW,PS2] edb= [HW,PS2] diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 2b7cf19a06ad..26364d06ae92 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -427,6 +427,23 @@ icmp_ignore_bogus_error_responses - BOOLEAN will avoid log file clutter. Default: FALSE +icmp_errors_use_inbound_ifaddr - BOOLEAN + + If zero, icmp error messages are sent with the primary address of + the exiting interface. + + If non-zero, the message will be sent with the primary address of + the interface that received the packet that caused the icmp error. + This is the behaviour network many administrators will expect from + a router. And it can make debugging complicated network layouts + much easier. + + Note that if no primary address exists for the interface selected, + then the primary address of the first non-loopback interface that + has one will be used regarldess of this setting. + + Default: 0 + igmp_max_memberships - INTEGER Change the maximum number of multicast groups we can subscribe to. Default: 20 diff --git a/Documentation/parport-lowlevel.txt b/Documentation/parport-lowlevel.txt index 1d40008a1926..8f2302415eff 100644 --- a/Documentation/parport-lowlevel.txt +++ b/Documentation/parport-lowlevel.txt @@ -1068,7 +1068,7 @@ SYNOPSIS struct parport_operations { ... - void (*write_status) (struct parport *port, unsigned char s); + void (*write_control) (struct parport *port, unsigned char s); ... }; @@ -1097,9 +1097,9 @@ SYNOPSIS struct parport_operations { ... - void (*frob_control) (struct parport *port, - unsigned char mask, - unsigned char val); + unsigned char (*frob_control) (struct parport *port, + unsigned char mask, + unsigned char val); ... }; diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt index d089967e4948..634d3e5b5756 100644 --- a/Documentation/pci-error-recovery.txt +++ b/Documentation/pci-error-recovery.txt @@ -1,246 +1,396 @@ PCI Error Recovery ------------------ - May 31, 2005 - - Current document maintainer: - Linas Vepstas <linas@austin.ibm.com> - - -Some PCI bus controllers are able to detect certain "hard" PCI errors -on the bus, such as parity errors on the data and address busses, as -well as SERR and PERR errors. These chipsets are then able to disable -I/O to/from the affected device, so that, for example, a bad DMA -address doesn't end up corrupting system memory. These same chipsets -are also able to reset the affected PCI device, and return it to -working condition. This document describes a generic API form -performing error recovery. - -The core idea is that after a PCI error has been detected, there must -be a way for the kernel to coordinate with all affected device drivers -so that the pci card can be made operational again, possibly after -performing a full electrical #RST of the PCI card. The API below -provides a generic API for device drivers to be notified of PCI -errors, and to be notified of, and respond to, a reset sequence. - -Preliminary sketch of API, cut-n-pasted-n-modified email from -Ben Herrenschmidt, circa 5 april 2005 + February 2, 2006 + + Current document maintainer: + Linas Vepstas <linas@austin.ibm.com> + + +Many PCI bus controllers are able to detect a variety of hardware +PCI errors on the bus, such as parity errors on the data and address +busses, as well as SERR and PERR errors. Some of the more advanced +chipsets are able to deal with these errors; these include PCI-E chipsets, +and the PCI-host bridges found on IBM Power4 and Power5-based pSeries +boxes. A typical action taken is to disconnect the affected device, +halting all I/O to it. The goal of a disconnection is to avoid system +corruption; for example, to halt system memory corruption due to DMA's +to "wild" addresses. Typically, a reconnection mechanism is also +offered, so that the affected PCI device(s) are reset and put back +into working condition. The reset phase requires coordination +between the affected device drivers and the PCI controller chip. +This document describes a generic API for notifying device drivers +of a bus disconnection, and then performing error recovery. +This API is currently implemented in the 2.6.16 and later kernels. + +Reporting and recovery is performed in several steps. First, when +a PCI hardware error has resulted in a bus disconnect, that event +is reported as soon as possible to all affected device drivers, +including multiple instances of a device driver on multi-function +cards. This allows device drivers to avoid deadlocking in spinloops, +waiting for some i/o-space register to change, when it never will. +It also gives the drivers a chance to defer incoming I/O as +needed. + +Next, recovery is performed in several stages. Most of the complexity +is forced by the need to handle multi-function devices, that is, +devices that have multiple device drivers associated with them. +In the first stage, each driver is allowed to indicate what type +of reset it desires, the choices being a simple re-enabling of I/O +or requesting a hard reset (a full electrical #RST of the PCI card). +If any driver requests a full reset, that is what will be done. + +After a full reset and/or a re-enabling of I/O, all drivers are +again notified, so that they may then perform any device setup/config +that may be required. After these have all completed, a final +"resume normal operations" event is sent out. + +The biggest reason for choosing a kernel-based implementation rather +than a user-space implementation was the need to deal with bus +disconnects of PCI devices attached to storage media, and, in particular, +disconnects from devices holding the root file system. If the root +file system is disconnected, a user-space mechanism would have to go +through a large number of contortions to complete recovery. Almost all +of the current Linux file systems are not tolerant of disconnection +from/reconnection to their underlying block device. By contrast, +bus errors are easy to manage in the device driver. Indeed, most +device drivers already handle very similar recovery procedures; +for example, the SCSI-generic layer already provides significant +mechanisms for dealing with SCSI bus errors and SCSI bus resets. + + +Detailed Design +--------------- +Design and implementation details below, based on a chain of +public email discussions with Ben Herrenschmidt, circa 5 April 2005. The error recovery API support is exposed to the driver in the form of a structure of function pointers pointed to by a new field in struct -pci_driver. The absence of this pointer in pci_driver denotes an -"non-aware" driver, behaviour on these is platform dependant. -Platforms like ppc64 can try to simulate pci hotplug remove/add. - -The definition of "pci_error_token" is not covered here. It is based on -Seto's work on the synchronous error detection. We still need to define -functions for extracting infos out of an opaque error token. This is -separate from this API. +pci_driver. A driver that fails to provide the structure is "non-aware", +and the actual recovery steps taken are platform dependent. The +arch/powerpc implementation will simulate a PCI hotplug remove/add. This structure has the form: - struct pci_error_handlers { - int (*error_detected)(struct pci_dev *dev, pci_error_token error); + int (*error_detected)(struct pci_dev *dev, enum pci_channel_state); int (*mmio_enabled)(struct pci_dev *dev); - int (*resume)(struct pci_dev *dev); int (*link_reset)(struct pci_dev *dev); int (*slot_reset)(struct pci_dev *dev); + void (*resume)(struct pci_dev *dev); }; -A driver doesn't have to implement all of these callbacks. The -only mandatory one is error_detected(). If a callback is not -implemented, the corresponding feature is considered unsupported. -For example, if mmio_enabled() and resume() aren't there, then the -driver is assumed as not doing any direct recovery and requires +The possible channel states are: +enum pci_channel_state { + pci_channel_io_normal, /* I/O channel is in normal state */ + pci_channel_io_frozen, /* I/O to channel is blocked */ + pci_channel_io_perm_failure, /* PCI card is dead */ +}; + +Possible return values are: +enum pci_ers_result { + PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */ + PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */ + PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */ + PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */ + PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */ +}; + +A driver does not have to implement all of these callbacks; however, +if it implements any, it must implement error_detected(). If a callback +is not implemented, the corresponding feature is considered unsupported. +For example, if mmio_enabled() and resume() aren't there, then it +is assumed that the driver is not doing any direct recovery and requires a reset. If link_reset() is not implemented, the card is assumed as -not caring about link resets, in which case, if recover is supported, -the core can try recover (but not slot_reset() unless it really did -reset the slot). If slot_reset() is not supported, link_reset() can -be called instead on a slot reset. - -At first, the call will always be : - - 1) error_detected() - - Error detected. This is sent once after an error has been detected. At -this point, the device might not be accessible anymore depending on the -platform (the slot will be isolated on ppc64). The driver may already -have "noticed" the error because of a failing IO, but this is the proper -"synchronisation point", that is, it gives a chance to the driver to -cleanup, waiting for pending stuff (timers, whatever, etc...) to -complete; it can take semaphores, schedule, etc... everything but touch -the device. Within this function and after it returns, the driver +not care about link resets. Typically a driver will want to know about +a slot_reset(). + +The actual steps taken by a platform to recover from a PCI error +event will be platform-dependent, but will follow the general +sequence described below. + +STEP 0: Error Event +------------------- +PCI bus error is detect by the PCI hardware. On powerpc, the slot +is isolated, in that all I/O is blocked: all reads return 0xffffffff, +all writes are ignored. + + +STEP 1: Notification +-------------------- +Platform calls the error_detected() callback on every instance of +every driver affected by the error. + +At this point, the device might not be accessible anymore, depending on +the platform (the slot will be isolated on powerpc). The driver may +already have "noticed" the error because of a failing I/O, but this +is the proper "synchronization point", that is, it gives the driver +a chance to cleanup, waiting for pending stuff (timers, whatever, etc...) +to complete; it can take semaphores, schedule, etc... everything but +touch the device. Within this function and after it returns, the driver shouldn't do any new IOs. Called in task context. This is sort of a "quiesce" point. See note about interrupts at the end of this doc. - Result codes: - - PCIERR_RESULT_CAN_RECOVER: - Driever returns this if it thinks it might be able to recover +All drivers participating in this system must implement this call. +The driver must return one of the following result codes: + - PCI_ERS_RESULT_CAN_RECOVER: + Driver returns this if it thinks it might be able to recover the HW by just banging IOs or if it wants to be given - a chance to extract some diagnostic informations (see - below). - - PCIERR_RESULT_NEED_RESET: - Driver returns this if it thinks it can't recover unless the - slot is reset. - - PCIERR_RESULT_DISCONNECT: - Return this if driver thinks it won't recover at all, - (this will detach the driver ? or just leave it - dangling ? to be decided) - -So at this point, we have called error_detected() for all drivers -on the segment that had the error. On ppc64, the slot is isolated. What -happens now typically depends on the result from the drivers. If all -drivers on the segment/slot return PCIERR_RESULT_CAN_RECOVER, we would -re-enable IOs on the slot (or do nothing special if the platform doesn't -isolate slots) and call 2). If not and we can reset slots, we go to 4), -if neither, we have a dead slot. If it's an hotplug slot, we might -"simulate" reset by triggering HW unplug/replug though. - ->>> Current ppc64 implementation assumes that a device driver will ->>> *not* schedule or semaphore in this routine; the current ppc64 + a chance to extract some diagnostic information (see + mmio_enable, below). + - PCI_ERS_RESULT_NEED_RESET: + Driver returns this if it can't recover without a hard + slot reset. + - PCI_ERS_RESULT_DISCONNECT: + Driver returns this if it doesn't want to recover at all. + +The next step taken will depend on the result codes returned by the +drivers. + +If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER, +then the platform should re-enable IOs on the slot (or do nothing in +particular, if the platform doesn't isolate slots), and recovery +proceeds to STEP 2 (MMIO Enable). + +If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET), +then recovery proceeds to STEP 4 (Slot Reset). + +If the platform is unable to recover the slot, the next step +is STEP 6 (Permanent Failure). + +>>> The current powerpc implementation assumes that a device driver will +>>> *not* schedule or semaphore in this routine; the current powerpc >>> implementation uses one kernel thread to notify all devices; ->>> thus, of one device sleeps/schedules, all devices are affected. +>>> thus, if one device sleeps/schedules, all devices are affected. >>> Doing better requires complex multi-threaded logic in the error >>> recovery implementation (e.g. waiting for all notification threads >>> to "join" before proceeding with recovery.) This seems excessively >>> complex and not worth implementing. ->>> The current ppc64 implementation doesn't much care if the device ->>> attempts i/o at this point, or not. I/O's will fail, returning +>>> The current powerpc implementation doesn't much care if the device +>>> attempts I/O at this point, or not. I/O's will fail, returning >>> a value of 0xff on read, and writes will be dropped. If the device >>> driver attempts more than 10K I/O's to a frozen adapter, it will >>> assume that the device driver has gone into an infinite loop, and ->>> it will panic the the kernel. +>>> it will panic the the kernel. There doesn't seem to be any other +>>> way of stopping a device driver that insists on spinning on I/O. - 2) mmio_enabled() +STEP 2: MMIO Enabled +------------------- +The platform re-enables MMIO to the device (but typically not the +DMA), and then calls the mmio_enabled() callback on all affected +device drivers. - This is the "early recovery" call. IOs are allowed again, but DMA is +This is the "early recovery" call. IOs are allowed again, but DMA is not (hrm... to be discussed, I prefer not), with some restrictions. This is NOT a callback for the driver to start operations again, only to peek/poke at the device, extract diagnostic information, if any, and eventually do things like trigger a device local reset or some such, -but not restart operations. This is sent if all drivers on a segment -agree that they can try to recover and no automatic link reset was -performed by the HW. If the platform can't just re-enable IOs without -a slot reset or a link reset, it doesn't call this callback and goes -directly to 3) or 4). All IOs should be done _synchronously_ from -within this callback, errors triggered by them will be returned via -the normal pci_check_whatever() api, no new error_detected() callback -will be issued due to an error happening here. However, such an error -might cause IOs to be re-blocked for the whole segment, and thus -invalidate the recovery that other devices on the same segment might -have done, forcing the whole segment into one of the next states, -that is link reset or slot reset. - - Result codes: - - PCIERR_RESULT_RECOVERED +but not restart operations. This is callback is made if all drivers on +a segment agree that they can try to recover and if no automatic link reset +was performed by the HW. If the platform can't just re-enable IOs without +a slot reset or a link reset, it wont call this callback, and instead +will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset) + +>>> The following is proposed; no platform implements this yet: +>>> Proposal: All I/O's should be done _synchronously_ from within +>>> this callback, errors triggered by them will be returned via +>>> the normal pci_check_whatever() API, no new error_detected() +>>> callback will be issued due to an error happening here. However, +>>> such an error might cause IOs to be re-blocked for the whole +>>> segment, and thus invalidate the recovery that other devices +>>> on the same segment might have done, forcing the whole segment +>>> into one of the next states, that is, link reset or slot reset. + +The driver should return one of the following result codes: + - PCI_ERS_RESULT_RECOVERED Driver returns this if it thinks the device is fully - functionnal and thinks it is ready to start + functional and thinks it is ready to start normal driver operations again. There is no guarantee that the driver will actually be allowed to proceed, as another driver on the same segment might have failed and thus triggered a slot reset on platforms that support it. - - PCIERR_RESULT_NEED_RESET + - PCI_ERS_RESULT_NEED_RESET Driver returns this if it thinks the device is not recoverable in it's current state and it needs a slot reset to proceed. - - PCIERR_RESULT_DISCONNECT + - PCI_ERS_RESULT_DISCONNECT Same as above. Total failure, no recovery even after reset driver dead. (To be defined more precisely) ->>> The current ppc64 implementation does not implement this callback. +The next step taken depends on the results returned by the drivers. +If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform +proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations). + +If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform +proceeds to STEP 4 (Slot Reset) - 3) link_reset() +>>> The current powerpc implementation does not implement this callback. - This is called after the link has been reset. This is typically -a PCI Express specific state at this point and is done whenever a -non-fatal error has been detected that can be "solved" by resetting -the link. This call informs the driver of the reset and the driver -should check if the device appears to be in working condition. -This function acts a bit like 2) mmio_enabled(), in that the driver -is not supposed to restart normal driver I/O operations right away. -Instead, it should just "probe" the device to check it's recoverability -status. If all is right, then the core will call resume() once all -drivers have ack'd link_reset(). + +STEP 3: Link Reset +------------------ +The platform resets the link, and then calls the link_reset() callback +on all affected device drivers. This is a PCI-Express specific state +and is done whenever a non-fatal error has been detected that can be +"solved" by resetting the link. This call informs the driver of the +reset and the driver should check to see if the device appears to be +in working condition. + +The driver is not supposed to restart normal driver I/O operations +at this point. It should limit itself to "probing" the device to +check it's recoverability status. If all is right, then the platform +will call resume() once all drivers have ack'd link_reset(). Result codes: - (identical to mmio_enabled) + (identical to STEP 3 (MMIO Enabled) + +The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5 +(Resume Operations). + +>>> The current powerpc implementation does not implement this callback. + + +STEP 4: Slot Reset +------------------ +The platform performs a soft or hard reset of the device, and then +calls the slot_reset() callback. + +A soft reset consists of asserting the adapter #RST line and then +restoring the PCI BAR's and PCI configuration header to a state +that is equivalent to what it would be after a fresh system +power-on followed by power-on BIOS/system firmware initialization. +If the platform supports PCI hotplug, then the reset might be +performed by toggling the slot electrical power off/on. ->>> The current ppc64 implementation does not implement this callback. +It is important for the platform to restore the PCI config space +to the "fresh poweron" state, rather than the "last state". After +a slot reset, the device driver will almost always use its standard +device initialization routines, and an unusual config space setup +may result in hung devices, kernel panics, or silent data corruption. - 4) slot_reset() +This call gives drivers the chance to re-initialize the hardware +(re-download firmware, etc.). At this point, the driver may assume +that he card is in a fresh state and is fully functional. In +particular, interrupt generation should work normally. - This is called after the slot has been soft or hard reset by the -platform. A soft reset consists of asserting the adapter #RST line -and then restoring the PCI BARs and PCI configuration header. If the -platform supports PCI hotplug, then it might instead perform a hard -reset by toggling power on the slot off/on. This call gives drivers -the chance to re-initialize the hardware (re-download firmware, etc.), -but drivers shouldn't restart normal I/O processing operations at -this point. (See note about interrupts; interrupts aren't guaranteed -to be delivered until the resume() callback has been called). If all -device drivers report success on this callback, the patform will call -resume() to complete the error handling and let the driver restart -normal I/O processing. +Drivers should not yet restart normal I/O processing operations +at this point. If all device drivers report success on this +callback, the platform will call resume() to complete the sequence, +and let the driver restart normal I/O processing. A driver can still return a critical failure for this function if it can't get the device operational after reset. If the platform -previously tried a soft reset, it migh now try a hard reset (power +previously tried a soft reset, it might now try a hard reset (power cycle) and then call slot_reset() again. It the device still can't be recovered, there is nothing more that can be done; the platform will typically report a "permanent failure" in such a case. The device will be considered "dead" in this case. - Result codes: - - PCIERR_RESULT_DISCONNECT - Same as above. +Drivers for multi-function cards will need to coordinate among +themselves as to which driver instance will perform any "one-shot" +or global device initialization. For example, the Symbios sym53cxx2 +driver performs device init only from PCI function 0: ->>> The current ppc64 implementation does not try a power-cycle reset ->>> if the driver returned PCIERR_RESULT_DISCONNECT. However, it should. ++ if (PCI_FUNC(pdev->devfn) == 0) ++ sym_reset_scsi_bus(np, 0); - 5) resume() - - This is called if all drivers on the segment have returned -PCIERR_RESULT_RECOVERED from one of the 3 prevous callbacks. -That basically tells the driver to restart activity, tht everything -is back and running. No result code is taken into account here. If -a new error happens, it will restart a new error handling process. + Result codes: + - PCI_ERS_RESULT_DISCONNECT + Same as above. -That's it. I think this covers all the possibilities. The way those -callbacks are called is platform policy. A platform with no slot reset -capability for example may want to just "ignore" drivers that can't +Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent +Failure). + +>>> The current powerpc implementation does not currently try a +>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT. +>>> However, it probably should. + + +STEP 5: Resume Operations +------------------------- +The platform will call the resume() callback on all affected device +drivers if all drivers on the segment have returned +PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks. +The goal of this callback is to tell the driver to restart activity, +that everything is back and running. This callback does not return +a result code. + +At this point, if a new error happens, the platform will restart +a new error recovery sequence. + +STEP 6: Permanent Failure +------------------------- +A "permanent failure" has occurred, and the platform cannot recover +the device. The platform will call error_detected() with a +pci_channel_state value of pci_channel_io_perm_failure. + +The device driver should, at this point, assume the worst. It should +cancel all pending I/O, refuse all new I/O, returning -EIO to +higher layers. The device driver should then clean up all of its +memory and remove itself from kernel operations, much as it would +during system shutdown. + +The platform will typically notify the system operator of the +permanent failure in some way. If the device is hotplug-capable, +the operator will probably want to remove and replace the device. +Note, however, not all failures are truly "permanent". Some are +caused by over-heating, some by a poorly seated card. Many +PCI error events are caused by software bugs, e.g. DMA's to +wild addresses or bogus split transactions due to programming +errors. See the discussion in powerpc/eeh-pci-error-recovery.txt +for additional detail on real-life experience of the causes of +software errors. + + +Conclusion; General Remarks +--------------------------- +The way those callbacks are called is platform policy. A platform with +no slot reset capability may want to just "ignore" drivers that can't recover (disconnect them) and try to let other cards on the same segment recover. Keep in mind that in most real life cases, though, there will be only one driver per segment. -Now, there is a note about interrupts. If you get an interrupt and your +Now, a note about interrupts. If you get an interrupt and your device is dead or has been isolated, there is a problem :) - -After much thinking, I decided to leave that to the platform. That is, -the recovery API only precies that: +The current policy is to turn this into a platform policy. +That is, the recovery API only requires that: - There is no guarantee that interrupt delivery can proceed from any device on the segment starting from the error detection and until the -restart callback is sent, at which point interrupts are expected to be +resume callback is sent, at which point interrupts are expected to be fully operational. - - There is no guarantee that interrupt delivery is stopped, that is, ad -river that gets an interrupts after detecting an error, or that detects -and error within the interrupt handler such that it prevents proper + - There is no guarantee that interrupt delivery is stopped, that is, +a driver that gets an interrupt after detecting an error, or that detects +an error within the interrupt handler such that it prevents proper ack'ing of the interrupt (and thus removal of the source) should just -return IRQ_NOTHANDLED. It's up to the platform to deal with taht -condition, typically by masking the irq source during the duration of +return IRQ_NOTHANDLED. It's up to the platform to deal with that +condition, typically by masking the IRQ source during the duration of the error handling. It is expected that the platform "knows" which interrupts are routed to error-management capable slots and can deal -with temporarily disabling that irq number during error processing (this +with temporarily disabling that IRQ number during error processing (this isn't terribly complex). That means some IRQ latency for other devices sharing the interrupt, but there is simply no other way. High end platforms aren't supposed to share interrupts between many devices anyway :) - -Revised: 31 May 2005 Linas Vepstas <linas@austin.ibm.com> +>>> Implementation details for the powerpc platform are discussed in +>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt + +>>> As of this writing, there are six device drivers with patches +>>> implementing error recovery. Not all of these patches are in +>>> mainline yet. These may be used as "examples": +>>> +>>> drivers/scsi/ipr.c +>>> drivers/scsi/sym53cxx_2 +>>> drivers/next/e100.c +>>> drivers/net/e1000 +>>> drivers/net/ixgb +>>> drivers/net/s2io.c + +The End +------- diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt index bd4ffb5bd49a..4117802af0f8 100644 --- a/Documentation/power/interface.txt +++ b/Documentation/power/interface.txt @@ -44,7 +44,7 @@ it. /sys/power/image_size controls the size of the image created by the suspend-to-disk mechanism. It can be written a string representing a non-negative integer that will be used as an upper -limit of the image size, in megabytes. The suspend-to-disk mechanism will +limit of the image size, in bytes. The suspend-to-disk mechanism will do its best to ensure the image size will not exceed that number. However, if this turns out to be impossible, it will try to suspend anyway using the smallest image possible. In particular, if "0" is written to this file, the diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 08c79d4dc540..b28b7f04abb8 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -27,7 +27,7 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state echo platform > /sys/power/disk; echo disk > /sys/power/state -If you want to limit the suspend image size to N megabytes, do +If you want to limit the suspend image size to N bytes, do echo N > /sys/power/image_size diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt new file mode 100644 index 000000000000..d02c64953dcd --- /dev/null +++ b/Documentation/powerpc/booting-without-of.txt @@ -0,0 +1,1486 @@ + Booting the Linux/ppc kernel without Open Firmware + -------------------------------------------------- + + +(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>, + IBM Corp. +(c) 2005 Becky Bruce <becky.bruce at freescale.com>, + Freescale Semiconductor, FSL SOC and 32-bit additions + + May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. + + May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or + clarifies the fact that a lot of things are + optional, the kernel only requires a very + small device tree, though it is encouraged + to provide an as complete one as possible. + + May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM + - Misc fixes + - Define version 3 and new format version 16 + for the DT block (version 16 needs kernel + patches, will be fwd separately). + String block now has a size, and full path + is replaced by unit name for more + compactness. + linux,phandle is made optional, only nodes + that are referenced by other nodes need it. + "name" property is now automatically + deduced from the unit name + + June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and + OF_DT_END_NODE in structure definition. + - Change version 16 format to always align + property data to 4 bytes. Since tokens are + already aligned, that means no specific + required alignement between property size + and property data. The old style variable + alignment would make it impossible to do + "simple" insertion of properties using + memove (thanks Milton for + noticing). Updated kernel patch as well + - Correct a few more alignement constraints + - Add a chapter about the device-tree + compiler and the textural representation of + the tree that can be "compiled" by dtc. + + November 21, 2005: Rev 0.5 + - Additions/generalizations for 32-bit + - Changed to reflect the new arch/powerpc + structure + - Added chapter VI + + + ToDo: + - Add some definitions of interrupt tree (simple/complex) + - Add some definitions for pci host bridges + - Add some common address format examples + - Add definitions for standard properties and "compatible" + names for cells that are not already defined by the existing + OF spec. + - Compare FSL SOC use of PCI to standard and make sure no new + node definition required. + - Add more information about node definitions for SOC devices + that currently have no standard, like the FSL CPM. + + +I - Introduction +================ + +During the recent development of the Linux/ppc64 kernel, and more +specifically, the addition of new platform types outside of the old +IBM pSeries/iSeries pair, it was decided to enforce some strict rules +regarding the kernel entry and bootloader <-> kernel interfaces, in +order to avoid the degeneration that had become the ppc32 kernel entry +point and the way a new platform should be added to the kernel. The +legacy iSeries platform breaks those rules as it predates this scheme, +but no new board support will be accepted in the main tree that +doesn't follows them properly. In addition, since the advent of the +arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit +platforms and 32-bit platforms which move into arch/powerpc will be +required to use these rules as well. + +The main requirement that will be defined in more detail below is +the presence of a device-tree whose format is defined after Open +Firmware specification. However, in order to make life easier +to embedded board vendors, the kernel doesn't require the device-tree +to represent every device in the system and only requires some nodes +and properties to be present. This will be described in detail in +section III, but, for example, the kernel does not require you to +create a node for every PCI device in the system. It is a requirement +to have a node for PCI host bridges in order to provide interrupt +routing informations and memory/IO ranges, among others. It is also +recommended to define nodes for on chip devices and other busses that +don't specifically fit in an existing OF specification. This creates a +great flexibility in the way the kernel can then probe those and match +drivers to device, without having to hard code all sorts of tables. It +also makes it more flexible for board vendors to do minor hardware +upgrades without significantly impacting the kernel code or cluttering +it with special cases. + + +1) Entry point for arch/powerpc +------------------------------- + + There is one and one single entry point to the kernel, at the start + of the kernel image. That entry point supports two calling + conventions: + + a) Boot from Open Firmware. If your firmware is compatible + with Open Firmware (IEEE 1275) or provides an OF compatible + client interface API (support for "interpret" callback of + forth words isn't required), you can enter the kernel with: + + r5 : OF callback pointer as defined by IEEE 1275 + bindings to powerpc. Only the 32 bit client interface + is currently supported + + r3, r4 : address & length of an initrd if any or 0 + + The MMU is either on or off; the kernel will run the + trampoline located in arch/powerpc/kernel/prom_init.c to + extract the device-tree and other information from open + firmware and build a flattened device-tree as described + in b). prom_init() will then re-enter the kernel using + the second method. This trampoline code runs in the + context of the firmware, which is supposed to handle all + exceptions during that time. + + b) Direct entry with a flattened device-tree block. This entry + point is called by a) after the OF trampoline and can also be + called directly by a bootloader that does not support the Open + Firmware client interface. It is also used by "kexec" to + implement "hot" booting of a new kernel from a previous + running one. This method is what I will describe in more + details in this document, as method a) is simply standard Open + Firmware, and thus should be implemented according to the + various standard documents defining it and its binding to the + PowerPC platform. The entry point definition then becomes: + + r3 : physical pointer to the device-tree block + (defined in chapter II) in RAM + + r4 : physical pointer to the kernel itself. This is + used by the assembly code to properly disable the MMU + in case you are entering the kernel with MMU enabled + and a non-1:1 mapping. + + r5 : NULL (as to differenciate with method a) + + Note about SMP entry: Either your firmware puts your other + CPUs in some sleep loop or spin loop in ROM where you can get + them out via a soft reset or some other means, in which case + you don't need to care, or you'll have to enter the kernel + with all CPUs. The way to do that with method b) will be + described in a later revision of this document. + + +2) Board support +---------------- + +64-bit kernels: + + Board supports (platforms) are not exclusive config options. An + arbitrary set of board supports can be built in a single kernel + image. The kernel will "know" what set of functions to use for a + given platform based on the content of the device-tree. Thus, you + should: + + a) add your platform support as a _boolean_ option in + arch/powerpc/Kconfig, following the example of PPC_PSERIES, + PPC_PMAC and PPC_MAPLE. The later is probably a good + example of a board support to start from. + + b) create your main platform file as + "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it + to the Makefile under the condition of your CONFIG_ + option. This file will define a structure of type "ppc_md" + containing the various callbacks that the generic code will + use to get to your platform specific code + + c) Add a reference to your "ppc_md" structure in the + "machines" table in arch/powerpc/kernel/setup_64.c if you are + a 64-bit platform. + + d) request and get assigned a platform number (see PLATFORM_* + constants in include/asm-powerpc/processor.h + +32-bit embedded kernels: + + Currently, board support is essentially an exclusive config option. + The kernel is configured for a single platform. Part of the reason + for this is to keep kernels on embedded systems small and efficient; + part of this is due to the fact the code is already that way. In the + future, a kernel may support multiple platforms, but only if the + platforms feature the same core architectire. A single kernel build + cannot support both configurations with Book E and configurations + with classic Powerpc architectures. + + 32-bit embedded platforms that are moved into arch/powerpc using a + flattened device tree should adopt the merged tree practice of + setting ppc_md up dynamically, even though the kernel is currently + built with support for only a single platform at a time. This allows + unification of the setup code, and will make it easier to go to a + multiple-platform-support model in the future. + +NOTE: I believe the above will be true once Ben's done with the merge +of the boot sequences.... someone speak up if this is wrong! + + To add a 32-bit embedded platform support, follow the instructions + for 64-bit platforms above, with the exception that the Kconfig + option should be set up such that the kernel builds exclusively for + the platform selected. The processor type for the platform should + enable another config option to select the specific board + supported. + +NOTE: If ben doesn't merge the setup files, may need to change this to +point to setup_32.c + + + I will describe later the boot process and various callbacks that + your platform should implement. + + +II - The DT block format +======================== + + +This chapter defines the actual format of the flattened device-tree +passed to the kernel. The actual content of it and kernel requirements +are described later. You can find example of code manipulating that +format in various places, including arch/powerpc/kernel/prom_init.c +which will generate a flattened device-tree from the Open Firmware +representation, or the fs2dt utility which is part of the kexec tools +which will generate one from a filesystem representation. It is +expected that a bootloader like uboot provides a bit more support, +that will be discussed later as well. + +Note: The block has to be in main memory. It has to be accessible in +both real mode and virtual mode with no mapping other than main +memory. If you are writing a simple flash bootloader, it should copy +the block to RAM before passing it to the kernel. + + +1) Header +--------- + + The kernel is entered with r3 pointing to an area of memory that is + roughtly described in include/asm-powerpc/prom.h by the structure + boot_param_header: + +struct boot_param_header { + u32 magic; /* magic word OF_DT_HEADER */ + u32 totalsize; /* total size of DT block */ + u32 off_dt_struct; /* offset to structure */ + u32 off_dt_strings; /* offset to strings */ + u32 off_mem_rsvmap; /* offset to memory reserve map +*/ + u32 version; /* format version */ + u32 last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + u32 boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + u32 size_dt_strings; /* size of the strings block */ +}; + + Along with the constants: + +/* Definitions used by the flattened device tree */ +#define OF_DT_HEADER 0xd00dfeed /* 4: version, + 4: total size */ +#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name +*/ +#define OF_DT_END_NODE 0x2 /* End node */ +#define OF_DT_PROP 0x3 /* Property: name off, + size, content */ +#define OF_DT_END 0x9 + + All values in this header are in big endian format, the various + fields in this header are defined more precisely below. All + "offset" values are in bytes from the start of the header; that is + from the value of r3. + + - magic + + This is a magic value that "marks" the beginning of the + device-tree block header. It contains the value 0xd00dfeed and is + defined by the constant OF_DT_HEADER + + - totalsize + + This is the total size of the DT block including the header. The + "DT" block should enclose all data structures defined in this + chapter (who are pointed to by offsets in this header). That is, + the device-tree structure, strings, and the memory reserve map. + + - off_dt_struct + + This is an offset from the beginning of the header to the start + of the "structure" part the device tree. (see 2) device tree) + + - off_dt_strings + + This is an offset from the beginning of the header to the start + of the "strings" part of the device-tree + + - off_mem_rsvmap + + This is an offset from the beginning of the header to the start + of the reserved memory map. This map is a list of pairs of 64 + bit integers. Each pair is a physical address and a size. The + + list is terminated by an entry of size 0. This map provides the + kernel with a list of physical memory areas that are "reserved" + and thus not to be used for memory allocations, especially during + early initialization. The kernel needs to allocate memory during + boot for things like un-flattening the device-tree, allocating an + MMU hash table, etc... Those allocations must be done in such a + way to avoid overriding critical things like, on Open Firmware + capable machines, the RTAS instance, or on some pSeries, the TCE + tables used for the iommu. Typically, the reserve map should + contain _at least_ this DT block itself (header,total_size). If + you are passing an initrd to the kernel, you should reserve it as + well. You do not need to reserve the kernel image itself. The map + should be 64 bit aligned. + + - version + + This is the version of this structure. Version 1 stops + here. Version 2 adds an additional field boot_cpuid_phys. + Version 3 adds the size of the strings block, allowing the kernel + to reallocate it easily at boot and free up the unused flattened + structure after expansion. Version 16 introduces a new more + "compact" format for the tree itself that is however not backward + compatible. You should always generate a structure of the highest + version defined at the time of your implementation. Currently + that is version 16, unless you explicitely aim at being backward + compatible. + + - last_comp_version + + Last compatible version. This indicates down to what version of + the DT block you are backward compatible. For example, version 2 + is backward compatible with version 1 (that is, a kernel build + for version 1 will be able to boot with a version 2 format). You + should put a 1 in this field if you generate a device tree of + version 1 to 3, or 0x10 if you generate a tree of version 0x10 + using the new unit name format. + + - boot_cpuid_phys + + This field only exist on version 2 headers. It indicate which + physical CPU ID is calling the kernel entry point. This is used, + among others, by kexec. If you are on an SMP system, this value + should match the content of the "reg" property of the CPU node in + the device-tree corresponding to the CPU calling the kernel entry + point (see further chapters for more informations on the required + device-tree contents) + + + So the typical layout of a DT block (though the various parts don't + need to be in that order) looks like this (addresses go from top to + bottom): + + + ------------------------------ + r3 -> | struct boot_param_header | + ------------------------------ + | (alignment gap) (*) | + ------------------------------ + | memory reserve map | + ------------------------------ + | (alignment gap) | + ------------------------------ + | | + | device-tree structure | + | | + ------------------------------ + | (alignment gap) | + ------------------------------ + | | + | device-tree strings | + | | + -----> ------------------------------ + | + | + --- (r3 + totalsize) + + (*) The alignment gaps are not necessarily present; their presence + and size are dependent on the various alignment requirements of + the individual data blocks. + + +2) Device tree generalities +--------------------------- + +This device-tree itself is separated in two different blocks, a +structure block and a strings block. Both need to be aligned to a 4 +byte boundary. + +First, let's quickly describe the device-tree concept before detailing +the storage format. This chapter does _not_ describe the detail of the +required types of nodes & properties for the kernel, this is done +later in chapter III. + +The device-tree layout is strongly inherited from the definition of +the Open Firmware IEEE 1275 device-tree. It's basically a tree of +nodes, each node having two or more named properties. A property can +have a value or not. + +It is a tree, so each node has one and only one parent except for the +root node who has no parent. + +A node has 2 names. The actual node name is generally contained in a +property of type "name" in the node property list whose value is a +zero terminated string and is mandatory for version 1 to 3 of the +format definition (as it is in Open Firmware). Version 0x10 makes it +optional as it can generate it from the unit name defined below. + +There is also a "unit name" that is used to differenciate nodes with +the same name at the same level, it is usually made of the node +name's, the "@" sign, and a "unit address", which definition is +specific to the bus type the node sits on. + +The unit name doesn't exist as a property per-se but is included in +the device-tree structure. It is typically used to represent "path" in +the device-tree. More details about the actual format of these will be +below. + +The kernel powerpc generic code does not make any formal use of the +unit address (though some board support code may do) so the only real +requirement here for the unit address is to ensure uniqueness of +the node unit name at a given level of the tree. Nodes with no notion +of address and no possible sibling of the same name (like /memory or +/cpus) may omit the unit address in the context of this specification, +or use the "@0" default unit address. The unit name is used to define +a node "full path", which is the concatenation of all parent node +unit names separated with "/". + +The root node doesn't have a defined name, and isn't required to have +a name property either if you are using version 3 or earlier of the +format. It also has no unit address (no @ symbol followed by a unit +address). The root node unit name is thus an empty string. The full +path to the root node is "/". + +Every node which actually represents an actual device (that is, a node +which isn't only a virtual "container" for more nodes, like "/cpus" +is) is also required to have a "device_type" property indicating the +type of node . + +Finally, every node that can be referenced from a property in another +node is required to have a "linux,phandle" property. Real open +firmware implementations provide a unique "phandle" value for every +node that the "prom_init()" trampoline code turns into +"linux,phandle" properties. However, this is made optional if the +flattened device tree is used directly. An example of a node +referencing another node via "phandle" is when laying out the +interrupt tree which will be described in a further version of this +document. + +This "linux, phandle" property is a 32 bit value that uniquely +identifies a node. You are free to use whatever values or system of +values, internal pointers, or whatever to generate these, the only +requirement is that every node for which you provide that property has +a unique value for it. + +Here is an example of a simple device-tree. In this example, an "o" +designates a node followed by the node unit name. Properties are +presented with their name followed by their content. "content" +represents an ASCII string (zero terminated) value, while <content> +represents a 32 bit hexadecimal value. The various nodes in this +example will be discussed in a later chapter. At this point, it is +only meant to give you a idea of what a device-tree looks like. I have +purposefully kept the "name" and "linux,phandle" properties which +aren't necessary in order to give you a better idea of what the tree +looks like in practice. + + / o device-tree + |- name = "device-tree" + |- model = "MyBoardName" + |- compatible = "MyBoardFamilyName" + |- #address-cells = <2> + |- #size-cells = <2> + |- linux,phandle = <0> + | + o cpus + | | - name = "cpus" + | | - linux,phandle = <1> + | | - #address-cells = <1> + | | - #size-cells = <0> + | | + | o PowerPC,970@0 + | |- name = "PowerPC,970" + | |- device_type = "cpu" + | |- reg = <0> + | |- clock-frequency = <5f5e1000> + | |- linux,boot-cpu + | |- linux,phandle = <2> + | + o memory@0 + | |- name = "memory" + | |- device_type = "memory" + | |- reg = <00000000 00000000 00000000 20000000> + | |- linux,phandle = <3> + | + o chosen + |- name = "chosen" + |- bootargs = "root=/dev/sda2" + |- linux,platform = <00000600> + |- linux,phandle = <4> + +This tree is almost a minimal tree. It pretty much contains the +minimal set of required nodes and properties to boot a linux kernel; +that is, some basic model informations at the root, the CPUs, and the +physical memory layout. It also includes misc information passed +through /chosen, like in this example, the platform type (mandatory) +and the kernel command line arguments (optional). + +The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a +property without a value. All other properties have a value. The +significance of the #address-cells and #size-cells properties will be +explained in chapter IV which defines precisely the required nodes and +properties and their content. + + +3) Device tree "structure" block + +The structure of the device tree is a linearized tree structure. The +"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE" +ends that node definition. Child nodes are simply defined before +"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 +bit value. The tree has to be "finished" with a OF_DT_END token + +Here's the basic structure of a single node: + + * token OF_DT_BEGIN_NODE (that is 0x00000001) + * for version 1 to 3, this is the node full path as a zero + terminated string, starting with "/". For version 16 and later, + this is the node unit name only (or an empty string for the + root node) + * [align gap to next 4 bytes boundary] + * for each property: + * token OF_DT_PROP (that is 0x00000003) + * 32 bit value of property value size in bytes (or 0 of no + * value) + * 32 bit value of offset in string block of property name + * property value data if any + * [align gap to next 4 bytes boundary] + * [child nodes if any] + * token OF_DT_END_NODE (that is 0x00000002) + +So the node content can be summmarised as a start token, a full path, +a list of properties, a list of child node and an end token. Every +child node is a full node structure itself as defined above. + +4) Device tree 'strings" block + +In order to save space, property names, which are generally redundant, +are stored separately in the "strings" block. This block is simply the +whole bunch of zero terminated strings for all property names +concatenated together. The device-tree property definitions in the +structure block will contain offset values from the beginning of the +strings block. + + +III - Required content of the device tree +========================================= + +WARNING: All "linux,*" properties defined in this document apply only +to a flattened device-tree. If your platform uses a real +implementation of Open Firmware or an implementation compatible with +the Open Firmware client interface, those properties will be created +by the trampoline code in the kernel's prom_init() file. For example, +that's where you'll have to add code to detect your board model and +set the platform number. However, when using the flatenned device-tree +entry point, there is no prom_init() pass, and thus you have to +provide those properties yourself. + + +1) Note about cells and address representation +---------------------------------------------- + +The general rule is documented in the various Open Firmware +documentations. If you chose to describe a bus with the device-tree +and there exist an OF bus binding, then you should follow the +specification. However, the kernel does not require every single +device or bus to be described by the device tree. + +In general, the format of an address for a device is defined by the +parent bus type, based on the #address-cells and #size-cells +property. In the absence of such a property, the parent's parent +values are used, etc... The kernel requires the root node to have +those properties defining addresses format for devices directly mapped +on the processor bus. + +Those 2 properties define 'cells' for representing an address and a +size. A "cell" is a 32 bit number. For example, if both contain 2 +like the example tree given above, then an address and a size are both +composed of 2 cells, and each is a 64 bit number (cells are +concatenated and expected to be in big endian format). Another example +is the way Apple firmware defines them, with 2 cells for an address +and one cell for a size. Most 32-bit implementations should define +#address-cells and #size-cells to 1, which represents a 32-bit value. +Some 32-bit processors allow for physical addresses greater than 32 +bits; these processors should define #address-cells as 2. + +"reg" properties are always a tuple of the type "address size" where +the number of cells of address and size is specified by the bus +#address-cells and #size-cells. When a bus supports various address +spaces and other flags relative to a given address allocation (like +prefetchable, etc...) those flags are usually added to the top level +bits of the physical address. For example, a PCI physical address is +made of 3 cells, the bottom two containing the actual address itself +while the top cell contains address space indication, flags, and pci +bus & device numbers. + +For busses that support dynamic allocation, it's the accepted practice +to then not provide the address in "reg" (keep it 0) though while +providing a flag indicating the address is dynamically allocated, and +then, to provide a separate "assigned-addresses" property that +contains the fully allocated addresses. See the PCI OF bindings for +details. + +In general, a simple bus with no address space bits and no dynamic +allocation is preferred if it reflects your hardware, as the existing +kernel address parsing functions will work out of the box. If you +define a bus type with a more complex address format, including things +like address space bits, you'll have to add a bus translator to the +prom_parse.c file of the recent kernels for your bus type. + +The "reg" property only defines addresses and sizes (if #size-cells +is +non-0) within a given bus. In order to translate addresses upward +(that is into parent bus addresses, and possibly into cpu physical +addresses), all busses must contain a "ranges" property. If the +"ranges" property is missing at a given level, it's assumed that +translation isn't possible. The format of the "ranges" proprety for a +bus is a list of: + + bus address, parent bus address, size + +"bus address" is in the format of the bus this bus node is defining, +that is, for a PCI bridge, it would be a PCI address. Thus, (bus +address, size) defines a range of addresses for child devices. "parent +bus address" is in the format of the parent bus of this bus. For +example, for a PCI host controller, that would be a CPU address. For a +PCI<->ISA bridge, that would be a PCI address. It defines the base +address in the parent bus where the beginning of that range is mapped. + +For a new 64 bit powerpc board, I recommend either the 2/2 format or +Apple's 2/1 format which is slightly more compact since sizes usually +fit in a single 32 bit word. New 32 bit powerpc boards should use a +1/1 format, unless the processor supports physical addresses greater +than 32-bits, in which case a 2/1 format is recommended. + + +2) Note about "compatible" properties +------------------------------------- + +These properties are optional, but recommended in devices and the root +node. The format of a "compatible" property is a list of concatenated +zero terminated strings. They allow a device to express its +compatibility with a family of similar devices, in some cases, +allowing a single driver to match against several devices regardless +of their actual names. + +3) Note about "name" properties +------------------------------- + +While earlier users of Open Firmware like OldWorld macintoshes tended +to use the actual device name for the "name" property, it's nowadays +considered a good practice to use a name that is closer to the device +class (often equal to device_type). For example, nowadays, ethernet +controllers are named "ethernet", an additional "model" property +defining precisely the chip type/model, and "compatible" property +defining the family in case a single driver can driver more than one +of these chips. However, the kernel doesn't generally put any +restriction on the "name" property; it is simply considered good +practice to follow the standard and its evolutions as closely as +possible. + +Note also that the new format version 16 makes the "name" property +optional. If it's absent for a node, then the node's unit name is then +used to reconstruct the name. That is, the part of the unit name +before the "@" sign is used (or the entire unit name if no "@" sign +is present). + +4) Note about node and property names and character set +------------------------------------------------------- + +While open firmware provides more flexibe usage of 8859-1, this +specification enforces more strict rules. Nodes and properties should +be comprised only of ASCII characters 'a' to 'z', '0' to +'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally +allow uppercase characters 'A' to 'Z' (property names should be +lowercase. The fact that vendors like Apple don't respect this rule is +irrelevant here). Additionally, node and property names should always +begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node +names). + +The maximum number of characters for both nodes and property names +is 31. In the case of node names, this is only the leftmost part of +a unit name (the pure "name" property), it doesn't include the unit +address which can extend beyond that limit. + + +5) Required nodes and properties +-------------------------------- + These are all that are currently required. However, it is strongly + recommended that you expose PCI host bridges as documented in the + PCI binding to open firmware, and your interrupt tree as documented + in OF interrupt tree specification. + + a) The root node + + The root node requires some properties to be present: + + - model : this is your board name/model + - #address-cells : address representation for "root" devices + - #size-cells: the size representation for "root" devices + + Additionally, some recommended properties are: + + - compatible : the board "family" generally finds its way here, + for example, if you have 2 board models with a similar layout, + that typically get driven by the same platform code in the + kernel, you would use a different "model" property but put a + value in "compatible". The kernel doesn't directly use that + value (see /chosen/linux,platform for how the kernel choses a + platform type) but it is generally useful. + + The root node is also generally where you add additional properties + specific to your board like the serial number if any, that sort of + thing. it is recommended that if you add any "custom" property whose + name may clash with standard defined ones, you prefix them with your + vendor name and a comma. + + b) The /cpus node + + This node is the parent of all individual CPU nodes. It doesn't + have any specific requirements, though it's generally good practice + to have at least: + + #address-cells = <00000001> + #size-cells = <00000000> + + This defines that the "address" for a CPU is a single cell, and has + no meaningful size. This is not necessary but the kernel will assume + that format when reading the "reg" properties of a CPU node, see + below + + c) The /cpus/* nodes + + So under /cpus, you are supposed to create a node for every CPU on + the machine. There is no specific restriction on the name of the + CPU, though It's common practice to call it PowerPC,<name>. For + example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX. + + Required properties: + + - device_type : has to be "cpu" + - reg : This is the physical cpu number, it's a single 32 bit cell + and is also used as-is as the unit number for constructing the + unit name in the full path. For example, with 2 CPUs, you would + have the full path: + /cpus/PowerPC,970FX@0 + /cpus/PowerPC,970FX@1 + (unit addresses do not require leading zeroes) + - d-cache-line-size : one cell, L1 data cache line size in bytes + - i-cache-line-size : one cell, L1 instruction cache line size in + bytes + - d-cache-size : one cell, size of L1 data cache in bytes + - i-cache-size : one cell, size of L1 instruction cache in bytes + - linux, boot-cpu : Should be defined if this cpu is the boot cpu. + + Recommended properties: + + - timebase-frequency : a cell indicating the frequency of the + timebase in Hz. This is not directly used by the generic code, + but you are welcome to copy/paste the pSeries code for setting + the kernel timebase/decrementer calibration based on this + value. + - clock-frequency : a cell indicating the CPU core clock frequency + in Hz. A new property will be defined for 64 bit values, but if + your frequency is < 4Ghz, one cell is enough. Here as well as + for the above, the common code doesn't use that property, but + you are welcome to re-use the pSeries or Maple one. A future + kernel version might provide a common function for this. + + You are welcome to add any property you find relevant to your board, + like some information about the mechanism used to soft-reset the + CPUs. For example, Apple puts the GPIO number for CPU soft reset + lines in there as a "soft-reset" property since they start secondary + CPUs by soft-resetting them. + + + d) the /memory node(s) + + To define the physical memory layout of your board, you should + create one or more memory node(s). You can either create a single + node with all memory ranges in its reg property, or you can create + several nodes, as you wish. The unit address (@ part) used for the + full path is the address of the first range of memory defined by a + given node. If you use a single memory node, this will typically be + @0. + + Required properties: + + - device_type : has to be "memory" + - reg : This property contains all the physical memory ranges of + your board. It's a list of addresses/sizes concatenated + together, with the number of cells of each defined by the + #address-cells and #size-cells of the root node. For example, + with both of these properties beeing 2 like in the example given + earlier, a 970 based machine with 6Gb of RAM could typically + have a "reg" property here that looks like: + + 00000000 00000000 00000000 80000000 + 00000001 00000000 00000001 00000000 + + That is a range starting at 0 of 0x80000000 bytes and a range + starting at 0x100000000 and of 0x100000000 bytes. You can see + that there is no memory covering the IO hole between 2Gb and + 4Gb. Some vendors prefer splitting those ranges into smaller + segments, but the kernel doesn't care. + + e) The /chosen node + + This node is a bit "special". Normally, that's where open firmware + puts some variable environment information, like the arguments, or + phandle pointers to nodes like the main interrupt controller, or the + default input/output devices. + + This specification makes a few of these mandatory, but also defines + some linux-specific properties that would be normally constructed by + the prom_init() trampoline when booting with an OF client interface, + but that you have to provide yourself when using the flattened format. + + Required properties: + + - linux,platform : This is your platform number as assigned by the + architecture maintainers + + Recommended properties: + + - bootargs : This zero-terminated string is passed as the kernel + command line + - linux,stdout-path : This is the full path to your standard + console device if any. Typically, if you have serial devices on + your board, you may want to put the full path to the one set as + the default console in the firmware here, for the kernel to pick + it up as it's own default console. If you look at the funciton + set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see + that the kernel tries to find out the default console and has + knowledge of various types like 8250 serial ports. You may want + to extend this function to add your own. + - interrupt-controller : This is one cell containing a phandle + value that matches the "linux,phandle" property of your main + interrupt controller node. May be used for interrupt routing. + + + Note that u-boot creates and fills in the chosen node for platforms + that use it. + + f) the /soc<SOCname> node + + This node is used to represent a system-on-a-chip (SOC) and must be + present if the processor is a SOC. The top-level soc node contains + information that is global to all devices on the SOC. The node name + should contain a unit address for the SOC, which is the base address + of the memory-mapped register set for the SOC. The name of an soc + node should start with "soc", and the remainder of the name should + represent the part number for the soc. For example, the MPC8540's + soc node would be called "soc8540". + + Required properties: + + - device_type : Should be "soc" + - ranges : Should be defined as specified in 1) to describe the + translation of SOC addresses for memory mapped SOC registers. + - bus-frequency: Contains the bus frequency for the SOC node. + Typically, the value of this field is filled in by the boot + loader. + + + Recommended properties: + + - reg : This property defines the address and size of the + memory-mapped registers that are used for the SOC node itself. + It does not include the child device registers - these will be + defined inside each child node. The address specified in the + "reg" property should match the unit address of the SOC node. + - #address-cells : Address representation for "soc" devices. The + format of this field may vary depending on whether or not the + device registers are memory mapped. For memory mapped + registers, this field represents the number of cells needed to + represent the address of the registers. For SOCs that do not + use MMIO, a special address format should be defined that + contains enough cells to represent the required information. + See 1) above for more details on defining #address-cells. + - #size-cells : Size representation for "soc" devices + - #interrupt-cells : Defines the width of cells used to represent + interrupts. Typically this value is <2>, which includes a + 32-bit number that represents the interrupt number, and a + 32-bit number that represents the interrupt sense and level. + This field is only needed if the SOC contains an interrupt + controller. + + The SOC node may contain child nodes for each SOC device that the + platform uses. Nodes should not be created for devices which exist + on the SOC but are not used by a particular platform. See chapter VI + for more information on how to specify devices that are part of an +SOC. + + Example SOC node for the MPC8540: + + soc8540@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <00000000 e0000000 00100000> + reg = <e0000000 00003000>; + bus-frequency = <0>; + } + + + +IV - "dtc", the device tree compiler +==================================== + + +dtc source code can be found at +<http://ozlabs.org/~dgibson/dtc/dtc.tar.gz> + +WARNING: This version is still in early development stage; the +resulting device-tree "blobs" have not yet been validated with the +kernel. The current generated bloc lacks a useful reserve map (it will +be fixed to generate an empty one, it's up to the bootloader to fill +it up) among others. The error handling needs work, bugs are lurking, +etc... + +dtc basically takes a device-tree in a given format and outputs a +device-tree in another format. The currently supported formats are: + + Input formats: + ------------- + + - "dtb": "blob" format, that is a flattened device-tree block + with + header all in a binary blob. + - "dts": "source" format. This is a text file containing a + "source" for a device-tree. The format is defined later in this + chapter. + - "fs" format. This is a representation equivalent to the + output of /proc/device-tree, that is nodes are directories and + properties are files + + Output formats: + --------------- + + - "dtb": "blob" format + - "dts": "source" format + - "asm": assembly language file. This is a file that can be + sourced by gas to generate a device-tree "blob". That file can + then simply be added to your Makefile. Additionally, the + assembly file exports some symbols that can be use + + +The syntax of the dtc tool is + + dtc [-I <input-format>] [-O <output-format>] + [-o output-filename] [-V output_version] input_filename + + +The "output_version" defines what versio of the "blob" format will be +generated. Supported versions are 1,2,3 and 16. The default is +currently version 3 but that may change in the future to version 16. + +Additionally, dtc performs various sanity checks on the tree, like the +uniqueness of linux,phandle properties, validity of strings, etc... + +The format of the .dts "source" file is "C" like, supports C and C++ +style commments. + +/ { +} + +The above is the "device-tree" definition. It's the only statement +supported currently at the toplevel. + +/ { + property1 = "string_value"; /* define a property containing a 0 + * terminated string + */ + + property2 = <1234abcd>; /* define a property containing a + * numerical 32 bits value (hexadecimal) + */ + + property3 = <12345678 12345678 deadbeef>; + /* define a property containing 3 + * numerical 32 bits values (cells) in + * hexadecimal + */ + property4 = [0a 0b 0c 0d de ea ad be ef]; + /* define a property whose content is + * an arbitrary array of bytes + */ + + childnode@addresss { /* define a child node named "childnode" + * whose unit name is "childnode at + * address" + */ + + childprop = "hello\n"; /* define a property "childprop" of + * childnode (in this case, a string) + */ + }; +}; + +Nodes can contain other nodes etc... thus defining the hierarchical +structure of the tree. + +Strings support common escape sequences from C: "\n", "\t", "\r", +"\(octal value)", "\x(hex value)". + +It is also suggested that you pipe your source file through cpp (gcc +preprocessor) so you can use #include's, #define for constants, etc... + +Finally, various options are planned but not yet implemented, like +automatic generation of phandles, labels (exported to the asm file so +you can point to a property content and change it easily from whatever +you link the device-tree with), label or path instead of numeric value +in some cells to "point" to a node (replaced by a phandle at compile +time), export of reserve map address to the asm file, ability to +specify reserve map content at compile time, etc... + +We may provide a .h include file with common definitions of that +proves useful for some properties (like building PCI properties or +interrupt maps) though it may be better to add a notion of struct +definitions to the compiler... + + +V - Recommendations for a bootloader +==================================== + + +Here are some various ideas/recommendations that have been proposed +while all this has been defined and implemented. + + - The bootloader may want to be able to use the device-tree itself + and may want to manipulate it (to add/edit some properties, + like physical memory size or kernel arguments). At this point, 2 + choices can be made. Either the bootloader works directly on the + flattened format, or the bootloader has its own internal tree + representation with pointers (similar to the kernel one) and + re-flattens the tree when booting the kernel. The former is a bit + more difficult to edit/modify, the later requires probably a bit + more code to handle the tree structure. Note that the structure + format has been designed so it's relatively easy to "insert" + properties or nodes or delete them by just memmoving things + around. It contains no internal offsets or pointers for this + purpose. + + - An example of code for iterating nodes & retreiving properties + directly from the flattened tree format can be found in the kernel + file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function, + it's usage in early_init_devtree(), and the corresponding various + early_init_dt_scan_*() callbacks. That code can be re-used in a + GPL bootloader, and as the author of that code, I would be happy + do discuss possible free licencing to any vendor who wishes to + integrate all or part of this code into a non-GPL bootloader. + + + +VI - System-on-a-chip devices and nodes +======================================= + +Many companies are now starting to develop system-on-a-chip +processors, where the processor core (cpu) and many peripheral devices +exist on a single piece of silicon. For these SOCs, an SOC node +should be used that defines child nodes for the devices that make +up the SOC. While platforms are not required to use this model in +order to boot the kernel, it is highly encouraged that all SOC +implementations define as complete a flat-device-tree as possible to +describe the devices on the SOC. This will allow for the +genericization of much of the kernel code. + + +1) Defining child nodes of an SOC +--------------------------------- + +Each device that is part of an SOC may have its own node entry inside +the SOC node. For each device that is included in the SOC, the unit +address property represents the address offset for this device's +memory-mapped registers in the parent's address space. The parent's +address space is defined by the "ranges" property in the top-level soc +node. The "reg" property for each node that exists directly under the +SOC node should contain the address mapping from the child address space +to the parent SOC address space and the size of the device's +memory-mapped register file. + +For many devices that may exist inside an SOC, there are predefined +specifications for the format of the device tree node. All SOC child +nodes should follow these specifications, except where noted in this +document. + +See appendix A for an example partial SOC node definition for the +MPC8540. + + +2) Specifying interrupt information for SOC devices +--------------------------------------------------- + +Each device that is part of an SOC and which generates interrupts +should have the following properties: + + - interrupt-parent : contains the phandle of the interrupt + controller which handles interrupts for this device + - interrupts : a list of tuples representing the interrupt + number and the interrupt sense and level for each interupt + for this device. + +This information is used by the kernel to build the interrupt table +for the interrupt controllers in the system. + +Sense and level information should be encoded as follows: + + Devices connected to openPIC-compatible controllers should encode + sense and polarity as follows: + + 0 = high to low edge sensitive type enabled + 1 = active low level sensitive type enabled + 2 = low to high edge sensitive type enabled + 3 = active high level sensitive type enabled + + ISA PIC interrupt controllers should adhere to the ISA PIC + encodings listed below: + + 0 = active low level sensitive type enabled + 1 = active high level sensitive type enabled + 2 = high to low edge sensitive type enabled + 3 = low to high edge sensitive type enabled + + + +3) Representing devices without a current OF specification +---------------------------------------------------------- + +Currently, there are many devices on SOCs that do not have a standard +representation pre-defined as part of the open firmware +specifications, mainly because the boards that contain these SOCs are +not currently booted using open firmware. This section contains +descriptions for the SOC devices for which new nodes have been +defined; this list will expand as more and more SOC-containing +platforms are moved over to use the flattened-device-tree model. + + a) MDIO IO device + + The MDIO is a bus to which the PHY devices are connected. For each + device that exists on this bus, a child node should be created. See + the definition of the PHY node below for an example of how to define + a PHY. + + Required properties: + - reg : Offset and length of the register set for the device + - device_type : Should be "mdio" + - compatible : Should define the compatible device type for the + mdio. Currently, this is most likely to be "gianfar" + + Example: + + mdio@24520 { + reg = <24520 20>; + device_type = "mdio"; + compatible = "gianfar"; + + ethernet-phy@0 { + ...... + }; + }; + + + b) Gianfar-compatible ethernet nodes + + Required properties: + + - device_type : Should be "network" + - model : Model of the device. Can be "TSEC", "eTSEC", or "FEC" + - compatible : Should be "gianfar" + - reg : Offset and length of the register set for the device + - address : List of bytes representing the ethernet address of + this controller + - interrupts : <a b> where a is the interrupt number and b is a + field that represents an encoding of the sense and level + information for the interrupt. This should be encoded based on + the information in section 2) depending on the type of interrupt + controller you have. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - phy-handle : The phandle for the PHY connected to this ethernet + controller. + + Example: + + ethernet@24000 { + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + address = [ 00 E0 0C 00 73 00 ]; + interrupts = <d 3 e 3 12 3>; + interrupt-parent = <40000>; + phy-handle = <2452000> + }; + + + + c) PHY nodes + + Required properties: + + - device_type : Should be "ethernet-phy" + - interrupts : <a b> where a is the interrupt number and b is a + field that represents an encoding of the sense and level + information for the interrupt. This should be encoded based on + the information in section 2) depending on the type of interrupt + controller you have. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - reg : The ID number for the phy, usually a small integer + - linux,phandle : phandle for this node; likely referenced by an + ethernet controller node. + + + Example: + + ethernet-phy@0 { + linux,phandle = <2452000> + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <0>; + device_type = "ethernet-phy"; + }; + + + d) Interrupt controllers + + Some SOC devices contain interrupt controllers that are different + from the standard Open PIC specification. The SOC device nodes for + these types of controllers should be specified just like a standard + OpenPIC controller. Sense and level information should be encoded + as specified in section 2) of this chapter for each device that + specifies an interrupt. + + Example : + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + + + e) I2C + + Required properties : + + - device_type : Should be "i2c" + - reg : Offset and length of the register set for the device + + Recommended properties : + + - compatible : Should be "fsl-i2c" for parts compatible with + Freescale I2C specifications. + - interrupts : <a b> where a is the interrupt number and b is a + field that represents an encoding of the sense and level + information for the interrupt. This should be encoded based on + the information in section 2) depending on the type of interrupt + controller you have. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - dfsrr : boolean; if defined, indicates that this I2C device has + a digital filter sampling rate register + - fsl5200-clocking : boolean; if defined, indicated that this device + uses the FSL 5200 clocking mechanism. + + Example : + + i2c@3000 { + interrupt-parent = <40000>; + interrupts = <1b 3>; + reg = <3000 18>; + device_type = "i2c"; + compatible = "fsl-i2c"; + dfsrr; + }; + + + f) Freescale SOC USB controllers + + The device node for a USB controller that is part of a Freescale + SOC is as described in the document "Open Firmware Recommended + Practice : Universal Serial Bus" with the following modifications + and additions : + + Required properties : + - compatible : Should be "fsl-usb2-mph" for multi port host usb + controllers, or "fsl-usb2-dr" for dual role usb controllers + - phy_type : For multi port host usb controllers, should be one of + "ulpi", or "serial". For dual role usb controllers, should be + one of "ulpi", "utmi", "utmi_wide", or "serial". + - reg : Offset and length of the register set for the device + - port0 : boolean; if defined, indicates port0 is connected for + fsl-usb2-mph compatible controllers. Either this property or + "port1" (or both) must be defined for "fsl-usb2-mph" compatible + controllers. + - port1 : boolean; if defined, indicates port1 is connected for + fsl-usb2-mph compatible controllers. Either this property or + "port0" (or both) must be defined for "fsl-usb2-mph" compatible + controllers. + + Recommended properties : + - interrupts : <a b> where a is the interrupt number and b is a + field that represents an encoding of the sense and level + information for the interrupt. This should be encoded based on + the information in section 2) depending on the type of interrupt + controller you have. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + + Example multi port host usb controller device node : + usb@22000 { + device_type = "usb"; + compatible = "fsl-usb2-mph"; + reg = <22000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <27 1>; + phy_type = "ulpi"; + port0; + port1; + }; + + Example dual role usb controller device node : + usb@23000 { + device_type = "usb"; + compatible = "fsl-usb2-dr"; + reg = <23000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <26 1>; + phy = "ulpi"; + }; + + + More devices will be defined as this spec matures. + + +Appendix A - Sample SOC node for MPC8540 +======================================== + +Note that the #address-cells and #size-cells for the SoC node +in this example have been explicitly listed; these are likely +not necessary as they are usually the same as the root node. + + soc8540@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <00000000 e0000000 00100000> + reg = <e0000000 00003000>; + bus-frequency = <0>; + + mdio@24520 { + reg = <24520 20>; + device_type = "mdio"; + compatible = "gianfar"; + + ethernet-phy@0 { + linux,phandle = <2452000> + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <0>; + device_type = "ethernet-phy"; + }; + + ethernet-phy@1 { + linux,phandle = <2452001> + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <1>; + device_type = "ethernet-phy"; + }; + + ethernet-phy@3 { + linux,phandle = <2452002> + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <3>; + device_type = "ethernet-phy"; + }; + + }; + + ethernet@24000 { + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + address = [ 00 E0 0C 00 73 00 ]; + interrupts = <d 3 e 3 12 3>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 3 14 3 18 3>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + ethernet@26000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "FEC"; + compatible = "gianfar"; + reg = <26000 1000>; + address = [ 00 E0 0C 00 73 02 ]; + interrupts = <19 3>; + interrupt-parent = <40000>; + phy-handle = <2452002>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <1a 3>; + interrupt-parent = <40000>; + }; + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + + i2c@3000 { + interrupt-parent = <40000>; + interrupts = <1b 3>; + reg = <3000 18>; + device_type = "i2c"; + compatible = "fsl-i2c"; + dfsrr; + }; + + }; diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas new file mode 100644 index 000000000000..f8c16cbf56ba --- /dev/null +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -0,0 +1,24 @@ +1 Release Date : Mon Jan 23 14:09:01 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com> +2 Current Version : 00.00.02.02 +3 Older Version : 00.00.02.01 + +i. New template defined to represent each family of controllers (identified by processor used). + The template will have defintions that will be initialised to appropritae values for a specific family of controllers. The template definition has four function pointers. During driver initialisation the function pointers will be set based on the controller family type. This change is done to support new controllers that has different processors and thus different register set. + + -Sumant Patro <Sumant.Patro@lsil.com> + +1 Release Date : Mon Dec 19 14:36:26 PST 2005 - Sumant Patro <Sumant.Patro@lsil.com> +2 Current Version : 00.00.02.00-rc4 +3 Older Version : 00.00.02.01 + +i. Code reorganized to remove code duplication in megasas_build_cmd. + + "There's a lot of duplicate code megasas_build_cmd. Move that out of the different codepathes and merge the reminder of megasas_build_cmd into megasas_queue_command" + + - Christoph Hellwig <hch@lst.de> + +ii. Defined MEGASAS_IOC_FIRMWARE32 for code paths that handles 32 bit applications in 64 bit systems. + + "MEGASAS_IOC_FIRMWARE can't be redefined if CONFIG_COMPAT is set, we need to define a MEGASAS_IOC_FIRMWARE32 define so native binaries continue to work" + + - Christoph Hellwig <hch@lst.de> diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt index 0aeef740a95a..382b439b439e 100644 --- a/Documentation/scsi/aic79xx.txt +++ b/Documentation/scsi/aic79xx.txt @@ -1,5 +1,5 @@ ==================================================================== -= Adaptec Ultra320 Family Manager Set v1.3.11 = += Adaptec Ultra320 Family Manager Set = = = = README for = = The Linux Operating System = @@ -63,6 +63,11 @@ The following information is available in this file: 68-pin) 2. Version History + 3.0 (December 1st, 2005) + - Updated driver to use SCSI transport class infrastructure + - Upported sequencer and core fixes from adaptec released + version 2.0.15 of the driver. + 1.3.11 (July 11, 2003) - Fix several deadlock issues. - Add 29320ALP and 39320B Id's. @@ -194,7 +199,7 @@ The following information is available in this file: supported) - Support for the PCI-X standard up to 133MHz - Support for the PCI v2.2 standard - - Domain Validation + - Domain Validation 2.2. Operating System Support: - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 @@ -411,77 +416,53 @@ The following information is available in this file: http://www.adaptec.com. -5. Contacting Adaptec +5. Adaptec Customer Support A Technical Support Identification (TSID) Number is required for Adaptec technical support. - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us + included inside the box with your product. The TSID helps us provide more efficient service by accurately identifying your product and support status. + Support Options - Search the Adaptec Support Knowledgebase (ASK) at http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions for your product. + frequently asked questions about your product. - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com. + Technical Support Specialists at http://ask.adaptec.com/. North America - - Visit our Web site at http://www.adaptec.com. - - To speak with a Fibre Channel/RAID/External Storage Technical - Support Specialist, call 1-321-207-2000, - Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST. - (Not open on holidays) - - For Technical Support in all other technologies including - SCSI, call 1-408-934-7274, - Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST. - (Not open on holidays) - - For after hours support, call 1-800-416-8066 ($99/call, - $149/call on holidays) - - To order Adaptec products including software and cables, call - 1-800-442-7274 or 1-408-957-7274. You can also visit our - online store at http://www.adaptecstore.com + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. Europe - - Visit our Web site at http://www.adaptec-europe.com. - - English and French: To speak with a Technical Support - Specialist, call one of the following numbers: - - English: +32-2-352-3470 - - French: +32-2-352-3460 - Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET - Friday, 10:00 to 12:30, 13:30 to 16:30 CET - - German: To speak with a Technical Support Specialist, - call +49-89-456-40660 - Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET - Friday, 09:30 to 12:30, 13:30 to 15:00 CET - - To order Adaptec products, including accessories and cables: - - UK: +0800-96-65-26 or fax +0800-731-02-95 - - Other European countries: +32-11-300-379 - - Australia and New Zealand - - Visit our Web site at http://www.adaptec.com.au. - - To speak with a Technical Support Specialist, call - +612-9416-0698 - Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT - (Not open on holidays) + - Visit our Web site at http://www.adaptec-europe.com/. + - To speak with a Technical Support Specialist, call, or email, + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. Japan + - Visit our web site at http://www.adaptec.co.jp/. - To speak with a Technical Support Specialist, call - +81-3-5308-6120 - Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to - 6:00 p.m. TSC - - Hong Kong and China - - To speak with a Technical Support Specialist, call - +852-2869-7200 - Hours: Monday-Friday, 10:00 to 17:00. - - Fax Technical Support at +852-2869-7100. - - Singapore - - To speak with a Technical Support Specialist, call - +65-245-7470 - Hours: Monday-Friday, 10:00 to 17:00. - - Fax Technical Support at +852-2869-7100 + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. ------------------------------------------------------------------- /* diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt index 47e74ddc4bc9..3481fcded4c2 100644 --- a/Documentation/scsi/aic7xxx.txt +++ b/Documentation/scsi/aic7xxx.txt @@ -309,81 +309,57 @@ The following information is available in this file: ----------------------------------------------------------------- Example: - 'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1" + 'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1' enables verbose logging, Disable EISA/VLB probing, and set tag depth on Controller 1/Target 2 to 10 tags. -3. Contacting Adaptec +4. Adaptec Customer Support A Technical Support Identification (TSID) Number is required for Adaptec technical support. - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us + included inside the box with your product. The TSID helps us provide more efficient service by accurately identifying your product and support status. + Support Options - Search the Adaptec Support Knowledgebase (ASK) at http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions for your product. + frequently asked questions about your product. - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com. + Technical Support Specialists at http://ask.adaptec.com/. North America - - Visit our Web site at http://www.adaptec.com. - - To speak with a Fibre Channel/RAID/External Storage Technical - Support Specialist, call 1-321-207-2000, - Hours: Monday-Friday, 3:00 A.M. to 5:00 P.M., PST. - (Not open on holidays) - - For Technical Support in all other technologies including - SCSI, call 1-408-934-7274, - Hours: Monday-Friday, 6:00 A.M. to 5:00 P.M., PST. - (Not open on holidays) - - For after hours support, call 1-800-416-8066 ($99/call, - $149/call on holidays) - - To order Adaptec products including software and cables, call - 1-800-442-7274 or 1-408-957-7274. You can also visit our - online store at http://www.adaptecstore.com + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. Europe - - Visit our Web site at http://www.adaptec-europe.com. - - English and French: To speak with a Technical Support - Specialist, call one of the following numbers: - - English: +32-2-352-3470 - - French: +32-2-352-3460 - Hours: Monday-Thursday, 10:00 to 12:30, 13:30 to 17:30 CET - Friday, 10:00 to 12:30, 13:30 to 16:30 CET - - German: To speak with a Technical Support Specialist, - call +49-89-456-40660 - Hours: Monday-Thursday, 09:30 to 12:30, 13:30 to 16:30 CET - Friday, 09:30 to 12:30, 13:30 to 15:00 CET - - To order Adaptec products, including accessories and cables: - - UK: +0800-96-65-26 or fax +0800-731-02-95 - - Other European countries: +32-11-300-379 - - Australia and New Zealand - - Visit our Web site at http://www.adaptec.com.au. - - To speak with a Technical Support Specialist, call - +612-9416-0698 - Hours: Monday-Friday, 10:00 A.M. to 4:30 P.M., EAT - (Not open on holidays) + - Visit our Web site at http://www.adaptec-europe.com/. + - To speak with a Technical Support Specialist, call, or email, + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. Japan + - Visit our web site at http://www.adaptec.co.jp/. - To speak with a Technical Support Specialist, call - +81-3-5308-6120 - Hours: Monday-Friday, 9:00 a.m. to 12:00 p.m., 1:00 p.m. to - 6:00 p.m. TSC - - Hong Kong and China - - To speak with a Technical Support Specialist, call - +852-2869-7200 - Hours: Monday-Friday, 10:00 to 17:00. - - Fax Technical Support at +852-2869-7100. - - Singapore - - To speak with a Technical Support Specialist, call - +65-245-7470 - Hours: Monday-Friday, 10:00 to 17:00. - - Fax Technical Support at +852-2869-7100 + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. ------------------------------------------------------------------- /* diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index d2578013e829..36b511c7cade 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -837,8 +837,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for AC'97 motherboards from Intel and compatibles. * Intel i810/810E, i815, i820, i830, i84x, MX440 + ICH5, ICH6, ICH7, ESB2 * SiS 7012 (SiS 735) - * NVidia NForce, NForce2 + * NVidia NForce, NForce2, NForce3, MCP04, CK804 + CK8, CK8S, MCP501 * AMD AMD768, AMD8111 * ALi m5455 @@ -868,6 +870,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. -------------------- Module for Intel ICH (i8x0) chipset MC97 modems. + * Intel i810/810E, i815, i820, i830, i84x, MX440 + ICH5, ICH6, ICH7 + * SiS 7013 (SiS 735) + * NVidia NForce, NForce2, NForce2s, NForce3 + * AMD AMD8111 + * ALi m5455 ac97_clock - AC'97 codec clock base (0 = auto-detect) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index e651ed8d1e6f..4251085d38d3 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -5206,14 +5206,14 @@ struct _snd_pcm_runtime { You need to pass the <function>snd_dma_pci_data(pci)</function>, where pci is the struct <structname>pci_dev</structname> pointer of the chip as well. - The <type>snd_sg_buf_t</type> instance is created as + The <type>struct snd_sg_buf</type> instance is created as substream->dma_private. You can cast the pointer like: <informalexample> <programlisting> <![CDATA[ - struct snd_sg_buf *sgbuf = (struct snd_sg_buf_t*)substream->dma_private; + struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private; ]]> </programlisting> </informalexample> diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly index a2e8c8d90e35..9927af7a629c 100644 --- a/Documentation/spi/butterfly +++ b/Documentation/spi/butterfly @@ -12,13 +12,20 @@ You can make this adapter from an old printer cable and solder things directly to the Butterfly. Or (if you have the parts and skills) you can come up with something fancier, providing ciruit protection to the Butterfly and the printer port, or with a better power supply than two -signal pins from the printer port. +signal pins from the printer port. Or for that matter, you can use +similar cables to talk to many AVR boards, even a breadboard. + +This is more powerful than "ISP programming" cables since it lets kernel +SPI protocol drivers interact with the AVR, and could even let the AVR +issue interrupts to them. Later, your protocol driver should work +easily with a "real SPI controller", instead of this bitbanger. The first cable connections will hook Linux up to one SPI bus, with the AVR and a DataFlash chip; and to the AVR reset line. This is all you need to reflash the firmware, and the pins are the standard Atmel "ISP" -connector pins (used also on non-Butterfly AVR boards). +connector pins (used also on non-Butterfly AVR boards). On the parport +side this is like "sp12" programming cables. Signal Butterfly Parport (DB-25) ------ --------- --------------- @@ -40,10 +47,14 @@ by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and SELECT = J400.PB0/nSS = pin 17/C3,nSELECT GND = J400.GND = pin 24/GND -The "USI" controller, using J405, can be used for a second SPI bus. That -would let you talk to the AVR over SPI, running firmware that makes it act -as an SPI slave, while letting either Linux or the AVR use the DataFlash. -There are plenty of spare parport pins to wire this one up, such as: +Or you could flash firmware making the AVR into an SPI slave (keeping the +DataFlash in reset) and tweak the spi_butterfly driver to make it bind to +the driver for your custom SPI-based protocol. + +The "USI" controller, using J405, can also be used for a second SPI bus. +That would let you talk to the AVR using custom SPI-with-USI firmware, +while letting either Linux or the AVR use the DataFlash. There are plenty +of spare parport pins to wire this one up, such as: Signal Butterfly Parport (DB-25) ------ --------- --------------- diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 6910c0136f8d..a46c10fcddfc 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -27,6 +27,8 @@ Currently, these files are in /proc/sys/vm: - laptop_mode - block_dump - drop-caches +- zone_reclaim_mode +- zone_reclaim_interval ============================================================== @@ -120,3 +122,59 @@ 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. + +=============================================================== + +zone_reclaim_mode: + +Zone_reclaim_mode allows to set more or less agressive approaches to +reclaim memory when a zone runs out of memory. If it is set to zero then no +zone reclaim occurs. Allocations will be satisfied from other zones / nodes +in the system. + +This is value ORed together of + +1 = Zone reclaim on +2 = Zone reclaim writes dirty pages out +4 = Zone reclaim swaps pages +8 = Also do a global slab reclaim pass + +zone_reclaim_mode is set during bootup to 1 if it is determined that pages +from remote zones will cause a measurable performance reduction. The +page allocator will then reclaim easily reusable pages (those page +cache pages that are currently not used) before allocating off node pages. + +It may be beneficial to switch off zone reclaim if the system is +used for a file server and all of memory should be used for caching files +from disk. In that case the caching effect is more important than +data locality. + +Allowing zone reclaim to write out pages stops processes that are +writing large amounts of data from dirtying pages on other nodes. Zone +reclaim will write out dirty pages if a zone fills up and so effectively +throttle the process. This may decrease the performance of a single process +since it cannot use all of system memory to buffer the outgoing writes +anymore but it preserve the memory on other nodes so that the performance +of other processes running on other nodes will not be affected. + +Allowing regular swap effectively restricts allocations to the local +node unless explicitly overridden by memory policies or cpuset +configurations. + +It may be advisable to allow slab reclaim if the system makes heavy +use of files and builds up large slab caches. However, the slab +shrink operation is global, may take a long time and free slabs +in all nodes of the system. + +================================================================ + +zone_reclaim_interval: + +The time allowed for off node allocations after zone reclaim +has failed to reclaim enough pages to allow a local allocation. + +Time is set in seconds and set by default to 30 seconds. + +Reduce the interval if undesired off node allocations occur. However, too +frequent scans will have a negative impact onoff node allocation performance. + diff --git a/Documentation/unshare.txt b/Documentation/unshare.txt new file mode 100644 index 000000000000..90a5e9e5bef1 --- /dev/null +++ b/Documentation/unshare.txt @@ -0,0 +1,295 @@ + +unshare system call: +-------------------- +This document describes the new system call, unshare. The document +provides an overview of the feature, why it is needed, how it can +be used, its interface specification, design, implementation and +how it can be tested. + +Change Log: +----------- +version 0.1 Initial document, Janak Desai (janak@us.ibm.com), Jan 11, 2006 + +Contents: +--------- + 1) Overview + 2) Benefits + 3) Cost + 4) Requirements + 5) Functional Specification + 6) High Level Design + 7) Low Level Design + 8) Test Specification + 9) Future Work + +1) Overview +----------- +Most legacy operating system kernels support an abstraction of threads +as multiple execution contexts within a process. These kernels provide +special resources and mechanisms to maintain these "threads". The Linux +kernel, in a clever and simple manner, does not make distinction +between processes and "threads". The kernel allows processes to share +resources and thus they can achieve legacy "threads" behavior without +requiring additional data structures and mechanisms in the kernel. The +power of implementing threads in this manner comes not only from +its simplicity but also from allowing application programmers to work +outside the confinement of all-or-nothing shared resources of legacy +threads. On Linux, at the time of thread creation using the clone system +call, applications can selectively choose which resources to share +between threads. + +unshare system call adds a primitive to the Linux thread model that +allows threads to selectively 'unshare' any resources that were being +shared at the time of their creation. unshare was conceptualized by +Al Viro in the August of 2000, on the Linux-Kernel mailing list, as part +of the discussion on POSIX threads on Linux. unshare augments the +usefulness of Linux threads for applications that would like to control +shared resources without creating a new process. unshare is a natural +addition to the set of available primitives on Linux that implement +the concept of process/thread as a virtual machine. + +2) Benefits +----------- +unshare would be useful to large application frameworks such as PAM +where creating a new process to control sharing/unsharing of process +resources is not possible. Since namespaces are shared by default +when creating a new process using fork or clone, unshare can benefit +even non-threaded applications if they have a need to disassociate +from default shared namespace. The following lists two use-cases +where unshare can be used. + +2.1 Per-security context namespaces +----------------------------------- +unshare can be used to implement polyinstantiated directories using +the kernel's per-process namespace mechanism. Polyinstantiated directories, +such as per-user and/or per-security context instance of /tmp, /var/tmp or +per-security context instance of a user's home directory, isolate user +processes when working with these directories. Using unshare, a PAM +module can easily setup a private namespace for a user at login. +Polyinstantiated directories are required for Common Criteria certification +with Labeled System Protection Profile, however, with the availability +of shared-tree feature in the Linux kernel, even regular Linux systems +can benefit from setting up private namespaces at login and +polyinstantiating /tmp, /var/tmp and other directories deemed +appropriate by system administrators. + +2.2 unsharing of virtual memory and/or open files +------------------------------------------------- +Consider a client/server application where the server is processing +client requests by creating processes that share resources such as +virtual memory and open files. Without unshare, the server has to +decide what needs to be shared at the time of creating the process +which services the request. unshare allows the server an ability to +disassociate parts of the context during the servicing of the +request. For large and complex middleware application frameworks, this +ability to unshare after the process was created can be very +useful. + +3) Cost +------- +In order to not duplicate code and to handle the fact that unshare +works on an active task (as opposed to clone/fork working on a newly +allocated inactive task) unshare had to make minor reorganizational +changes to copy_* functions utilized by clone/fork system call. +There is a cost associated with altering existing, well tested and +stable code to implement a new feature that may not get exercised +extensively in the beginning. However, with proper design and code +review of the changes and creation of an unshare test for the LTP +the benefits of this new feature can exceed its cost. + +4) Requirements +--------------- +unshare reverses sharing that was done using clone(2) system call, +so unshare should have a similar interface as clone(2). That is, +since flags in clone(int flags, void *stack) specifies what should +be shared, similar flags in unshare(int flags) should specify +what should be unshared. Unfortunately, this may appear to invert +the meaning of the flags from the way they are used in clone(2). +However, there was no easy solution that was less confusing and that +allowed incremental context unsharing in future without an ABI change. + +unshare interface should accommodate possible future addition of +new context flags without requiring a rebuild of old applications. +If and when new context flags are added, unshare design should allow +incremental unsharing of those resources on an as needed basis. + +5) Functional Specification +--------------------------- +NAME + unshare - disassociate parts of the process execution context + +SYNOPSIS + #include <sched.h> + + int unshare(int flags); + +DESCRIPTION + unshare allows a process to disassociate parts of its execution + context that are currently being shared with other processes. Part + of execution context, such as the namespace, is shared by default + when a new process is created using fork(2), while other parts, + such as the virtual memory, open file descriptors, etc, may be + shared by explicit request to share them when creating a process + using clone(2). + + The main use of unshare is to allow a process to control its + shared execution context without creating a new process. + + The flags argument specifies one or bitwise-or'ed of several of + the following constants. + + CLONE_FS + If CLONE_FS is set, file system information of the caller + is disassociated from the shared file system information. + + CLONE_FILES + If CLONE_FILES is set, the file descriptor table of the + caller is disassociated from the shared file descriptor + table. + + CLONE_NEWNS + If CLONE_NEWNS is set, the namespace of the caller is + disassociated from the shared namespace. + + CLONE_VM + If CLONE_VM is set, the virtual memory of the caller is + disassociated from the shared virtual memory. + +RETURN VALUE + On success, zero returned. On failure, -1 is returned and errno is + +ERRORS + EPERM CLONE_NEWNS was specified by a non-root process (process + without CAP_SYS_ADMIN). + + ENOMEM Cannot allocate sufficient memory to copy parts of caller's + context that need to be unshared. + + EINVAL Invalid flag was specified as an argument. + +CONFORMING TO + The unshare() call is Linux-specific and should not be used + in programs intended to be portable. + +SEE ALSO + clone(2), fork(2) + +6) High Level Design +-------------------- +Depending on the flags argument, the unshare system call allocates +appropriate process context structures, populates it with values from +the current shared version, associates newly duplicated structures +with the current task structure and releases corresponding shared +versions. Helper functions of clone (copy_*) could not be used +directly by unshare because of the following two reasons. + 1) clone operates on a newly allocated not-yet-active task + structure, where as unshare operates on the current active + task. Therefore unshare has to take appropriate task_lock() + before associating newly duplicated context structures + 2) unshare has to allocate and duplicate all context structures + that are being unshared, before associating them with the + current task and releasing older shared structures. Failure + do so will create race conditions and/or oops when trying + to backout due to an error. Consider the case of unsharing + both virtual memory and namespace. After successfully unsharing + vm, if the system call encounters an error while allocating + new namespace structure, the error return code will have to + reverse the unsharing of vm. As part of the reversal the + system call will have to go back to older, shared, vm + structure, which may not exist anymore. + +Therefore code from copy_* functions that allocated and duplicated +current context structure was moved into new dup_* functions. Now, +copy_* functions call dup_* functions to allocate and duplicate +appropriate context structures and then associate them with the +task structure that is being constructed. unshare system call on +the other hand performs the following: + 1) Check flags to force missing, but implied, flags + 2) For each context structure, call the corresponding unshare + helper function to allocate and duplicate a new context + structure, if the appropriate bit is set in the flags argument. + 3) If there is no error in allocation and duplication and there + are new context structures then lock the current task structure, + associate new context structures with the current task structure, + and release the lock on the current task structure. + 4) Appropriately release older, shared, context structures. + +7) Low Level Design +------------------- +Implementation of unshare can be grouped in the following 4 different +items: + a) Reorganization of existing copy_* functions + b) unshare system call service function + c) unshare helper functions for each different process context + d) Registration of system call number for different architectures + + 7.1) Reorganization of copy_* functions + Each copy function such as copy_mm, copy_namespace, copy_files, + etc, had roughly two components. The first component allocated + and duplicated the appropriate structure and the second component + linked it to the task structure passed in as an argument to the copy + function. The first component was split into its own function. + These dup_* functions allocated and duplicated the appropriate + context structure. The reorganized copy_* functions invoked + their corresponding dup_* functions and then linked the newly + duplicated structures to the task structure with which the + copy function was called. + + 7.2) unshare system call service function + * Check flags + Force implied flags. If CLONE_THREAD is set force CLONE_VM. + If CLONE_VM is set, force CLONE_SIGHAND. If CLONE_SIGHAND is + set and signals are also being shared, force CLONE_THREAD. If + CLONE_NEWNS is set, force CLONE_FS. + * For each context flag, invoke the corresponding unshare_* + helper routine with flags passed into the system call and a + reference to pointer pointing the new unshared structure + * If any new structures are created by unshare_* helper + functions, take the task_lock() on the current task, + modify appropriate context pointers, and release the + task lock. + * For all newly unshared structures, release the corresponding + older, shared, structures. + + 7.3) unshare_* helper functions + For unshare_* helpers corresponding to CLONE_SYSVSEM, CLONE_SIGHAND, + and CLONE_THREAD, return -EINVAL since they are not implemented yet. + For others, check the flag value to see if the unsharing is + required for that structure. If it is, invoke the corresponding + dup_* function to allocate and duplicate the structure and return + a pointer to it. + + 7.4) Appropriately modify architecture specific code to register the + the new system call. + +8) Test Specification +--------------------- +The test for unshare should test the following: + 1) Valid flags: Test to check that clone flags for signal and + signal handlers, for which unsharing is not implemented + yet, return -EINVAL. + 2) Missing/implied flags: Test to make sure that if unsharing + namespace without specifying unsharing of filesystem, correctly + unshares both namespace and filesystem information. + 3) For each of the four (namespace, filesystem, files and vm) + supported unsharing, verify that the system call correctly + unshares the appropriate structure. Verify that unsharing + them individually as well as in combination with each + other works as expected. + 4) Concurrent execution: Use shared memory segments and futex on + an address in the shm segment to synchronize execution of + about 10 threads. Have a couple of threads execute execve, + a couple _exit and the rest unshare with different combination + of flags. Verify that unsharing is performed as expected and + that there are no oops or hangs. + +9) Future Work +-------------- +The current implementation of unshare does not allow unsharing of +signals and signal handlers. Signals are complex to begin with and +to unshare signals and/or signal handlers of a currently running +process is even more complex. If in the future there is a specific +need to allow unsharing of signals and/or signal handlers, it can +be incrementally added to unshare without affecting legacy +applications using unshare. + diff --git a/Documentation/usb/et61x251.txt b/Documentation/usb/et61x251.txt new file mode 100644 index 000000000000..b44dda407ce2 --- /dev/null +++ b/Documentation/usb/et61x251.txt @@ -0,0 +1,306 @@ + + ET61X[12]51 PC Camera Controllers + Driver for Linux + ================================= + + - Documentation - + + +Index +===== +1. Copyright +2. Disclaimer +3. License +4. Overview and features +5. Module dependencies +6. Module loading +7. Module parameters +8. Optional device control through "sysfs" +9. Supported devices +10. Notes for V4L2 application developers +11. Contact information + + +1. Copyright +============ +Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> + + +2. Disclaimer +============= +Etoms is a trademark of Etoms Electronics Corp. +This software is not developed or sponsored by Etoms Electronics. + + +3. License +========== +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +4. Overview and features +======================== +This driver supports the video interface of the devices mounting the ET61X151 +or ET61X251 PC Camera Controllers. + +It's worth to note that Etoms Electronics has never collaborated with the +author during the development of this project; despite several requests, +Etoms Electronics also refused to release enough detailed specifications of +the video compression engine. + +The driver relies on the Video4Linux2 and USB core modules. It has been +designed to run properly on SMP systems as well. + +The latest version of the ET61X[12]51 driver can be found at the following URL: +http://www.linux-projects.org/ + +Some of the features of the driver are: + +- full compliance with the Video4Linux2 API (see also "Notes for V4L2 + application developers" paragraph); +- available mmap or read/poll methods for video streaming through isochronous + data transfers; +- automatic detection of image sensor; +- support for any window resolutions and optional panning within the maximum + pixel area of image sensor; +- image downscaling with arbitrary scaling factors from 1 and 2 in both + directions (see "Notes for V4L2 application developers" paragraph); +- two different video formats for uncompressed or compressed data in low or + high compression quality (see also "Notes for V4L2 application developers" + paragraph); +- full support for the capabilities of every possible image sensors that can + be connected to the ET61X[12]51 bridges, including, for istance, red, green, + blue and global gain adjustments and exposure control (see "Supported + devices" paragraph for details); +- use of default color settings for sunlight conditions; +- dynamic I/O interface for both ET61X[12]51 and image sensor control (see + "Optional device control through 'sysfs'" paragraph); +- dynamic driver control thanks to various module parameters (see "Module + parameters" paragraph); +- up to 64 cameras can be handled at the same time; they can be connected and + disconnected from the host many times without turning off the computer, if + the system supports hotplugging; +- no known bugs. + + +5. Module dependencies +====================== +For it to work properly, the driver needs kernel support for Video4Linux and +USB. + +The following options of the kernel configuration file must be enabled and +corresponding modules must be compiled: + + # Multimedia devices + # + CONFIG_VIDEO_DEV=m + +To enable advanced debugging functionality on the device through /sysfs: + + # Multimedia devices + # + CONFIG_VIDEO_ADV_DEBUG=y + + # USB support + # + CONFIG_USB=m + +In addition, depending on the hardware being used, the modules below are +necessary: + + # USB Host Controller Drivers + # + CONFIG_USB_EHCI_HCD=m + CONFIG_USB_UHCI_HCD=m + CONFIG_USB_OHCI_HCD=m + +And finally: + + # USB Multimedia devices + # + CONFIG_USB_ET61X251=m + + +6. Module loading +================= +To use the driver, it is necessary to load the "et61x251" module into memory +after every other module required: "videodev", "usbcore" and, depending on +the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". + +Loading can be done as shown below: + + [root@localhost home]# modprobe et61x251 + +At this point the devices should be recognized. You can invoke "dmesg" to +analyze kernel messages and verify that the loading process has gone well: + + [user@localhost home]$ dmesg + + +7. Module parameters +==================== +Module parameters are listed below: +------------------------------------------------------------------------------- +Name: video_nr +Type: short array (min = 0, max = 64) +Syntax: <-1|n[,...]> +Description: Specify V4L2 minor mode number: + -1 = use next available + n = use minor number n + You can specify up to 64 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + registered camera and use auto for the first one and for every + other camera. +Default: -1 +------------------------------------------------------------------------------- +Name: force_munmap +Type: bool array (min = 0, max = 64) +Syntax: <0|1[,...]> +Description: Force the application to unmap previously mapped buffer memory + before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not + all the applications support this feature. This parameter is + specific for each detected camera. + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) +Default: 0 +------------------------------------------------------------------------------- +Name: debug +Type: ushort +Syntax: <n> +Description: Debugging information level, from 0 to 3: + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = more verbose messages + Level 3 is useful for testing only, when only one device + is used at the same time. It also shows some more informations + about the hardware being detected. This module parameter can be + changed at runtime thanks to the /sys filesystem interface. +Default: 2 +------------------------------------------------------------------------------- + + +8. Optional device control through "sysfs" +========================================== +If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled, +it is possible to read and write both the ET61X[12]51 and the image sensor +registers by using the "sysfs" filesystem interface. + +There are four files in the /sys/class/video4linux/videoX directory for each +registered camera: "reg", "val", "i2c_reg" and "i2c_val". The first two files +control the ET61X[12]51 bridge, while the other two control the sensor chip. +"reg" and "i2c_reg" hold the values of the current register index where the +following reading/writing operations are addressed at through "val" and +"i2c_val". Their use is not intended for end-users, unless you know what you +are doing. Remember that you must be logged in as root before writing to them. + +As an example, suppose we were to want to read the value contained in the +register number 1 of the sensor register table - which is usually the product +identifier - of the camera registered as "/dev/video0": + + [root@localhost #] cd /sys/class/video4linux/video0 + [root@localhost #] echo 1 > i2c_reg + [root@localhost #] cat i2c_val + +Note that if the sensor registers can not be read, "cat" will fail. +To avoid race conditions, all the I/O accesses to the files are serialized. + + +9. Supported devices +==================== +None of the names of the companies as well as their products will be mentioned +here. They have never collaborated with the author, so no advertising. + +From the point of view of a driver, what unambiguously identify a device are +its vendor and product USB identifiers. Below is a list of known identifiers of +devices mounting the ET61X[12]51 PC camera controllers: + +Vendor ID Product ID +--------- ---------- +0x102c 0x6151 +0x102c 0x6251 +0x102c 0x6253 +0x102c 0x6254 +0x102c 0x6255 +0x102c 0x6256 +0x102c 0x6257 +0x102c 0x6258 +0x102c 0x6259 +0x102c 0x625a +0x102c 0x625b +0x102c 0x625c +0x102c 0x625d +0x102c 0x625e +0x102c 0x625f +0x102c 0x6260 +0x102c 0x6261 +0x102c 0x6262 +0x102c 0x6263 +0x102c 0x6264 +0x102c 0x6265 +0x102c 0x6266 +0x102c 0x6267 +0x102c 0x6268 +0x102c 0x6269 + +The following image sensors are supported: + +Model Manufacturer +----- ------------ +TAS5130D1B Taiwan Advanced Sensor Corporation + +All the available control settings of each image sensor are supported through +the V4L2 interface. + + +10. Notes for V4L2 application developers +======================================== +This driver follows the V4L2 API specifications. In particular, it enforces two +rules: + +- exactly one I/O method, either "mmap" or "read", is associated with each +file descriptor. Once it is selected, the application must close and reopen the +device to switch to the other I/O method; + +- although it is not mandatory, previously mapped buffer memory should always +be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's. +The same number of buffers as before will be allocated again to match the size +of the new video frames, so you have to map the buffers again before any I/O +attempts on them. + +Consistently with the hardware limits, this driver also supports image +downscaling with arbitrary scaling factors from 1 and 2 in both directions. +However, the V4L2 API specifications don't correctly define how the scaling +factor can be chosen arbitrarily by the "negotiation" of the "source" and +"target" rectangles. To work around this flaw, we have added the convention +that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the +scaling factor is restored to 1. + +This driver supports two different video formats: the first one is the "8-bit +Sequential Bayer" format and can be used to obtain uncompressed video data +from the device through the current I/O method, while the second one provides +"raw" compressed video data (without frame headers not related to the +compressed data). The current compression quality may vary from 0 to 1 and can +be selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP +V4L2 ioctl's. + + +11. Contact information +======================= +The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>. + +GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is +'FCE635A4'; the public 1024-bit key should be available at any keyserver; +the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt index 3f8a119db31b..c6b76414172c 100644 --- a/Documentation/usb/sn9c102.txt +++ b/Documentation/usb/sn9c102.txt @@ -17,16 +17,15 @@ Index 7. Module parameters 8. Optional device control through "sysfs" 9. Supported devices -10. How to add plug-in's for new image sensors -11. Notes for V4L2 application developers -12. Video frame formats -13. Contact information -14. Credits +10. Notes for V4L2 application developers +11. Video frame formats +12. Contact information +13. Credits 1. Copyright ============ -Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> +Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> 2. Disclaimer @@ -54,9 +53,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 4. Overview and features ======================== -This driver attempts to support the video and audio streaming capabilities of -the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 PC Camera -Controllers. +This driver attempts to support the video interface of the devices mounting the +SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers. It's worth to note that SONiX has never collaborated with the author during the development of this project, despite several requests for enough detailed @@ -78,6 +76,7 @@ Some of the features of the driver are: - available mmap or read/poll methods for video streaming through isochronous data transfers; - automatic detection of image sensor; +- support for built-in microphone interface; - support for any window resolutions and optional panning within the maximum pixel area of image sensor; - image downscaling with arbitrary scaling factors from 1, 2 and 4 in both @@ -96,7 +95,7 @@ Some of the features of the driver are: parameters" paragraph); - up to 64 cameras can be handled at the same time; they can be connected and disconnected from the host many times without turning off the computer, if - your system supports hotplugging; + the system supports hotplugging; - no known bugs. @@ -112,6 +111,12 @@ corresponding modules must be compiled: # CONFIG_VIDEO_DEV=m +To enable advanced debugging functionality on the device through /sysfs: + + # Multimedia devices + # + CONFIG_VIDEO_ADV_DEBUG=y + # USB support # CONFIG_USB=m @@ -125,6 +130,21 @@ necessary: CONFIG_USB_UHCI_HCD=m CONFIG_USB_OHCI_HCD=m +The SN9C103 controller also provides a built-in microphone interface. It is +supported by the USB Audio driver thanks to the ALSA API: + + # Sound + # + CONFIG_SOUND=y + + # Advanced Linux Sound Architecture + # + CONFIG_SND=m + + # USB devices + # + CONFIG_SND_USB_AUDIO=m + And finally: # USB Multimedia devices @@ -153,7 +173,7 @@ analyze kernel messages and verify that the loading process has gone well: Module parameters are listed below: ------------------------------------------------------------------------------- Name: video_nr -Type: int array (min = 0, max = 64) +Type: short array (min = 0, max = 64) Syntax: <-1|n[,...]> Description: Specify V4L2 minor mode number: -1 = use next available @@ -165,19 +185,19 @@ Description: Specify V4L2 minor mode number: other camera. Default: -1 ------------------------------------------------------------------------------- -Name: force_munmap; +Name: force_munmap Type: bool array (min = 0, max = 64) Syntax: <0|1[,...]> Description: Force the application to unmap previously mapped buffer memory before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not all the applications support this feature. This parameter is specific for each detected camera. - 0 = do not force memory unmapping" - 1 = force memory unmapping (save memory)" + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- Name: debug -Type: int +Type: ushort Syntax: <n> Description: Debugging information level, from 0 to 3: 0 = none (use carefully) @@ -187,14 +207,15 @@ Description: Debugging information level, from 0 to 3: Level 3 is useful for testing only, when only one device is used. It also shows some more informations about the hardware being detected. This parameter can be changed at - runtime thanks to the /sys filesystem. + runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- 8. Optional device control through "sysfs" [1] ========================================== -It is possible to read and write both the SN9C10x and the image sensor +If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled, +it is possible to read and write both the SN9C10x and the image sensor registers by using the "sysfs" filesystem interface. Every time a supported device is recognized, a write-only file named "green" is @@ -236,7 +257,7 @@ serialized. The sysfs interface also provides the "frame_header" entry, which exports the frame header of the most recent requested and captured video frame. The header -is 12-bytes long and is appended to every video frame by the SN9C10x +is always 18-bytes long and is appended to every video frame by the SN9C10x controllers. As an example, this additional information can be used by the user application for implementing auto-exposure features via software. @@ -250,7 +271,8 @@ Byte # Value Description 0x03 0xC4 Frame synchronisation pattern. 0x04 0xC4 Frame synchronisation pattern. 0x05 0x96 Frame synchronisation pattern. -0x06 0x00 or 0x01 Unknown meaning. The exact value depends on the chip. +0x06 0xXX Unknown meaning. The exact value depends on the chip; + possible values are 0x00, 0x01 and 0x20. 0x07 0xXX Variable value, whose bits are ff00uzzc, where ff is a frame counter, u is unknown, zz is a size indicator (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for @@ -267,12 +289,23 @@ Byte # Value Description times the area outside of the specified AE area. For images that are not pure white, the value scales down according to relative whiteness. + according to relative whiteness. + +The following bytes are used by the SN9C103 bridge only: + +0x0C 0xXX Unknown meaning +0x0D 0xXX Unknown meaning +0x0E 0xXX Unknown meaning +0x0F 0xXX Unknown meaning +0x10 0xXX Unknown meaning +0x11 0xXX Unknown meaning The AE area (sx, sy, ex, ey) in the active window can be set by programming the registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit corresponds to 32 pixels. -[1] The frame header has been documented by Bertrik Sikken. +[1] Part of the meaning of the frame header has been documented by Bertrik + Sikken. 9. Supported devices @@ -298,6 +331,7 @@ Vendor ID Product ID 0x0c45 0x602b 0x0c45 0x602c 0x0c45 0x602d +0x0c45 0x602e 0x0c45 0x6030 0x0c45 0x6080 0x0c45 0x6082 @@ -348,18 +382,7 @@ appreciated. Non-available hardware will not be supported by the author of this driver. -10. How to add plug-in's for new image sensors -============================================== -It should be easy to write plug-in's for new sensors by using the small API -that has been created for this purpose, which is present in "sn9c102_sensor.h" -(documentation is included there). As an example, have a look at the code in -"sn9c102_pas106b.c", which uses the mentioned interface. - -At the moment, possible unsupported image sensors are: CIS-VF10 (VGA), -OV7620 (VGA), OV7630 (VGA). - - -11. Notes for V4L2 application developers +10. Notes for V4L2 application developers ========================================= This driver follows the V4L2 API specifications. In particular, it enforces two rules: @@ -394,7 +417,7 @@ initialized (as described in the documentation of the API for the image sensors supplied by this driver). -12. Video frame formats [1] +11. Video frame formats [1] ======================= The SN9C10x PC Camera Controllers can send images in two possible video formats over the USB: either native "Sequential RGB Bayer" or Huffman @@ -455,7 +478,7 @@ The following Huffman codes have been found: documented by Bertrik Sikken. -13. Contact information +12. Contact information ======================= The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>. @@ -464,7 +487,7 @@ GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. -14. Credits +13. Credits =========== Many thanks to following persons for their contribute (listed in alphabetical order): @@ -480,5 +503,5 @@ order): - Bertrik Sikken, who reverse-engineered and documented the Huffman compression algorithm used in the SN9C10x controllers and implemented the first decoder; - Mizuno Takafumi for the donation of a webcam; -- An "anonymous" donator (who didn't want his name to be revealed) for the +- an "anonymous" donator (who didn't want his name to be revealed) for the donation of a webcam. diff --git a/Documentation/usb/w9968cf.txt b/Documentation/usb/w9968cf.txt index 18a47738d56c..9d46cd0b19e3 100644 --- a/Documentation/usb/w9968cf.txt +++ b/Documentation/usb/w9968cf.txt @@ -57,16 +57,12 @@ based cameras should be supported as well. The driver is divided into two modules: the basic one, "w9968cf", is needed for the supported devices to work; the second one, "w9968cf-vpp", is an optional module, which provides some useful video post-processing functions like video -decoding, up-scaling and colour conversions. Once the driver is installed, -every time an application tries to open a recognized device, "w9968cf" checks -the presence of the "w9968cf-vpp" module and loads it automatically by default. +decoding, up-scaling and colour conversions. -Please keep in mind that official kernels do not include the second module for -performance purposes. However it is always recommended to download and install -the latest and complete release of the driver, replacing the existing one, if -present: it will be still even possible not to load the "w9968cf-vpp" module at -all, if you ever want to. Another important missing feature of the version in -the official Linux 2.4 kernels is the writeable /proc filesystem interface. +Note that the official kernels do neither include nor support the second +module for performance purposes. Therefore, it is always recommended to +download and install the latest and complete release of the driver, +replacing the existing one, if present. The latest and full-featured version of the W996[87]CF driver can be found at: http://www.linux-projects.org. Please refer to the documentation included in @@ -201,22 +197,6 @@ Note: The kernel must be compiled with the CONFIG_KMOD option enabled for the 'ovcamchip' module to be loaded and for this parameter to be present. ------------------------------------------------------------------------------- -Name: vppmod_load -Type: bool -Syntax: <0|1> -Description: Automatic 'w9968cf-vpp' module loading: 0 disabled, 1 enabled. - If enabled, every time an application attempts to open a - camera, 'insmod' searches for the video post-processing module - in the system and loads it automatically (if present). - The optional 'w9968cf-vpp' module adds extra image manipulation - capabilities to the 'w9968cf' module,like software up-scaling, - colour conversions and video decompression for very high frame - rates. -Default: 1 -Note: The kernel must be compiled with the CONFIG_KMOD option - enabled for the 'w9968cf-vpp' module to be loaded and for - this parameter to be present. -------------------------------------------------------------------------------- Name: simcams Type: int Syntax: <n> diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 56e194f1a0b0..8bea3fbd0548 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -42,4 +42,4 @@ 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] - 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50] + 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index cb3a59bbeb17..8a352597830f 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -1,7 +1,7 @@ 0 -> UNKNOWN/GENERIC 1 -> Proteus Pro [philips reference design] [1131:2001,1131:2001] 2 -> LifeView FlyVIDEO3000 [5168:0138,4e42:0138] - 3 -> LifeView FlyVIDEO2000 [5168:0138] + 3 -> LifeView/Typhoon FlyVIDEO2000 [5168:0138,4e42:0138] 4 -> EMPRESS [1131:6752] 5 -> SKNet Monster TV [1131:4e85] 6 -> Tevion MD 9717 @@ -53,12 +53,12 @@ 52 -> AverMedia AverTV/305 [1461:2108] 53 -> ASUS TV-FM 7135 [1043:4845] 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214] - 55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306] + 55 -> LifeView FlyDVB-T DUO [5168:0306] 56 -> Avermedia AVerTV 307 [1461:a70a] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f] 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370] 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134 - 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502] + 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus [5168:0502,4e42:0502] 61 -> Philips TOUGH DVB-T reference design [1131:2004] 62 -> Compro VideoMate TV Gold+II 63 -> Kworld Xpert TV PVR7134 diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration new file mode 100644 index 000000000000..c52820fcf500 --- /dev/null +++ b/Documentation/vm/page_migration @@ -0,0 +1,129 @@ +Page migration +-------------- + +Page migration allows the moving of the physical location of pages between +nodes in a numa system while the process is running. This means that the +virtual addresses that the process sees do not change. However, the +system rearranges the physical location of those pages. + +The main intend of page migration is to reduce the latency of memory access +by moving pages near to the processor where the process accessing that memory +is running. + +Page migration allows a process to manually relocate the node on which its +pages are located through the MF_MOVE and MF_MOVE_ALL options while setting +a new memory policy. The pages of process can also be relocated +from another process using the sys_migrate_pages() function call. The +migrate_pages function call takes two sets of nodes and moves pages of a +process that are located on the from nodes to the destination nodes. + +Manual migration is very useful if for example the scheduler has relocated +a process to a processor on a distant node. A batch scheduler or an +administrator may detect the situation and move the pages of the process +nearer to the new processor. At some point in the future we may have +some mechanism in the scheduler that will automatically move the pages. + +Larger installations usually partition the system using cpusets into +sections of nodes. Paul Jackson has equipped cpusets with the ability to +move pages when a task is moved to another cpuset. This allows automatic +control over locality of a process. If a task is moved to a new cpuset +then also all its pages are moved with it so that the performance of the +process does not sink dramatically (as is the case today). + +Page migration allows the preservation of the relative location of pages +within a group of nodes for all migration techniques which will preserve a +particular memory allocation pattern generated even after migrating a +process. This is necessary in order to preserve the memory latencies. +Processes will run with similar performance after migration. + +Page migration occurs in several steps. First a high level +description for those trying to use migrate_pages() and then +a low level description of how the low level details work. + +A. Use of migrate_pages() +------------------------- + +1. Remove pages from the LRU. + + Lists of pages to be migrated are generated by scanning over + pages and moving them into lists. This is done by + calling isolate_lru_page() or __isolate_lru_page(). + Calling isolate_lru_page increases the references to the page + so that it cannot vanish under us. + +2. Generate a list of newly allocates page to move the contents + of the first list to. + +3. The migrate_pages() function is called which attempts + to do the migration. It returns the moved pages in the + list specified as the third parameter and the failed + migrations in the fourth parameter. The first parameter + will contain the pages that could still be retried. + +4. The leftover pages of various types are returned + to the LRU using putback_to_lru_pages() or otherwise + disposed of. The pages will still have the refcount as + increased by isolate_lru_pages()! + +B. Operation of migrate_pages() +-------------------------------- + +migrate_pages does several passes over its list of pages. A page is moved +if all references to a page are removable at the time. + +Steps: + +1. Lock the page to be migrated + +2. Insure that writeback is complete. + +3. Make sure that the page has assigned swap cache entry if + it is an anonyous page. The swap cache reference is necessary + to preserve the information contain in the page table maps. + +4. Prep the new page that we want to move to. It is locked + and set to not being uptodate so that all accesses to the new + page immediately lock while we are moving references. + +5. All the page table references to the page are either dropped (file backed) + or converted to swap references (anonymous pages). This should decrease the + reference count. + +6. The radix tree lock is taken + +7. The refcount of the page is examined and we back out if references remain + otherwise we know that we are the only one referencing this page. + +8. The radix tree is checked and if it does not contain the pointer to this + page then we back out. + +9. The mapping is checked. If the mapping is gone then a truncate action may + be in progress and we back out. + +10. The new page is prepped with some settings from the old page so that accesses + to the new page will be discovered to have the correct settings. + +11. The radix tree is changed to point to the new page. + +12. The reference count of the old page is dropped because the reference has now + been removed. + +13. The radix tree lock is dropped. + +14. The page contents are copied to the new page. + +15. The remaining page flags are copied to the new page. + +16. The old page flags are cleared to indicate that the page does + not use any information anymore. + +17. Queued up writeback on the new page is triggered. + +18. If swap pte's were generated for the page then remove them again. + +19. The locks are dropped from the old and new page. + +20. The new page is moved to the LRU. + +Christoph Lameter, December 19, 2005. + diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 9c5fc15d03d1..153740f460a6 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -40,6 +40,18 @@ APICs no_timer_check Don't check the IO-APIC timer. This can work around problems with incorrect timer initialization on some boards. + apicmaintimer Run time keeping from the local APIC timer instead + of using the PIT/HPET interrupt for this. This is useful + when the PIT/HPET interrupts are unreliable. + + noapicmaintimer Don't do time keeping using the APIC timer. + Useful when this option was auto selected, but doesn't work. + + apicpmtimer + Do APIC timer calibration using the pmtimer. Implies + apicmaintimer. Useful when your PIT timer is totally + broken. + Early Console syntax: earlyprintk=vga diff --git a/MAINTAINERS b/MAINTAINERS index ff16eac8cf5b..9c592aa0280c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -540,7 +540,8 @@ S: Supported BTTV VIDEO4LINUX DRIVER P: Mauro Carvalho Chehab -M: mchehab@brturbo.com.br +M: mchehab@infradead.org +M: v4l-dvb-maintainer@linuxtv.org L: video4linux-list@redhat.com W: http://linuxtv.org T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git @@ -557,7 +558,8 @@ S: Supported CONFIGFS P: Joel Becker -M: Joel Becker <joel.becker@oracle.com> +M: joel.becker@oracle.com +L: linux-kernel@vger.kernel.org S: Supported CIRRUS LOGIC GENERIC FBDEV DRIVER @@ -836,11 +838,12 @@ S: Maintained DVB SUBSYSTEM AND DRIVERS P: LinuxTV.org Project -M: linux-dvb-maintainer@linuxtv.org +M: mchehab@infradead.org +M: v4l-dvb-maintainer@linuxtv.org L: linux-dvb@linuxtv.org (subscription required) W: http://linuxtv.org/ T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git -S: Supported +S: Maintained EATA-DMA SCSI DRIVER P: Michael Neuffer @@ -867,6 +870,15 @@ L: ebtables-devel@lists.sourceforge.net W: http://ebtables.sourceforge.net/ S: Maintained +EDAC-CORE +P: Doug Thompson +M: norsk5@xmission.com, dthompson@linuxnetworx.com +P: Dave Peterson +M: dsp@llnl.gov, dave_peterson@pobox.com +L: bluesmoke-devel@lists.sourceforge.net +W: bluesmoke.sourceforge.net +S: Maintained + EEPRO100 NETWORK DRIVER P: Andrey V. Savochkin M: saw@saw.sw.com.sg @@ -919,6 +931,12 @@ M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com L: ext3-users@redhat.com S: Maintained +F71805F HARDWARE MONITORING DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: lm-sensors@lm-sensors.org +S: Maintained + FARSYNC SYNCHRONOUS DRIVER P: Kevin Curtis M: kevin.curtis@farsite.co.uk @@ -1167,8 +1185,8 @@ T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git S: Maintained SN-IA64 (Itanium) SUB-PLATFORM -P: Greg Edwards -M: edwardsg@sgi.com +P: Jes Sorensen +M: jes@sgi.com L: linux-altix@sgi.com L: linux-ia64@vger.kernel.org W: http://www.sgi.com/altix @@ -1398,7 +1416,7 @@ IRDA SUBSYSTEM P: Jean Tourrilhes L: irda-users@lists.sourceforge.net (subscribers-only) W: http://irda.sourceforge.net/ -S: Maintained +S: Odd Fixes ISAPNP P: Jaroslav Kysela @@ -1843,7 +1861,14 @@ M: yoshfuji@linux-ipv6.org P: Patrick McHardy M: kaber@coreworks.de L: netdev@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/davem/net-2.6.git +T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git +S: Maintained + +NETWORKING [WIRELESS] +P: John W. Linville +M: linville@tuxdriver.com +L: netdev@vger.kernel.org +T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained IPVS @@ -1968,7 +1993,6 @@ M: philb@gnu.org P: Tim Waugh M: tim@cyberelk.net P: David Campbell -M: campbell@torque.net P: Andrea Arcangeli M: andrea@suse.de L: linux-parport@lists.infradead.org @@ -2208,7 +2232,23 @@ P: Martin Schwidefsky M: schwidefsky@de.ibm.com M: linux390@de.ibm.com L: linux-390@vm.marist.edu -W: http://oss.software.ibm.com/developerworks/opensource/linux390 +W: http://www.ibm.com/developerworks/linux/linux390/ +S: Supported + +S390 NETWORK DRIVERS +P: Frank Pavlic +M: fpavlic@de.ibm.com +M: linux390@de.ibm.com +L: linux-390@vm.marist.edu +W: http://www.ibm.com/developerworks/linux/linux390/ +S: Supported + +S390 ZFCP DRIVER +P: Andreas Herrmann +M: aherrman@de.ibm.com +M: linux390@de.ibm.com +L: linux-390@vm.marist.edu +W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported SAA7146 VIDEO4LINUX-2 DRIVER @@ -2282,7 +2322,7 @@ S: Supported SELINUX SECURITY MODULE P: Stephen Smalley -M: sds@epoch.ncsc.mil +M: sds@tycho.nsa.gov P: James Morris M: jmorris@namei.org L: linux-kernel@vger.kernel.org (kernel issues) @@ -2536,11 +2576,11 @@ S: Maintained TIPC NETWORK LAYER P: Per Liden -M: per.liden@nospam.ericsson.com +M: per.liden@ericsson.com P: Jon Maloy -M: jon.maloy@nospam.ericsson.com +M: jon.maloy@ericsson.com P: Allan Stephens -M: allan.stephens@nospam.windriver.com +M: allan.stephens@windriver.com L: tipc-discussion@lists.sourceforge.net W: http://tipc.sourceforge.net/ W: http://tipc.cslab.ericsson.net/ @@ -2657,6 +2697,14 @@ M: dbrownell@users.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB ET61X[12]51 DRIVER +P: Luca Risolia +M: luca.risolia@studio.unibo.it +L: linux-usb-devel@lists.sourceforge.net +L: video4linux-list@redhat.com +W: http://www.linux-projects.org +S: Maintained + USB HID/HIDBP DRIVERS P: Vojtech Pavlik M: vojtech@suse.cz @@ -2820,6 +2868,7 @@ USB SN9C10x DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb-devel@lists.sourceforge.net +L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -2849,6 +2898,7 @@ USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb-devel@lists.sourceforge.net +L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -2930,7 +2980,8 @@ S: Maintained VIDEO FOR LINUX P: Mauro Carvalho Chehab -M: mchehab@brturbo.com.br +M: mchehab@infradead.org +M: v4l-dvb-maintainer@linuxtv.org L: video4linux-list@redhat.com W: http://linuxtv.org T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 16 -EXTRAVERSION =-rc1 +EXTRAVERSION =-rc3 NAME=Sliding Snow Leopard # *DOCUMENTATION* @@ -442,7 +442,7 @@ export KBUILD_DEFCONFIG config %config: scripts_basic outputmakefile FORCE $(Q)mkdir -p include/linux $(Q)$(MAKE) $(build)=scripts/kconfig $@ - $(Q)$(MAKE) .kernelrelease + $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease else # =========================================================================== diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c index 8f2e5c718b50..6c56c754a0b5 100644 --- a/arch/alpha/kernel/asm-offsets.c +++ b/arch/alpha/kernel/asm-offsets.c @@ -28,6 +28,7 @@ void foo(void) DEFINE(TASK_GID, offsetof(struct task_struct, gid)); DEFINE(TASK_EGID, offsetof(struct task_struct, egid)); DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent)); + DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader)); DEFINE(TASK_TGID, offsetof(struct task_struct, tgid)); BLANK(); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index e38671c922bc..7af15bf7e5ab 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -879,17 +879,19 @@ sys_getxpid: /* See linux/kernel/timer.c sys_getppid for discussion about this loop. */ - ldq $3, TASK_REAL_PARENT($2) -1: ldl $1, TASK_TGID($3) + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + ldl $0, TASK_TGID($2) +1: ldl $1, TASK_TGID($4) #ifdef CONFIG_SMP - mov $3, $4 + mov $4, $5 mb - ldq $3, TASK_REAL_PARENT($2) - cmpeq $3, $4, $4 - beq $4, 1b + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + cmpeq $4, $5, $5 + beq $5, 1b #endif stq $1, 80($sp) - ldl $0, TASK_TGID($2) ret .end sys_getxpid diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 76be5cf0de13..9006063e7369 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -68,34 +68,32 @@ show_interrupts(struct seq_file *p, void *v) #ifdef CONFIG_SMP int j; #endif - int i = *(loff_t *) v; + int irq = *(loff_t *) v; struct irqaction * action; unsigned long flags; #ifdef CONFIG_SMP - if (i == 0) { + if (irq == 0) { seq_puts(p, " "); - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - seq_printf(p, "CPU%d ", i); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ", j); seq_putc(p, '\n'); } #endif - if (i < ACTUAL_NR_IRQS) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; + if (irq < ACTUAL_NR_IRQS) { + spin_lock_irqsave(&irq_desc[irq].lock, flags); + action = irq_desc[irq].action; if (!action) goto unlock; - seq_printf(p, "%3d: ",i); + seq_printf(p, "%3d: ", irq); #ifndef CONFIG_SMP - seq_printf(p, "%10u ", kstat_irqs(i)); + seq_printf(p, "%10u ", kstat_irqs(irq)); #else - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]); #endif - seq_printf(p, " %14s", irq_desc[i].handler->typename); + seq_printf(p, " %14s", irq_desc[irq].handler->typename); seq_printf(p, " %c%s", (action->flags & SA_INTERRUPT)?'+':' ', action->name); @@ -108,13 +106,12 @@ show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == ACTUAL_NR_IRQS) { + spin_unlock_irqrestore(&irq_desc[irq].lock, flags); + } else if (irq == ACTUAL_NR_IRQS) { #ifdef CONFIG_SMP seq_puts(p, "IPI: "); - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - seq_printf(p, "%10lu ", cpu_data[i].ipi_count); + for_each_online_cpu(j) + seq_printf(p, "%10lu ", cpu_data[j].ipi_count); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10lu\n", irq_err_count); @@ -122,7 +119,6 @@ unlock: return 0; } - /* * handle_irq handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 01fe990d3e54..7fb14f42a125 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -960,7 +960,7 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs) return -EFAULT; } - return do_utimes(filename, tvs ? ktvs : NULL); + return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL); } #define MAX_SELECT_SECONDS \ diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 4b873527ce1c..02c2db08114a 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -73,9 +73,6 @@ cpumask_t cpu_online_map; EXPORT_SYMBOL(cpu_online_map); -/* cpus reported in the hwrpb */ -static unsigned long hwrpb_cpu_present_mask __initdata = 0; - int smp_num_probed; /* Internal processor count */ int smp_num_cpus = 1; /* Number that came online. */ @@ -442,7 +439,7 @@ setup_smp(void) if ((cpu->flags & 0x1cc) == 0x1cc) { smp_num_probed++; /* Assume here that "whami" == index */ - hwrpb_cpu_present_mask |= (1UL << i); + cpu_set(i, cpu_possible_map); cpu->pal_revision = boot_cpu_palrev; } @@ -453,12 +450,12 @@ setup_smp(void) } } else { smp_num_probed = 1; - hwrpb_cpu_present_mask = (1UL << boot_cpuid); + cpu_set(boot_cpuid, cpu_possible_map); } cpu_present_mask = cpumask_of_cpu(boot_cpuid); printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n", - smp_num_probed, hwrpb_cpu_present_mask); + smp_num_probed, cpu_possible_map.bits[0]); } /* @@ -467,8 +464,6 @@ setup_smp(void) void __init smp_prepare_cpus(unsigned int max_cpus) { - int cpu_count, i; - /* Take care of some initial bookkeeping. */ memset(ipi_data, 0, sizeof(ipi_data)); @@ -486,19 +481,7 @@ smp_prepare_cpus(unsigned int max_cpus) printk(KERN_INFO "SMP starting up secondaries.\n"); - cpu_count = 1; - for (i = 0; (i < NR_CPUS) && (cpu_count < max_cpus); i++) { - if (i == boot_cpuid) - continue; - - if (((hwrpb_cpu_present_mask >> i) & 1) == 0) - continue; - - cpu_set(i, cpu_possible_map); - cpu_count++; - } - - smp_num_cpus = cpu_count; + smp_num_cpus = smp_num_probed; } void __devinit diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5959e36c3b4c..15dc1a0dffbb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -10,9 +10,9 @@ config ARM default y help The ARM series is a line of low-power-consumption RISC chip designs - licensed by ARM ltd and targeted at embedded applications and + licensed by ARM Ltd and targeted at embedded applications and handhelds such as the Compaq IPAQ. ARM-based PCs are no longer - manufactured, but legacy ARM-based PC hardware remains popular in + manufactured, but legacy ARM-based PC hardware remains popular in Europe. There is an ARM Linux project with a web page at <http://www.arm.linux.org.uk/>. @@ -69,6 +69,9 @@ config GENERIC_ISA_DMA config FIQ bool +config ARCH_MTD_XIP + bool + source "init/Kconfig" menu "System Type" @@ -81,45 +84,62 @@ config ARCH_CLPS7500 bool "Cirrus-CL-PS7500FE" select TIMER_ACORN select ISA + help + Support for the Cirrus Logic PS7500FE system-on-a-chip. config ARCH_CLPS711X bool "CLPS711x/EP721x-based" + help + Support for Cirrus Logic 711x/721x based boards. config ARCH_CO285 bool "Co-EBSA285" select FOOTBRIDGE select FOOTBRIDGE_ADDIN + help + Support for Intel's EBSA285 companion chip. config ARCH_EBSA110 bool "EBSA-110" select ISA help This is an evaluation board for the StrongARM processor available - from Digital. It has limited hardware on-board, including an onboard + from Digital. It has limited hardware on-board, including an Ethernet interface, two PCMCIA sockets, two serial ports and a parallel port. config ARCH_FOOTBRIDGE bool "FootBridge" select FOOTBRIDGE + help + Support for systems based on the DC21285 companion chip + ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. config ARCH_INTEGRATOR bool "Integrator" select ARM_AMBA select ICST525 + help + Support for ARM's Integrator platform. config ARCH_IOP3XX bool "IOP3xx-based" select PCI + help + Support for Intel's IOP3XX (XScale) family of processors. config ARCH_IXP4XX bool "IXP4xx-based" select DMABOUNCE select PCI + help + Support for Intel's IXP4XX (XScale) family of processors. config ARCH_IXP2000 bool "IXP2400/2800-based" select PCI + help + Support for Intel's IXP2400/2800 (XScale) family of processors. config ARCH_L7200 bool "LinkUp-L7200" @@ -136,6 +156,9 @@ config ARCH_L7200 config ARCH_PXA bool "PXA2xx-based" + select ARCH_MTD_XIP + help + Support for Intel's PXA2XX processor line. config ARCH_RPC bool "RiscPC" @@ -152,19 +175,25 @@ config ARCH_SA1100 bool "SA1100-based" select ISA select ARCH_DISCONTIGMEM_ENABLE + select ARCH_MTD_XIP + help + Support for StrongARM 11x0 based boards. config ARCH_S3C2410 bool "Samsung S3C2410" help Samsung S3C2410X CPU based systems, such as the Simtec Electronics BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or - the Samsung SMDK2410 development board (and derviatives). + the Samsung SMDK2410 development board (and derivatives). config ARCH_SHARK bool "Shark" select ISA select ISA_DMA select PCI + help + Support for the StrongARM based Digital DNARD machine, also known + as "Shark" (<http://www.shark-linux.de/shark.html>). config ARCH_LH7A40X bool "Sharp LH7A40X" @@ -176,6 +205,8 @@ config ARCH_LH7A40X config ARCH_OMAP bool "TI OMAP" + help + Support for TI's OMAP platform (OMAP1 and OMAP2). config ARCH_VERSATILE bool "Versatile" @@ -194,6 +225,8 @@ config ARCH_REALVIEW config ARCH_IMX bool "IMX" + help + Support for Motorola's i.MX family of processors (MX1, MXL). config ARCH_H720X bool "Hynix-HMS720x-based" @@ -210,8 +243,8 @@ config ARCH_AAEC2000 config ARCH_AT91RM9200 bool "AT91RM9200" help - Say Y here if you intend to run this kernel on an AT91RM9200-based - board. + Say Y here if you intend to run this kernel on an Atmel + AT91RM9200-based board. endchoice @@ -417,8 +450,8 @@ config AEABI To use this you need GCC version 4.0.0 or later. config OABI_COMPAT - bool "Allow old ABI binaries to run with this kernel" - depends on AEABI + bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)" + depends on AEABI && EXPERIMENTAL default y help This option preserves the old syscall interface along with the diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index aaa47400eb9c..db3389d8e027 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -334,7 +334,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size mov r1, #0x12 orr r1, r1, #3 << 10 add r2, r3, #16384 -1: cmp r1, r8 @ if virt > start of RAM +1: cmp r1, r9 @ if virt > start of RAM orrhs r1, r1, #0x0c @ set cacheable, bufferable cmp r1, r10 @ if virt > end of RAM bichs r1, r1, #0x0c @ clear cacheable, bufferable diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index 5cdd13acf8ff..1fe73d198888 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index 20838ccf1da7..b7d934cdb1b7 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig index 6886001b5366..4a8564f386af 100644 --- a/arch/arm/configs/bast_defconfig +++ b/arch/arm/configs/bast_defconfig @@ -14,8 +14,7 @@ CONFIG_GENERIC_IOMAP=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y # @@ -360,7 +359,6 @@ CONFIG_BLK_DEV_IDE_BAST=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -781,7 +779,6 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index 15468a0cf70e..c9aa878e610a 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig @@ -13,8 +13,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -308,9 +307,7 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set CONFIG_MTD_OBSOLETE_CHIPS=y -# CONFIG_MTD_AMDSTD is not set CONFIG_MTD_SHARP=y -# CONFIG_MTD_JEDEC is not set # # Mapping drivers for chip access @@ -396,7 +393,6 @@ CONFIG_ATA_OVER_ETH=m # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -741,7 +737,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index 885a3184830a..94bd9932a402 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index 95a96a5462a0..1519124c5501 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index 9592e3925c79..5fdaf3ce9d56 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig @@ -171,7 +171,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware" +CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0" # CONFIG_XIP_KERNEL is not set # diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig index fbe312e757cb..3c73b707c2f3 100644 --- a/arch/arm/configs/ep80219_defconfig +++ b/arch/arm/configs/ep80219_defconfig @@ -522,6 +522,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig index c07628ceaf0c..32467160a6df 100644 --- a/arch/arm/configs/iq31244_defconfig +++ b/arch/arm/configs/iq31244_defconfig @@ -493,6 +493,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig index 18fa1615fdfd..b000da753c41 100644 --- a/arch/arm/configs/iq80321_defconfig +++ b/arch/arm/configs/iq80321_defconfig @@ -415,6 +415,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig index f50035de1fff..46c79e1efe07 100644 --- a/arch/arm/configs/iq80331_defconfig +++ b/arch/arm/configs/iq80331_defconfig @@ -496,6 +496,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig index 18b3f372ed68..11959b705d82 100644 --- a/arch/arm/configs/iq80332_defconfig +++ b/arch/arm/configs/iq80332_defconfig @@ -496,6 +496,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index d9d6bb86a6fa..c67fc449a11f 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -172,7 +172,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware" +CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0" # CONFIG_XIP_KERNEL is not set # diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 2dc9d499c7d7..60d66e82c51f 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig @@ -172,7 +172,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware" +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0" # CONFIG_XIP_KERNEL is not set # diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index ea8f4b478fa3..f54f3dcc5b33 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig @@ -172,7 +172,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000" +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0" # CONFIG_XIP_KERNEL is not set # diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 33f31080a98c..6695b07cf1ba 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,11 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc1 -# Sun Nov 13 17:41:24 2005 +# Linux kernel version: 2.6.16-rc2 +# Mon Feb 6 11:17:23 2006 # CONFIG_ARM=y CONFIG_MMU=y -CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_CALIBRATE_DELAY=y @@ -13,8 +12,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -29,27 +27,31 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y # # Loadable module support @@ -103,6 +105,7 @@ CONFIG_ARCH_S3C2410=y # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set # # S3C24XX Implementations @@ -161,7 +164,6 @@ CONFIG_CPU_TLB_V4WBI=y # Bus support # CONFIG_ISA=y -CONFIG_ISA_DMA_API=y # # PCCARD (PCMCIA/CardBus) support @@ -173,6 +175,7 @@ CONFIG_ISA_DMA_API=y # # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set +# CONFIG_AEABI is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -215,6 +218,8 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set CONFIG_APM=y # @@ -260,6 +265,11 @@ CONFIG_TCP_CONG_BIC=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -277,7 +287,6 @@ CONFIG_TCP_CONG_BIC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -301,6 +310,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # CONFIG_MTD=y @@ -413,8 +427,6 @@ CONFIG_PARPORT_1284=y # # Block devices # -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set @@ -473,7 +485,6 @@ CONFIG_BLK_DEV_IDE_BAST=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -504,7 +515,6 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_SMC91X is not set CONFIG_DM9000=y @@ -609,11 +619,11 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set # CONFIG_DIGIEPCA is not set -# CONFIG_ESPSERIAL is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set # CONFIG_SYNCLINKMP is not set +# CONFIG_SYNCLINK_GT is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set # CONFIG_SPECIALIX is not set @@ -627,6 +637,7 @@ CONFIG_SERIAL_NONSTANDARD=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y @@ -689,6 +700,7 @@ CONFIG_S3C2410_RTC=y # # TPM devices # +# CONFIG_TCG_TPM is not set # CONFIG_TELCLOCK is not set # @@ -733,6 +745,12 @@ CONFIG_SENSORS_EEPROM=m # CONFIG_I2C_DEBUG_CHIP is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Hardware Monitoring support # CONFIG_HWMON=y @@ -865,6 +883,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y CONFIG_INOTIFY=y @@ -896,10 +915,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_SYSFS=y # CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -968,6 +987,7 @@ CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -1023,12 +1043,13 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1037,6 +1058,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y # CONFIG_DEBUG_WAITQ is not set diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 75e6f9a94713..8c3035d5ffc9 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -7,337 +7,334 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * This file is included twice in entry-common.S + * This file is included thrice in entry-common.S */ -#ifndef NR_syscalls -#define NR_syscalls 328 -#else - -100: -/* 0 */ .long sys_restart_syscall - .long sys_exit - .long sys_fork_wrapper - .long sys_read - .long sys_write -/* 5 */ .long sys_open - .long sys_close - .long sys_ni_syscall /* was sys_waitpid */ - .long sys_creat - .long sys_link -/* 10 */ .long sys_unlink - .long sys_execve_wrapper - .long sys_chdir - .long OBSOLETE(sys_time) /* used by libc4 */ - .long sys_mknod -/* 15 */ .long sys_chmod - .long sys_lchown16 - .long sys_ni_syscall /* was sys_break */ - .long sys_ni_syscall /* was sys_stat */ - .long sys_lseek -/* 20 */ .long sys_getpid - .long sys_mount - .long OBSOLETE(sys_oldumount) /* used by libc4 */ - .long sys_setuid16 - .long sys_getuid16 -/* 25 */ .long OBSOLETE(sys_stime) - .long sys_ptrace - .long OBSOLETE(sys_alarm) /* used by libc4 */ - .long sys_ni_syscall /* was sys_fstat */ - .long sys_pause -/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */ - .long sys_ni_syscall /* was sys_stty */ - .long sys_ni_syscall /* was sys_getty */ - .long sys_access - .long sys_nice -/* 35 */ .long sys_ni_syscall /* was sys_ftime */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir -/* 40 */ .long sys_rmdir - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* was sys_prof */ -/* 45 */ .long sys_brk - .long sys_setgid16 - .long sys_getgid16 - .long sys_ni_syscall /* was sys_signal */ - .long sys_geteuid16 -/* 50 */ .long sys_getegid16 - .long sys_acct - .long sys_umount - .long sys_ni_syscall /* was sys_lock */ - .long sys_ioctl -/* 55 */ .long sys_fcntl - .long sys_ni_syscall /* was sys_mpx */ - .long sys_setpgid - .long sys_ni_syscall /* was sys_ulimit */ - .long sys_ni_syscall /* was sys_olduname */ -/* 60 */ .long sys_umask - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid -/* 65 */ .long sys_getpgrp - .long sys_setsid - .long sys_sigaction - .long sys_ni_syscall /* was sys_sgetmask */ - .long sys_ni_syscall /* was sys_ssetmask */ -/* 70 */ .long sys_setreuid16 - .long sys_setregid16 - .long sys_sigsuspend_wrapper - .long sys_sigpending - .long sys_sethostname -/* 75 */ .long sys_setrlimit - .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */ - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday -/* 80 */ .long sys_getgroups16 - .long sys_setgroups16 - .long OBSOLETE(old_select) /* used by libc4 */ - .long sys_symlink - .long sys_ni_syscall /* was sys_lstat */ -/* 85 */ .long sys_readlink - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long OBSOLETE(old_readdir) /* used by libc4 */ -/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod -/* 95 */ .long sys_fchown16 - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* was sys_profil */ - .long sys_statfs -/* 100 */ .long sys_fstatfs - .long sys_ni_syscall - .long OBSOLETE(sys_socketcall) - .long sys_syslog - .long sys_setitimer -/* 105 */ .long sys_getitimer - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall /* was sys_uname */ -/* 110 */ .long sys_ni_syscall /* was sys_iopl */ - .long sys_vhangup - .long sys_ni_syscall - .long OBSOLETE(sys_syscall) /* call a syscall */ - .long sys_wait4 -/* 115 */ .long sys_swapoff - .long sys_sysinfo - .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)) - .long sys_fsync - .long sys_sigreturn_wrapper -/* 120 */ .long sys_clone_wrapper - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall - .long sys_adjtimex -/* 125 */ .long sys_mprotect - .long sys_sigprocmask - .long sys_ni_syscall /* was sys_create_module */ - .long sys_init_module - .long sys_delete_module -/* 130 */ .long sys_ni_syscall /* was sys_get_kernel_syms */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush -/* 135 */ .long sys_sysfs - .long sys_personality - .long sys_ni_syscall /* .long _sys_afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 -/* 140 */ .long sys_llseek - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync -/* 145 */ .long sys_readv - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl -/* 150 */ .long sys_mlock - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam -/* 155 */ .long sys_sched_getparam - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max -/* 160 */ .long sys_sched_get_priority_min - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_arm_mremap - .long sys_setresuid16 -/* 165 */ .long sys_getresuid16 - .long sys_ni_syscall - .long sys_ni_syscall /* was sys_query_module */ - .long sys_poll - .long sys_nfsservctl -/* 170 */ .long sys_setresgid16 - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn_wrapper - .long sys_rt_sigaction -/* 175 */ .long sys_rt_sigprocmask - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend_wrapper -/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64) - .long ABI(sys_pwrite64, sys_oabi_pwrite64) - .long sys_chown16 - .long sys_getcwd - .long sys_capget -/* 185 */ .long sys_capset - .long sys_sigaltstack_wrapper - .long sys_sendfile - .long sys_ni_syscall - .long sys_ni_syscall -/* 190 */ .long sys_vfork_wrapper - .long sys_getrlimit - .long sys_mmap2 - .long ABI(sys_truncate64, sys_oabi_truncate64) - .long ABI(sys_ftruncate64, sys_oabi_ftruncate64) -/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64) - .long ABI(sys_lstat64, sys_oabi_lstat64) - .long ABI(sys_fstat64, sys_oabi_fstat64) - .long sys_lchown - .long sys_getuid -/* 200 */ .long sys_getgid - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid -/* 205 */ .long sys_getgroups - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid -/* 210 */ .long sys_setresgid - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid -/* 215 */ .long sys_setfsuid - .long sys_setfsgid - .long sys_getdents64 - .long sys_pivot_root - .long sys_mincore -/* 220 */ .long sys_madvise - .long ABI(sys_fcntl64, sys_oabi_fcntl64) - .long sys_ni_syscall /* TUX */ - .long sys_ni_syscall - .long sys_gettid -/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead) - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr -/* 230 */ .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr -/* 235 */ .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 -/* 240 */ .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_io_setup - .long sys_io_destroy -/* 245 */ .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_exit_group - .long sys_lookup_dcookie -/* 250 */ .long sys_epoll_create - .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl) - .long ABI(sys_epoll_wait, sys_oabi_epoll_wait) - .long sys_remap_file_pages - .long sys_ni_syscall /* sys_set_thread_area */ -/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime - .long sys_timer_gettime -/* 260 */ .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime - .long sys_clock_getres -/* 265 */ .long sys_clock_nanosleep - .long sys_statfs64_wrapper - .long sys_fstatfs64_wrapper - .long sys_tgkill - .long sys_utimes -/* 270 */ .long sys_arm_fadvise64_64 - .long sys_pciconfig_iobase - .long sys_pciconfig_read - .long sys_pciconfig_write - .long sys_mq_open -/* 275 */ .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive - .long sys_mq_notify - .long sys_mq_getsetattr -/* 280 */ .long sys_waitid - .long sys_socket - .long sys_bind - .long sys_connect - .long sys_listen -/* 285 */ .long sys_accept - .long sys_getsockname - .long sys_getpeername - .long sys_socketpair - .long sys_send -/* 290 */ .long sys_sendto - .long sys_recv - .long sys_recvfrom - .long sys_shutdown - .long sys_setsockopt -/* 295 */ .long sys_getsockopt - .long sys_sendmsg - .long sys_recvmsg - .long ABI(sys_semop, sys_oabi_semop) - .long sys_semget -/* 300 */ .long sys_semctl - .long sys_msgsnd - .long sys_msgrcv - .long sys_msgget - .long sys_msgctl -/* 305 */ .long sys_shmat - .long sys_shmdt - .long sys_shmget - .long sys_shmctl - .long sys_add_key -/* 310 */ .long sys_request_key - .long sys_keyctl - .long ABI(sys_semtimedop, sys_oabi_semtimedop) -/* vserver */ .long sys_ni_syscall - .long sys_ioprio_set -/* 315 */ .long sys_ioprio_get - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_mbind -/* 320 */ .long sys_get_mempolicy - .long sys_set_mempolicy - - .rept NR_syscalls - (. - 100b) / 4 - .long sys_ni_syscall - .endr +/* 0 */ CALL(sys_restart_syscall) + CALL(sys_exit) + CALL(sys_fork_wrapper) + CALL(sys_read) + CALL(sys_write) +/* 5 */ CALL(sys_open) + CALL(sys_close) + CALL(sys_ni_syscall) /* was sys_waitpid */ + CALL(sys_creat) + CALL(sys_link) +/* 10 */ CALL(sys_unlink) + CALL(sys_execve_wrapper) + CALL(sys_chdir) + CALL(OBSOLETE(sys_time)) /* used by libc4 */ + CALL(sys_mknod) +/* 15 */ CALL(sys_chmod) + CALL(sys_lchown16) + CALL(sys_ni_syscall) /* was sys_break */ + CALL(sys_ni_syscall) /* was sys_stat */ + CALL(sys_lseek) +/* 20 */ CALL(sys_getpid) + CALL(sys_mount) + CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */ + CALL(sys_setuid16) + CALL(sys_getuid16) +/* 25 */ CALL(OBSOLETE(sys_stime)) + CALL(sys_ptrace) + CALL(OBSOLETE(sys_alarm)) /* used by libc4 */ + CALL(sys_ni_syscall) /* was sys_fstat */ + CALL(sys_pause) +/* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */ + CALL(sys_ni_syscall) /* was sys_stty */ + CALL(sys_ni_syscall) /* was sys_getty */ + CALL(sys_access) + CALL(sys_nice) +/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */ + CALL(sys_sync) + CALL(sys_kill) + CALL(sys_rename) + CALL(sys_mkdir) +/* 40 */ CALL(sys_rmdir) + CALL(sys_dup) + CALL(sys_pipe) + CALL(sys_times) + CALL(sys_ni_syscall) /* was sys_prof */ +/* 45 */ CALL(sys_brk) + CALL(sys_setgid16) + CALL(sys_getgid16) + CALL(sys_ni_syscall) /* was sys_signal */ + CALL(sys_geteuid16) +/* 50 */ CALL(sys_getegid16) + CALL(sys_acct) + CALL(sys_umount) + CALL(sys_ni_syscall) /* was sys_lock */ + CALL(sys_ioctl) +/* 55 */ CALL(sys_fcntl) + CALL(sys_ni_syscall) /* was sys_mpx */ + CALL(sys_setpgid) + CALL(sys_ni_syscall) /* was sys_ulimit */ + CALL(sys_ni_syscall) /* was sys_olduname */ +/* 60 */ CALL(sys_umask) + CALL(sys_chroot) + CALL(sys_ustat) + CALL(sys_dup2) + CALL(sys_getppid) +/* 65 */ CALL(sys_getpgrp) + CALL(sys_setsid) + CALL(sys_sigaction) + CALL(sys_ni_syscall) /* was sys_sgetmask */ + CALL(sys_ni_syscall) /* was sys_ssetmask */ +/* 70 */ CALL(sys_setreuid16) + CALL(sys_setregid16) + CALL(sys_sigsuspend_wrapper) + CALL(sys_sigpending) + CALL(sys_sethostname) +/* 75 */ CALL(sys_setrlimit) + CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */ + CALL(sys_getrusage) + CALL(sys_gettimeofday) + CALL(sys_settimeofday) +/* 80 */ CALL(sys_getgroups16) + CALL(sys_setgroups16) + CALL(OBSOLETE(old_select)) /* used by libc4 */ + CALL(sys_symlink) + CALL(sys_ni_syscall) /* was sys_lstat */ +/* 85 */ CALL(sys_readlink) + CALL(sys_uselib) + CALL(sys_swapon) + CALL(sys_reboot) + CALL(OBSOLETE(old_readdir)) /* used by libc4 */ +/* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */ + CALL(sys_munmap) + CALL(sys_truncate) + CALL(sys_ftruncate) + CALL(sys_fchmod) +/* 95 */ CALL(sys_fchown16) + CALL(sys_getpriority) + CALL(sys_setpriority) + CALL(sys_ni_syscall) /* was sys_profil */ + CALL(sys_statfs) +/* 100 */ CALL(sys_fstatfs) + CALL(sys_ni_syscall) + CALL(OBSOLETE(sys_socketcall)) + CALL(sys_syslog) + CALL(sys_setitimer) +/* 105 */ CALL(sys_getitimer) + CALL(sys_newstat) + CALL(sys_newlstat) + CALL(sys_newfstat) + CALL(sys_ni_syscall) /* was sys_uname */ +/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */ + CALL(sys_vhangup) + CALL(sys_ni_syscall) + CALL(OBSOLETE(sys_syscall)) /* call a syscall */ + CALL(sys_wait4) +/* 115 */ CALL(sys_swapoff) + CALL(sys_sysinfo) + CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) + CALL(sys_fsync) + CALL(sys_sigreturn_wrapper) +/* 120 */ CALL(sys_clone_wrapper) + CALL(sys_setdomainname) + CALL(sys_newuname) + CALL(sys_ni_syscall) + CALL(sys_adjtimex) +/* 125 */ CALL(sys_mprotect) + CALL(sys_sigprocmask) + CALL(sys_ni_syscall) /* was sys_create_module */ + CALL(sys_init_module) + CALL(sys_delete_module) +/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */ + CALL(sys_quotactl) + CALL(sys_getpgid) + CALL(sys_fchdir) + CALL(sys_bdflush) +/* 135 */ CALL(sys_sysfs) + CALL(sys_personality) + CALL(sys_ni_syscall) /* CALL(_sys_afs_syscall) */ + CALL(sys_setfsuid16) + CALL(sys_setfsgid16) +/* 140 */ CALL(sys_llseek) + CALL(sys_getdents) + CALL(sys_select) + CALL(sys_flock) + CALL(sys_msync) +/* 145 */ CALL(sys_readv) + CALL(sys_writev) + CALL(sys_getsid) + CALL(sys_fdatasync) + CALL(sys_sysctl) +/* 150 */ CALL(sys_mlock) + CALL(sys_munlock) + CALL(sys_mlockall) + CALL(sys_munlockall) + CALL(sys_sched_setparam) +/* 155 */ CALL(sys_sched_getparam) + CALL(sys_sched_setscheduler) + CALL(sys_sched_getscheduler) + CALL(sys_sched_yield) + CALL(sys_sched_get_priority_max) +/* 160 */ CALL(sys_sched_get_priority_min) + CALL(sys_sched_rr_get_interval) + CALL(sys_nanosleep) + CALL(sys_arm_mremap) + CALL(sys_setresuid16) +/* 165 */ CALL(sys_getresuid16) + CALL(sys_ni_syscall) + CALL(sys_ni_syscall) /* was sys_query_module */ + CALL(sys_poll) + CALL(sys_nfsservctl) +/* 170 */ CALL(sys_setresgid16) + CALL(sys_getresgid16) + CALL(sys_prctl) + CALL(sys_rt_sigreturn_wrapper) + CALL(sys_rt_sigaction) +/* 175 */ CALL(sys_rt_sigprocmask) + CALL(sys_rt_sigpending) + CALL(sys_rt_sigtimedwait) + CALL(sys_rt_sigqueueinfo) + CALL(sys_rt_sigsuspend_wrapper) +/* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) + CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) + CALL(sys_chown16) + CALL(sys_getcwd) + CALL(sys_capget) +/* 185 */ CALL(sys_capset) + CALL(sys_sigaltstack_wrapper) + CALL(sys_sendfile) + CALL(sys_ni_syscall) + CALL(sys_ni_syscall) +/* 190 */ CALL(sys_vfork_wrapper) + CALL(sys_getrlimit) + CALL(sys_mmap2) + CALL(ABI(sys_truncate64, sys_oabi_truncate64)) + CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64)) +/* 195 */ CALL(ABI(sys_stat64, sys_oabi_stat64)) + CALL(ABI(sys_lstat64, sys_oabi_lstat64)) + CALL(ABI(sys_fstat64, sys_oabi_fstat64)) + CALL(sys_lchown) + CALL(sys_getuid) +/* 200 */ CALL(sys_getgid) + CALL(sys_geteuid) + CALL(sys_getegid) + CALL(sys_setreuid) + CALL(sys_setregid) +/* 205 */ CALL(sys_getgroups) + CALL(sys_setgroups) + CALL(sys_fchown) + CALL(sys_setresuid) + CALL(sys_getresuid) +/* 210 */ CALL(sys_setresgid) + CALL(sys_getresgid) + CALL(sys_chown) + CALL(sys_setuid) + CALL(sys_setgid) +/* 215 */ CALL(sys_setfsuid) + CALL(sys_setfsgid) + CALL(sys_getdents64) + CALL(sys_pivot_root) + CALL(sys_mincore) +/* 220 */ CALL(sys_madvise) + CALL(ABI(sys_fcntl64, sys_oabi_fcntl64)) + CALL(sys_ni_syscall) /* TUX */ + CALL(sys_ni_syscall) + CALL(sys_gettid) +/* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead)) + CALL(sys_setxattr) + CALL(sys_lsetxattr) + CALL(sys_fsetxattr) + CALL(sys_getxattr) +/* 230 */ CALL(sys_lgetxattr) + CALL(sys_fgetxattr) + CALL(sys_listxattr) + CALL(sys_llistxattr) + CALL(sys_flistxattr) +/* 235 */ CALL(sys_removexattr) + CALL(sys_lremovexattr) + CALL(sys_fremovexattr) + CALL(sys_tkill) + CALL(sys_sendfile64) +/* 240 */ CALL(sys_futex) + CALL(sys_sched_setaffinity) + CALL(sys_sched_getaffinity) + CALL(sys_io_setup) + CALL(sys_io_destroy) +/* 245 */ CALL(sys_io_getevents) + CALL(sys_io_submit) + CALL(sys_io_cancel) + CALL(sys_exit_group) + CALL(sys_lookup_dcookie) +/* 250 */ CALL(sys_epoll_create) + CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)) + CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait)) + CALL(sys_remap_file_pages) + CALL(sys_ni_syscall) /* sys_set_thread_area */ +/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */ + CALL(sys_set_tid_address) + CALL(sys_timer_create) + CALL(sys_timer_settime) + CALL(sys_timer_gettime) +/* 260 */ CALL(sys_timer_getoverrun) + CALL(sys_timer_delete) + CALL(sys_clock_settime) + CALL(sys_clock_gettime) + CALL(sys_clock_getres) +/* 265 */ CALL(sys_clock_nanosleep) + CALL(sys_statfs64_wrapper) + CALL(sys_fstatfs64_wrapper) + CALL(sys_tgkill) + CALL(sys_utimes) +/* 270 */ CALL(sys_arm_fadvise64_64) + CALL(sys_pciconfig_iobase) + CALL(sys_pciconfig_read) + CALL(sys_pciconfig_write) + CALL(sys_mq_open) +/* 275 */ CALL(sys_mq_unlink) + CALL(sys_mq_timedsend) + CALL(sys_mq_timedreceive) + CALL(sys_mq_notify) + CALL(sys_mq_getsetattr) +/* 280 */ CALL(sys_waitid) + CALL(sys_socket) + CALL(ABI(sys_bind, sys_oabi_bind)) + CALL(ABI(sys_connect, sys_oabi_connect)) + CALL(sys_listen) +/* 285 */ CALL(sys_accept) + CALL(sys_getsockname) + CALL(sys_getpeername) + CALL(sys_socketpair) + CALL(sys_send) +/* 290 */ CALL(ABI(sys_sendto, sys_oabi_sendto)) + CALL(sys_recv) + CALL(sys_recvfrom) + CALL(sys_shutdown) + CALL(sys_setsockopt) +/* 295 */ CALL(sys_getsockopt) + CALL(ABI(sys_sendmsg, sys_oabi_sendmsg)) + CALL(sys_recvmsg) + CALL(ABI(sys_semop, sys_oabi_semop)) + CALL(sys_semget) +/* 300 */ CALL(sys_semctl) + CALL(sys_msgsnd) + CALL(sys_msgrcv) + CALL(sys_msgget) + CALL(sys_msgctl) +/* 305 */ CALL(sys_shmat) + CALL(sys_shmdt) + CALL(sys_shmget) + CALL(sys_shmctl) + CALL(sys_add_key) +/* 310 */ CALL(sys_request_key) + CALL(sys_keyctl) + CALL(ABI(sys_semtimedop, sys_oabi_semtimedop)) +/* vserver */ CALL(sys_ni_syscall) + CALL(sys_ioprio_set) +/* 315 */ CALL(sys_ioprio_get) + CALL(sys_inotify_init) + CALL(sys_inotify_add_watch) + CALL(sys_inotify_rm_watch) + CALL(sys_mbind) +/* 320 */ CALL(sys_get_mempolicy) + CALL(sys_set_mempolicy) +#ifndef syscalls_counted +.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls +#define syscalls_counted #endif +.rept syscalls_padding + CALL(sys_ni_syscall) +.endr diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 874e6bb79405..964cd717506b 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -333,10 +333,14 @@ __pabt_svc: @ from the exception stack #if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else @ make sure our user space atomic helper is aborted cmp r2, #TASK_SIZE bichs r3, r3, #PSR_Z_BIT #endif +#endif @ @ We are now ready to fill in the remaining blanks on the stack: @@ -705,7 +709,12 @@ __kuser_memory_barrier: @ 0xffff0fa0 * The C flag is also set if *ptr was changed to allow for assembly * optimization in the calling code. * - * Note: this routine already includes memory barriers as needed. + * Notes: + * + * - This routine already includes memory barriers as needed. + * + * - A failure might be transient, i.e. it is possible, although unlikely, + * that "failure" be returned even if *ptr == oldval. * * For example, a user space atomic_add implementation could look like this: * @@ -735,8 +744,11 @@ __kuser_cmpxchg: @ 0xffff0fc0 * The kernel itself must perform the operation. * A special ghost syscall is used for that (see traps.c). */ + stmfd sp!, {r7, lr} + mov r7, #0xff00 @ 0xfff0 into r7 for EABI + orr r7, r7, #0xf0 swi #0x9ffff0 - mov pc, lr + ldmfd sp!, {r7, pc} #elif __LINUX_ARM_ARCH__ < 6 @@ -753,12 +765,18 @@ __kuser_cmpxchg: @ 0xffff0fc0 * exception happening just after the str instruction which would * clear the Z flag although the exchange was done. */ +#ifdef CONFIG_MMU teq ip, ip @ set Z flag ldr ip, [r2] @ load current val add r3, r2, #1 @ prepare store ptr teqeq ip, r0 @ compare with oldval if still allowed streq r1, [r3, #-1]! @ store newval if still allowed subs r0, r2, r3 @ if r2 == r3 the str occured +#else +#warning "NPTL on non MMU needs fixing" + mov r0, #-1 + adds r0, r0, #0 +#endif mov pc, lr #else diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 2b92ce85f97f..dbcb11a31f78 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -87,7 +87,11 @@ ENTRY(ret_from_fork) b ret_slow_syscall + .equ NR_syscalls,0 +#define CALL(x) .equ NR_syscalls,NR_syscalls+1 #include "calls.S" +#undef CALL +#define CALL(x) .long x /*============================================================================= * SWI handler diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 765922bcf9e7..a0cd0a90a10d 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -30,15 +30,21 @@ #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)) /* + * With EABI, the syscall number has to be loaded into r7. + */ +#define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE)) +#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) + +/* * For Thumb syscalls, we pass the syscall number via r7. We therefore * need two 16-bit instructions. */ #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) -const unsigned long sigreturn_codes[4] = { - SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, - SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN +const unsigned long sigreturn_codes[7] = { + MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, + MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, }; static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); @@ -189,7 +195,7 @@ struct aux_sigframe { struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; - unsigned long retcode; + unsigned long retcode[2]; struct aux_sigframe aux __attribute__((aligned(8))); }; @@ -198,7 +204,7 @@ struct rt_sigframe { void __user *puc; struct siginfo info; struct ucontext uc; - unsigned long retcode; + unsigned long retcode[2]; struct aux_sigframe aux __attribute__((aligned(8))); }; @@ -436,12 +442,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) { retcode = (unsigned long)ka->sa.sa_restorer; } else { - unsigned int idx = thumb; + unsigned int idx = thumb << 1; if (ka->sa.sa_flags & SA_SIGINFO) - idx += 2; + idx += 3; - if (__put_user(sigreturn_codes[idx], rc)) + if (__put_user(sigreturn_codes[idx], rc) || + __put_user(sigreturn_codes[idx+1], rc+1)) return 1; if (cpsr & MODE32_BIT) { @@ -456,7 +463,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, * the return code written onto the stack. */ flush_icache_range((unsigned long)rc, - (unsigned long)(rc + 1)); + (unsigned long)(rc + 2)); retcode = ((unsigned long)rc) + thumb; } @@ -488,7 +495,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg } if (err == 0) - err = setup_return(regs, ka, &frame->retcode, frame, usig); + err = setup_return(regs, ka, frame->retcode, frame, usig); return err; } @@ -522,7 +529,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err == 0) - err = setup_return(regs, ka, &frame->retcode, frame, usig); + err = setup_return(regs, ka, frame->retcode, frame, usig); if (err == 0) { /* diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 91d26faca62b..9991049c522d 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h @@ -9,4 +9,4 @@ */ #define KERN_SIGRETURN_CODE 0xffff0500 -extern const unsigned long sigreturn_codes[4]; +extern const unsigned long sigreturn_codes[7]; diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index eafa8e5284af..9d4b76409c64 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -59,6 +59,16 @@ * struct sembuf loses its padding with EABI. Since arrays of them are * used they have to be copyed to remove the padding. Compatibility wrappers * provided below. + * + * sys_bind: + * sys_connect: + * sys_sendmsg: + * sys_sendto: + * + * struct sockaddr_un loses its padding with EABI. Since the size of the + * structure is used as a validation test in unix_mkname(), we need to + * change the length argument to 110 whenever it is 112. Compatibility + * wrappers provided below. */ #include <linux/syscalls.h> @@ -67,6 +77,7 @@ #include <linux/fcntl.h> #include <linux/eventpoll.h> #include <linux/sem.h> +#include <linux/socket.h> #include <asm/ipc.h> #include <asm/uaccess.h> @@ -337,3 +348,63 @@ asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, return sys_ipc(call, first, second, third, ptr, fifth); } } + +asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen) +{ + sa_family_t sa_family; + if (addrlen == 112 && + get_user(sa_family, &addr->sa_family) == 0 && + sa_family == AF_UNIX) + addrlen = 110; + return sys_bind(fd, addr, addrlen); +} + +asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen) +{ + sa_family_t sa_family; + if (addrlen == 112 && + get_user(sa_family, &addr->sa_family) == 0 && + sa_family == AF_UNIX) + addrlen = 110; + return sys_connect(fd, addr, addrlen); +} + +asmlinkage long sys_oabi_sendto(int fd, void __user *buff, + size_t len, unsigned flags, + struct sockaddr __user *addr, + int addrlen) +{ + sa_family_t sa_family; + if (addrlen == 112 && + get_user(sa_family, &addr->sa_family) == 0 && + sa_family == AF_UNIX) + addrlen = 110; + return sys_sendto(fd, buff, len, flags, addr, addrlen); +} + +asmlinkage long sys_oabi_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) +{ + struct sockaddr __user *addr; + int msg_namelen; + sa_family_t sa_family; + if (msg && + get_user(msg_namelen, &msg->msg_namelen) == 0 && + msg_namelen == 112 && + get_user(addr, &msg->msg_name) == 0 && + get_user(sa_family, &addr->sa_family) == 0 && + sa_family == AF_UNIX) + { + /* + * HACK ALERT: there is a limit to how much backward bending + * we should do for what is actually a transitional + * compatibility layer. This already has known flaws with + * a few ioctls that we don't intend to fix. Therefore + * consider this blatent hack as another one... and take care + * to run for cover. In most cases it will "just work fine". + * If it doesn't, well, tough. + */ + put_user(110, &msg->msg_namelen); + } + return sys_sendmsg(fd, msg, flags); +} + diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig index 0793dcf54f2e..0e2b641268ad 100644 --- a/arch/arm/mach-clps711x/Kconfig +++ b/arch/arm/mach-clps711x/Kconfig @@ -24,6 +24,8 @@ config ARCH_CEIVA config ARCH_CLEP7312 bool "CLEP7312" + help + Boards based on the Cirrus Logic 7212/7312 chips. config ARCH_EDB7211 bool "EDB7211" diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c index dc31e3fd6c57..8ab1b040288c 100644 --- a/arch/arm/mach-imx/mx1ads.c +++ b/arch/arm/mach-imx/mx1ads.c @@ -27,7 +27,6 @@ #include <asm/mach/arch.h> #include <linux/interrupt.h> #include "generic.h" -#include <asm/serial.h> static struct resource cs89x0_resources[] = { [0] = { diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 31820170f306..a0724f2b24ce 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -469,7 +469,9 @@ static void cp_clcd_enable(struct clcd_fb *fb) if (fb->fb.var.bits_per_pixel <= 8) val = CM_CTRL_LCDMUXSEL_VGA_8421BPP; else if (fb->fb.var.bits_per_pixel <= 16) - val = CM_CTRL_LCDMUXSEL_VGA_16BPP; + val = CM_CTRL_LCDMUXSEL_VGA_16BPP + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1 + | CM_CTRL_STATIC1 | CM_CTRL_STATIC2; else val = 0; /* no idea for this, don't trust the docs */ diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c index 9e5a13bb39d0..52fac89e95b5 100644 --- a/arch/arm/mach-ixp2000/enp2611.c +++ b/arch/arm/mach-ixp2000/enp2611.c @@ -106,6 +106,7 @@ static void __init enp2611_pci_preinit(void) { ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000); ixp2000_pci_preinit(); + pcibios_setup("firmware"); } static inline int enp2611_pci_valid_device(struct pci_bus *bus, diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c index 7c782403042a..09101271298e 100644 --- a/arch/arm/mach-ixp2000/ixdp2400.c +++ b/arch/arm/mach-ixp2000/ixdp2400.c @@ -68,6 +68,7 @@ void __init ixdp2400_pci_preinit(void) { ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000); ixp2000_pci_preinit(); + pcibios_setup("firmware"); } int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys) diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 10f06606d460..150519fb38ec 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -212,6 +212,7 @@ void __init ixdp2x01_pci_preinit(void) { ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000); ixp2000_pci_preinit(); + pcibios_setup("firmware"); } #define DEVPIN(dev, pin) ((pin) | ((dev) << 3)) @@ -299,7 +300,9 @@ struct hw_pci ixdp2x01_pci __initdata = { int __init ixdp2x01_pci_init(void) { - pci_common_init(&ixdp2x01_pci); + if (machine_is_ixdp2401() || machine_is_ixdp2801()) + pci_common_init(&ixdp2x01_pci); + return 0; } diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6b393691d0e8..4bdc9d4526cd 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -333,6 +333,7 @@ static struct platform_device *ixp46x_devices[] __initdata = { }; unsigned long ixp4xx_exp_bus_size; +EXPORT_SYMBOL(ixp4xx_exp_bus_size); void __init ixp4xx_sys_init(void) { @@ -352,7 +353,7 @@ void __init ixp4xx_sys_init(void) } } - printk("IXP4xx: Using %uMiB expansion bus window size\n", + printk("IXP4xx: Using %luMiB expansion bus window size\n", ixp4xx_exp_bus_size >> 20); } diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index bdc20b51b076..a177e78b2b87 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -30,6 +30,7 @@ static void __init omap_generic_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); } @@ -104,7 +105,7 @@ static void __init omap_generic_init(void) static void __init omap_generic_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 9533c36a92df..89f0cc74a519 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -128,6 +128,7 @@ static void __init h2_init_smc91x(void) static void __init h2_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); h2_init_smc91x(); @@ -194,7 +195,7 @@ static void __init h2_init(void) static void __init h2_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } MACHINE_START(OMAP_H2, "TI-H2") diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index d665efc1c344..d9f386265996 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -203,6 +203,7 @@ static void __init h3_init_smc91x(void) void h3_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); h3_init_smc91x(); @@ -210,7 +211,7 @@ void h3_init_irq(void) static void __init h3_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 652f37c7f906..a04e4332915e 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -181,6 +181,7 @@ static void __init innovator_init_smc91x(void) void innovator_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); #ifdef CONFIG_ARCH_OMAP15XX @@ -285,7 +286,7 @@ static void __init innovator_init(void) static void __init innovator_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index 58f783930d45..60d5f8a3339c 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c @@ -65,6 +65,7 @@ static struct omap_board_config_kernel netstar_config[] = { static void __init netstar_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); } @@ -108,7 +109,7 @@ static void __init netstar_init(void) static void __init netstar_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } #define MACHINE_PANICED 1 diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index e5d126e8f276..543fa136106d 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -169,6 +169,7 @@ static void __init osk_init_cf(void) static void __init osk_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); osk_init_smc91x(); @@ -269,7 +270,7 @@ static void __init osk_init(void) static void __init osk_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } MACHINE_START(OMAP_OSK, "TI-OSK") diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 67fada207622..e488f7236775 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -34,6 +34,7 @@ static void __init omap_generic_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); } @@ -72,7 +73,7 @@ static void __init omap_generic_init(void) static void __init omap_generic_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 88708a0c52a2..3913a3cc0ce6 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -144,6 +144,7 @@ static void __init perseus2_init_smc91x(void) void omap_perseus2_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); perseus2_init_smc91x(); @@ -160,7 +161,7 @@ static struct map_desc omap_perseus2_io_desc[] __initdata = { static void __init omap_perseus2_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); iotable_init(omap_perseus2_io_desc, ARRAY_SIZE(omap_perseus2_io_desc)); diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 959b4b847c87..bfd5fdd1a875 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -162,6 +162,7 @@ static struct omap_board_config_kernel voiceblue_config[] = { static void __init voiceblue_init_irq(void) { + omap1_init_common_hw(); omap_init_irq(); omap_gpio_init(); } @@ -206,7 +207,7 @@ static void __init voiceblue_init(void) static void __init voiceblue_map_io(void) { - omap_map_common_io(); + omap1_map_common_io(); } #define MACHINE_PANICED 1 diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 9d862f86bba6..75110ba10424 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -50,10 +50,10 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk) { int retval; - retval = omap1_clk_use(&api_ck.clk); + retval = omap1_clk_enable(&api_ck.clk); if (!retval) { - retval = omap1_clk_enable(clk); - omap1_clk_unuse(&api_ck.clk); + retval = omap1_clk_enable_generic(clk); + omap1_clk_disable(&api_ck.clk); } return retval; @@ -61,9 +61,9 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk) static void omap1_clk_disable_dsp_domain(struct clk *clk) { - if (omap1_clk_use(&api_ck.clk) == 0) { - omap1_clk_disable(clk); - omap1_clk_unuse(&api_ck.clk); + if (omap1_clk_enable(&api_ck.clk) == 0) { + omap1_clk_disable_generic(clk); + omap1_clk_disable(&api_ck.clk); } } @@ -72,7 +72,7 @@ static int omap1_clk_enable_uart_functional(struct clk *clk) int ret; struct uart_clk *uclk; - ret = omap1_clk_enable(clk); + ret = omap1_clk_enable_generic(clk); if (ret == 0) { /* Set smart idle acknowledgement mode */ uclk = (struct uart_clk *)clk; @@ -91,7 +91,7 @@ static void omap1_clk_disable_uart_functional(struct clk *clk) uclk = (struct uart_clk *)clk; omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); - omap1_clk_disable(clk); + omap1_clk_disable_generic(clk); } static void omap1_clk_allow_idle(struct clk *clk) @@ -230,9 +230,9 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk) * Note that DSP_CKCTL virt addr = phys addr, so * we must use __raw_readw() instead of omap_readw(). */ - omap1_clk_use(&api_ck.clk); + omap1_clk_enable(&api_ck.clk); dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); - omap1_clk_unuse(&api_ck.clk); + omap1_clk_disable(&api_ck.clk); if (unlikely(clk->rate == clk->parent->rate / dsor)) return; /* No change, quick exit */ @@ -412,12 +412,12 @@ static void omap1_init_ext_clk(struct clk * clk) clk-> rate = 96000000 / dsor; } -static int omap1_clk_use(struct clk *clk) +static int omap1_clk_enable(struct clk *clk) { int ret = 0; if (clk->usecount++ == 0) { if (likely(clk->parent)) { - ret = omap1_clk_use(clk->parent); + ret = omap1_clk_enable(clk->parent); if (unlikely(ret != 0)) { clk->usecount--; @@ -432,7 +432,7 @@ static int omap1_clk_use(struct clk *clk) ret = clk->enable(clk); if (unlikely(ret != 0) && clk->parent) { - omap1_clk_unuse(clk->parent); + omap1_clk_disable(clk->parent); clk->usecount--; } } @@ -440,12 +440,12 @@ static int omap1_clk_use(struct clk *clk) return ret; } -static void omap1_clk_unuse(struct clk *clk) +static void omap1_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { clk->disable(clk); if (likely(clk->parent)) { - omap1_clk_unuse(clk->parent); + omap1_clk_disable(clk->parent); if (clk->flags & CLOCK_NO_IDLE_PARENT) if (!cpu_is_omap24xx()) omap1_clk_allow_idle(clk->parent); @@ -453,7 +453,7 @@ static void omap1_clk_unuse(struct clk *clk) } } -static int omap1_clk_enable(struct clk *clk) +static int omap1_clk_enable_generic(struct clk *clk) { __u16 regval16; __u32 regval32; @@ -492,7 +492,7 @@ static int omap1_clk_enable(struct clk *clk) return 0; } -static void omap1_clk_disable(struct clk *clk) +static void omap1_clk_disable_generic(struct clk *clk) { __u16 regval16; __u32 regval32; @@ -654,8 +654,8 @@ late_initcall(omap1_late_clk_reset); #endif static struct clk_functions omap1_clk_functions = { - .clk_use = omap1_clk_use, - .clk_unuse = omap1_clk_unuse, + .clk_enable = omap1_clk_enable, + .clk_disable = omap1_clk_disable, .clk_round_rate = omap1_clk_round_rate, .clk_set_rate = omap1_clk_set_rate, }; @@ -780,9 +780,9 @@ int __init omap1_clk_init(void) * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ - clk_use(&armper_ck.clk); - clk_use(&armxor_ck.clk); - clk_use(&armtim_ck.clk); /* This should be done by timer code */ + clk_enable(&armper_ck.clk); + clk_enable(&armxor_ck.clk); + clk_enable(&armtim_ck.clk); /* This should be done by timer code */ if (cpu_is_omap1510()) clk_enable(&arm_gpio_ck); diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index f3bdfb50e01a..4f18d1b94449 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -13,8 +13,8 @@ #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H #define __ARCH_ARM_MACH_OMAP1_CLOCK_H -static int omap1_clk_enable(struct clk * clk); -static void omap1_clk_disable(struct clk * clk); +static int omap1_clk_enable_generic(struct clk * clk); +static void omap1_clk_disable_generic(struct clk * clk); static void omap1_ckctl_recalc(struct clk * clk); static void omap1_watchdog_recalc(struct clk * clk); static void omap1_ckctl_recalc_dsp_domain(struct clk * clk); @@ -30,8 +30,8 @@ static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate); static void omap1_init_ext_clk(struct clk * clk); static int omap1_select_table_rate(struct clk * clk, unsigned long rate); static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); -static int omap1_clk_use(struct clk *clk); -static void omap1_clk_unuse(struct clk *clk); +static int omap1_clk_enable(struct clk *clk); +static void omap1_clk_disable(struct clk *clk); struct mpu_rate { unsigned long rate; @@ -152,8 +152,8 @@ static struct clk ck_ref = { .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk ck_dpll1 = { @@ -161,8 +161,8 @@ static struct clk ck_dpll1 = { .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | RATE_PROPAGATES | ALWAYS_ENABLED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk ck_dpll1out = { @@ -173,8 +173,8 @@ static struct arm_idlect1_clk ck_dpll1out = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_CKOUT_ARM, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 12, }; @@ -186,8 +186,8 @@ static struct clk arm_ck = { RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armper_ck = { @@ -200,8 +200,8 @@ static struct arm_idlect1_clk armper_ck = { .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 2, }; @@ -213,8 +213,8 @@ static struct clk arm_gpio_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_GPIOCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armxor_ck = { @@ -226,8 +226,8 @@ static struct arm_idlect1_clk armxor_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 1, }; @@ -241,8 +241,8 @@ static struct arm_idlect1_clk armtim_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_TIMCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 9, }; @@ -256,8 +256,8 @@ static struct arm_idlect1_clk armwdt_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_WDTCK, .recalc = &omap1_watchdog_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 0, }; @@ -272,8 +272,8 @@ static struct clk arminth_ck16xx = { * * 1510 version is in TC clocks. */ - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dsp_ck = { @@ -285,8 +285,8 @@ static struct clk dsp_ck = { .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dspmmu_ck = { @@ -296,8 +296,8 @@ static struct clk dspmmu_ck = { RATE_CKCTL | ALWAYS_ENABLED, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dspper_ck = { @@ -349,8 +349,8 @@ static struct arm_idlect1_clk tc_ck = { CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 6, }; @@ -364,8 +364,8 @@ static struct clk arminth_ck1510 = { * * 16xx version is in MPU clocks. */ - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tipb_ck = { @@ -374,8 +374,8 @@ static struct clk tipb_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk l3_ocpi_ck = { @@ -386,8 +386,8 @@ static struct clk l3_ocpi_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_OCPI_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tc1_ck = { @@ -397,8 +397,8 @@ static struct clk tc1_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC1_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tc2_ck = { @@ -408,8 +408,8 @@ static struct clk tc2_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC2_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dma_ck = { @@ -419,8 +419,8 @@ static struct clk dma_ck = { .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dma_lcdfree_ck = { @@ -428,8 +428,8 @@ static struct clk dma_lcdfree_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk api_ck = { @@ -441,8 +441,8 @@ static struct arm_idlect1_clk api_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_APICK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 8, }; @@ -455,8 +455,8 @@ static struct arm_idlect1_clk lb_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LBCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 4, }; @@ -466,8 +466,8 @@ static struct clk rhea1_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk rhea2_ck = { @@ -475,8 +475,8 @@ static struct clk rhea2_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk lcd_ck_16xx = { @@ -487,8 +487,8 @@ static struct clk lcd_ck_16xx = { .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk lcd_ck_1510 = { @@ -501,8 +501,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 3, }; @@ -518,8 +518,8 @@ static struct clk uart1_1510 = { .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart1_16xx = { @@ -550,8 +550,8 @@ static struct clk uart2_ck = { .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk uart3_1510 = { @@ -565,8 +565,8 @@ static struct clk uart3_1510 = { .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart3_16xx = { @@ -593,8 +593,8 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, .enable_bit = USB_MCLK_EN_BIT, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck1510 = { @@ -605,8 +605,8 @@ static struct clk usb_hhc_ck1510 = { RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = USB_HOST_HHC_UHOST_EN, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck16xx = { @@ -618,8 +618,8 @@ static struct clk usb_hhc_ck16xx = { RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, .enable_bit = 8 /* UHOST_EN */, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_dc_ck = { @@ -629,8 +629,8 @@ static struct clk usb_dc_ck = { .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 4, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mclk_1510 = { @@ -638,8 +638,8 @@ static struct clk mclk_1510 = { /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mclk_16xx = { @@ -651,8 +651,8 @@ static struct clk mclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk bclk_1510 = { @@ -660,8 +660,8 @@ static struct clk bclk_1510 = { /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk bclk_16xx = { @@ -673,8 +673,8 @@ static struct clk bclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mmc1_ck = { @@ -686,8 +686,8 @@ static struct clk mmc1_ck = { RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 23, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mmc2_ck = { @@ -699,8 +699,8 @@ static struct clk mmc2_ck = { RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 20, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk virtual_ck_mpu = { @@ -711,8 +711,8 @@ static struct clk virtual_ck_mpu = { .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, .round_rate = &omap1_round_to_table_rate, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk * onchip_clks[] = { diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index a7a19f75b9e1..82d556be79c5 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <asm/tlb.h> #include <asm/mach/map.h> #include <asm/io.h> #include <asm/arch/mux.h> @@ -83,15 +84,24 @@ static struct map_desc omap16xx_io_desc[] __initdata = { }; #endif -static int initialized = 0; - -static void __init _omap_map_io(void) +/* + * Maps common IO regions for omap1. This should only get called from + * board specific init. + */ +void __init omap1_map_common_io(void) { - initialized = 1; - - /* We have to initialize the IO space mapping before we can run - * cpu_is_omapxxx() macros. */ iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc)); + + /* Normally devicemaps_init() would flush caches and tlb after + * mdesc->map_io(), but we must also do it here because of the CPU + * revision check below. + */ + local_flush_tlb_all(); + flush_cache_all(); + + /* We want to check CPU revision early for cpu_is_omapxxxx() macros. + * IO space mapping must be initialized before we can do that. + */ omap_check_revision(); #ifdef CONFIG_ARCH_OMAP730 @@ -111,7 +121,14 @@ static void __init _omap_map_io(void) #endif omap_sram_init(); +} +/* + * Common low-level hardware init for omap1. This should only get called from + * board specific init. + */ +void __init omap1_init_common_hw() +{ /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort * on a Posted Write in the TIPB Bridge". */ @@ -121,16 +138,7 @@ static void __init _omap_map_io(void) /* Must init clocks early to assure that timer interrupt works */ omap1_clk_init(); -} -/* - * This should only get called from board specific init - */ -void __init omap_map_common_io(void) -{ - if (!initialized) { - _omap_map_io(); - omap1_mux_init(); - } + omap1_mux_init(); } diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 7a68f098a025..e924e0c6a4ce 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -146,7 +146,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart1_ck)) printk("Could not get uart1_ck\n"); else { - clk_use(uart1_ck); + clk_enable(uart1_ck); if (cpu_is_omap1510()) clk_set_rate(uart1_ck, 12000000); } @@ -166,7 +166,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart2_ck)) printk("Could not get uart2_ck\n"); else { - clk_use(uart2_ck); + clk_enable(uart2_ck); if (cpu_is_omap1510()) clk_set_rate(uart2_ck, 12000000); else @@ -188,7 +188,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart3_ck)) printk("Could not get uart3_ck\n"); else { - clk_use(uart3_ck); + clk_enable(uart3_ck); if (cpu_is_omap1510()) clk_set_rate(uart3_ck, 12000000); } diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index b937123e5c65..eaecbf422d8c 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -33,6 +33,7 @@ static void __init omap_generic_init_irq(void) { + omap2_init_common_hw(); omap_init_irq(); } @@ -64,7 +65,7 @@ static void __init omap_generic_init(void) static void __init omap_generic_map_io(void) { - omap_map_common_io(); + omap2_map_common_io(); } MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index c3c35d40378a..a300d634d8a5 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -136,6 +136,7 @@ static inline void __init h4_init_smc91x(void) static void __init omap_h4_init_irq(void) { + omap2_init_common_hw(); omap_init_irq(); omap_gpio_init(); h4_init_smc91x(); @@ -181,7 +182,7 @@ static void __init omap_h4_init(void) static void __init omap_h4_map_io(void) { - omap_map_common_io(); + omap2_map_common_io(); } MACHINE_START(OMAP_H4, "OMAP2420 H4 board") diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 5407b9549150..180f675c9064 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -111,7 +111,7 @@ static void omap2_clk_fixed_enable(struct clk *clk) /* Enables clock without considering parent dependencies or use count * REVISIT: Maybe change this to use clk->enable like on omap1? */ -static int omap2_clk_enable(struct clk * clk) +static int _omap2_clk_enable(struct clk * clk) { u32 regval32; @@ -150,7 +150,7 @@ static void omap2_clk_fixed_disable(struct clk *clk) } /* Disables clock without considering parent dependencies or use count */ -static void omap2_clk_disable(struct clk *clk) +static void _omap2_clk_disable(struct clk *clk) { u32 regval32; @@ -167,23 +167,23 @@ static void omap2_clk_disable(struct clk *clk) __raw_writel(regval32, clk->enable_reg); } -static int omap2_clk_use(struct clk *clk) +static int omap2_clk_enable(struct clk *clk) { int ret = 0; if (clk->usecount++ == 0) { if (likely((u32)clk->parent)) - ret = omap2_clk_use(clk->parent); + ret = omap2_clk_enable(clk->parent); if (unlikely(ret != 0)) { clk->usecount--; return ret; } - ret = omap2_clk_enable(clk); + ret = _omap2_clk_enable(clk); if (unlikely(ret != 0) && clk->parent) { - omap2_clk_unuse(clk->parent); + omap2_clk_disable(clk->parent); clk->usecount--; } } @@ -191,12 +191,12 @@ static int omap2_clk_use(struct clk *clk) return ret; } -static void omap2_clk_unuse(struct clk *clk) +static void omap2_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { - omap2_clk_disable(clk); + _omap2_clk_disable(clk); if (likely((u32)clk->parent)) - omap2_clk_unuse(clk->parent); + omap2_clk_disable(clk->parent); } } @@ -873,7 +873,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) reg = (void __iomem *)src_sel; if (clk->usecount > 0) - omap2_clk_disable(clk); + _omap2_clk_disable(clk); /* Set new source value (previous dividers if any in effect) */ reg_val = __raw_readl(reg) & ~(field_mask << src_off); @@ -884,7 +884,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); if (clk->usecount > 0) - omap2_clk_enable(clk); + _omap2_clk_enable(clk); clk->parent = new_parent; @@ -999,8 +999,6 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) static struct clk_functions omap2_clk_functions = { .clk_enable = omap2_clk_enable, .clk_disable = omap2_clk_disable, - .clk_use = omap2_clk_use, - .clk_unuse = omap2_clk_unuse, .clk_round_rate = omap2_clk_round_rate, .clk_set_rate = omap2_clk_set_rate, .clk_set_parent = omap2_clk_set_parent, @@ -1045,7 +1043,7 @@ static void __init omap2_disable_unused_clocks(void) continue; printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); - omap2_clk_disable(ck); + _omap2_clk_disable(ck); } } late_initcall(omap2_disable_unused_clocks); @@ -1120,10 +1118,10 @@ int __init omap2_clk_init(void) * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ - clk_use(&sync_32k_ick); - clk_use(&omapctrl_ick); + clk_enable(&sync_32k_ick); + clk_enable(&omapctrl_ick); if (cpu_is_omap2430()) - clk_use(&sdrc_ick); + clk_enable(&sdrc_ick); return 0; } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 4aeab5591bd3..6cab20b1d3c1 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -24,7 +24,7 @@ static void omap2_propagate_rate(struct clk * clk); static void omap2_mpu_recalc(struct clk * clk); static int omap2_select_table_rate(struct clk * clk, unsigned long rate); static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate); -static void omap2_clk_unuse(struct clk *clk); +static void omap2_clk_disable(struct clk *clk); static void omap2_sys_clk_recalc(struct clk * clk); static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val); static u32 omap2_clksel_get_divisor(struct clk *clk); @@ -859,7 +859,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", - .parent = &core_ck, + .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP | CONFIG_PARTICIPANT, @@ -1045,7 +1045,7 @@ static struct clk gpt1_ick = { .name = "gpt1_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit4 */ + .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit0 */ .enable_bit = 0, .recalc = &omap2_followparent_recalc, }; @@ -1055,7 +1055,7 @@ static struct clk gpt1_fck = { .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | CM_WKUP_SEL1, - .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, + .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, /* Bit0 */ .enable_bit = 0, .src_offset = 0, .recalc = &omap2_followparent_recalc, @@ -1065,7 +1065,7 @@ static struct clk gpt2_ick = { .name = "gpt2_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit4 */ + .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */ .enable_bit = 0, .recalc = &omap2_followparent_recalc, }; @@ -1839,7 +1839,7 @@ static struct clk usb_fck = { static struct clk usbhs_ick = { .name = "usbhs_ick", - .parent = &l4_ck, + .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, .enable_bit = 6, diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index e1bd46a96e11..24dd374224af 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -119,14 +119,14 @@ void __init omap_serial_init() if (IS_ERR(uart1_ick)) printk("Could not get uart1_ick\n"); else { - clk_use(uart1_ick); + clk_enable(uart1_ick); } uart1_fck = clk_get(NULL, "uart1_fck"); if (IS_ERR(uart1_fck)) printk("Could not get uart1_fck\n"); else { - clk_use(uart1_fck); + clk_enable(uart1_fck); } break; case 1: @@ -134,14 +134,14 @@ void __init omap_serial_init() if (IS_ERR(uart2_ick)) printk("Could not get uart2_ick\n"); else { - clk_use(uart2_ick); + clk_enable(uart2_ick); } uart2_fck = clk_get(NULL, "uart2_fck"); if (IS_ERR(uart2_fck)) printk("Could not get uart2_fck\n"); else { - clk_use(uart2_fck); + clk_enable(uart2_fck); } break; case 2: @@ -149,14 +149,14 @@ void __init omap_serial_init() if (IS_ERR(uart3_ick)) printk("Could not get uart3_ick\n"); else { - clk_use(uart3_ick); + clk_enable(uart3_ick); } uart3_fck = clk_get(NULL, "uart3_fck"); if (IS_ERR(uart3_fck)) printk("Could not get uart3_fck\n"); else { - clk_use(uart3_fck); + clk_enable(uart3_fck); } break; } diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 23d36b1c40fe..1d2f5ac2f69b 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -104,7 +104,7 @@ static void __init omap2_gp_timer_init(void) if (IS_ERR(sys_ck)) printk(KERN_ERR "Could not get sys_ck\n"); else { - clk_use(sys_ck); + clk_enable(sys_ck); tick_period = clk_get_rate(sys_ck) / 100; clk_put(sys_ck); } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index b41b1efaa2cf..3baa70819f24 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -44,7 +44,7 @@ unsigned int get_clk_frequency_khz( int info) /* Read clkcfg register: it has turbo, b, half-turbo (and f) */ asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) ); - t = clkcfg & (1 << 1); + t = clkcfg & (1 << 0); ht = clkcfg & (1 << 2); b = clkcfg & (1 << 3); diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 4a222f59f2cf..4303d988c4bf 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -182,7 +182,7 @@ static const struct icst307_params realview_oscvco_params = { static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco) { void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET; - void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC1_OFFSET; + void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; u32 val; val = readl(sys_osc) & ~0x7ffff; diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index b4f1e051c768..1217bf00309c 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -10,9 +10,13 @@ obj-m := obj-n := obj- := +# S3C2400 support files +obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o + # S3C2410 support files obj-$(CONFIG_CPU_S3C2410) += s3c2410.o +obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o obj-$(CONFIG_S3C2410_DMA) += dma.o # Power Management support @@ -25,6 +29,7 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o +obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o # bast extras diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index af2f3d52b61b..08489efdaf06 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -40,7 +40,6 @@ #include <linux/mutex.h> #include <asm/hardware.h> -#include <asm/atomic.h> #include <asm/irq.h> #include <asm/io.h> @@ -59,22 +58,18 @@ static DEFINE_MUTEX(clocks_mutex); void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable) { unsigned long clkcon; - unsigned long flags; - - local_irq_save(flags); clkcon = __raw_readl(S3C2410_CLKCON); - clkcon &= ~clocks; if (enable) clkcon |= clocks; + else + clkcon &= ~clocks; /* ensure none of the special function bits set */ clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); __raw_writel(clkcon, S3C2410_CLKCON); - - local_irq_restore(flags); } /* enable and disable calls for use with the clk struct */ @@ -138,16 +133,32 @@ void clk_put(struct clk *clk) int clk_enable(struct clk *clk) { - if (IS_ERR(clk)) + if (IS_ERR(clk) || clk == NULL) return -EINVAL; - return (clk->enable)(clk, 1); + clk_enable(clk->parent); + + mutex_lock(&clocks_mutex); + + if ((clk->usage++) == 0) + (clk->enable)(clk, 1); + + mutex_unlock(&clocks_mutex); + return 0; } void clk_disable(struct clk *clk) { - if (!IS_ERR(clk)) + if (IS_ERR(clk) || clk == NULL) + return; + + mutex_lock(&clocks_mutex); + + if ((--clk->usage) == 0) (clk->enable)(clk, 0); + + mutex_unlock(&clocks_mutex); + clk_disable(clk->parent); } @@ -361,6 +372,14 @@ int s3c24xx_register_clock(struct clk *clk) if (clk->enable == NULL) clk->enable = clk_null_enable; + /* if this is a standard clock, set the usage state */ + + if (clk->ctrlbit) { + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + + clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; + } + /* add to the list of available clocks */ mutex_lock(&clocks_mutex); @@ -402,6 +421,8 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, * the LCD clock if it is not needed. */ + mutex_lock(&clocks_mutex); + s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0); s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0); s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0); @@ -409,6 +430,8 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0); s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0); + mutex_unlock(&clocks_mutex); + /* assume uart clocks are correctly setup */ /* register our clocks */ diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index 177d5c8decf7..eb5c95d1e7f2 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h @@ -16,6 +16,7 @@ struct clk { struct clk *parent; const char *name; int id; + int usage; unsigned long rate; unsigned long ctrlbit; int (*enable)(struct clk *, int enable); diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c index 687fe371369d..00a379334b60 100644 --- a/arch/arm/mach-s3c2410/cpu.c +++ b/arch/arm/mach-s3c2410/cpu.c @@ -40,6 +40,7 @@ #include "cpu.h" #include "clock.h" +#include "s3c2400.h" #include "s3c2410.h" #include "s3c2440.h" @@ -55,6 +56,7 @@ struct cpu_table { /* table of supported CPUs */ +static const char name_s3c2400[] = "S3C2400"; static const char name_s3c2410[] = "S3C2410"; static const char name_s3c2440[] = "S3C2440"; static const char name_s3c2410a[] = "S3C2410A"; @@ -96,7 +98,16 @@ static struct cpu_table cpu_ids[] __initdata = { .init_uarts = s3c2440_init_uarts, .init = s3c2440_init, .name = name_s3c2440a - } + }, + { + .idcode = 0x0, /* S3C2400 doesn't have an idcode */ + .idmask = 0xffffffff, + .map_io = s3c2400_map_io, + .init_clocks = s3c2400_init_clocks, + .init_uarts = s3c2400_init_uarts, + .init = s3c2400_init, + .name = name_s3c2400 + }, }; /* minimal IO mapping */ @@ -148,12 +159,15 @@ static struct cpu_table *cpu; void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) { - unsigned long idcode; + unsigned long idcode = 0x0; /* initialise the io descriptors we need for initialisation */ iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); +#ifndef CONFIG_CPU_S3C2400 idcode = __raw_readl(S3C2410_GSTATUS1); +#endif + cpu = s3c_lookup_cpu(idcode); if (cpu == NULL) { diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index 9cbe5eef492b..fc1067783f6d 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -17,11 +17,12 @@ * 14-Jan-2005 BJD Added s3c24xx_init_clocks() call * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT * 14-Mar-2005 BJD Updated for __iomem + * 15-Jan-2006 LCVR Updated S3C2410_PA_##x to new S3C24XX_PA_##x macro */ /* todo - fix when rmk changes iodescs to use `void __iomem *` */ -#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C2410_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } +#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ #define MHZ (1000*1000) diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c index f58406e6ef5a..0a47d38789a5 100644 --- a/arch/arm/mach-s3c2410/devs.c +++ b/arch/arm/mach-s3c2410/devs.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. * * Modifications: + * 15-Jan-2006 LCVR Using S3C24XX_PA_##x macro for common S3C24XX devices * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} * 10-Feb-2005 BJD Added camera from guillaume.gourat@nexvision.tv * 29-Aug-2004 BJD Added timers 0 through 3 @@ -46,8 +47,8 @@ struct platform_device *s3c24xx_uart_devs[3]; static struct resource s3c_usb_resource[] = { [0] = { - .start = S3C2410_PA_USBHOST, - .end = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST - 1, + .start = S3C24XX_PA_USBHOST, + .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -76,8 +77,8 @@ EXPORT_SYMBOL(s3c_device_usb); static struct resource s3c_lcd_resource[] = { [0] = { - .start = S3C2410_PA_LCD, - .end = S3C2410_PA_LCD + S3C24XX_SZ_LCD - 1, + .start = S3C24XX_PA_LCD, + .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -139,8 +140,8 @@ EXPORT_SYMBOL(s3c_device_nand); static struct resource s3c_usbgadget_resource[] = { [0] = { - .start = S3C2410_PA_USBDEV, - .end = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV - 1, + .start = S3C24XX_PA_USBDEV, + .end = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -164,8 +165,8 @@ EXPORT_SYMBOL(s3c_device_usbgadget); static struct resource s3c_wdt_resource[] = { [0] = { - .start = S3C2410_PA_WATCHDOG, - .end = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, + .start = S3C24XX_PA_WATCHDOG, + .end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -189,8 +190,8 @@ EXPORT_SYMBOL(s3c_device_wdt); static struct resource s3c_i2c_resource[] = { [0] = { - .start = S3C2410_PA_IIC, - .end = S3C2410_PA_IIC + S3C24XX_SZ_IIC - 1, + .start = S3C24XX_PA_IIC, + .end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -214,8 +215,8 @@ EXPORT_SYMBOL(s3c_device_i2c); static struct resource s3c_iis_resource[] = { [0] = { - .start = S3C2410_PA_IIS, - .end = S3C2410_PA_IIS + S3C24XX_SZ_IIS -1, + .start = S3C24XX_PA_IIS, + .end = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1, .flags = IORESOURCE_MEM, } }; @@ -239,8 +240,8 @@ EXPORT_SYMBOL(s3c_device_iis); static struct resource s3c_rtc_resource[] = { [0] = { - .start = S3C2410_PA_RTC, - .end = S3C2410_PA_RTC + 0xff, + .start = S3C24XX_PA_RTC, + .end = S3C24XX_PA_RTC + 0xff, .flags = IORESOURCE_MEM, }, [1] = { @@ -268,12 +269,17 @@ EXPORT_SYMBOL(s3c_device_rtc); static struct resource s3c_adc_resource[] = { [0] = { - .start = S3C2410_PA_ADC, - .end = S3C2410_PA_ADC + S3C24XX_SZ_ADC - 1, + .start = S3C24XX_PA_ADC, + .end = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_TC, + .end = IRQ_TC, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_ADC, .end = IRQ_ADC, .flags = IORESOURCE_IRQ, } @@ -316,8 +322,8 @@ EXPORT_SYMBOL(s3c_device_sdi); static struct resource s3c_spi0_resource[] = { [0] = { - .start = S3C2410_PA_SPI, - .end = S3C2410_PA_SPI + 0x1f, + .start = S3C24XX_PA_SPI, + .end = S3C24XX_PA_SPI + 0x1f, .flags = IORESOURCE_MEM, }, [1] = { @@ -341,8 +347,8 @@ EXPORT_SYMBOL(s3c_device_spi0); static struct resource s3c_spi1_resource[] = { [0] = { - .start = S3C2410_PA_SPI + 0x20, - .end = S3C2410_PA_SPI + 0x20 + 0x1f, + .start = S3C24XX_PA_SPI + 0x20, + .end = S3C24XX_PA_SPI + 0x20 + 0x1f, .flags = IORESOURCE_MEM, }, [1] = { @@ -366,8 +372,8 @@ EXPORT_SYMBOL(s3c_device_spi1); static struct resource s3c_timer0_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x0C, - .end = S3C2410_PA_TIMER + 0x0C + 0xB, + .start = S3C24XX_PA_TIMER + 0x0C, + .end = S3C24XX_PA_TIMER + 0x0C + 0xB, .flags = IORESOURCE_MEM, }, [1] = { @@ -391,8 +397,8 @@ EXPORT_SYMBOL(s3c_device_timer0); static struct resource s3c_timer1_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x18, - .end = S3C2410_PA_TIMER + 0x23, + .start = S3C24XX_PA_TIMER + 0x18, + .end = S3C24XX_PA_TIMER + 0x23, .flags = IORESOURCE_MEM, }, [1] = { @@ -416,8 +422,8 @@ EXPORT_SYMBOL(s3c_device_timer1); static struct resource s3c_timer2_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x24, - .end = S3C2410_PA_TIMER + 0x2F, + .start = S3C24XX_PA_TIMER + 0x24, + .end = S3C24XX_PA_TIMER + 0x2F, .flags = IORESOURCE_MEM, }, [1] = { @@ -441,8 +447,8 @@ EXPORT_SYMBOL(s3c_device_timer2); static struct resource s3c_timer3_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x30, - .end = S3C2410_PA_TIMER + 0x3B, + .start = S3C24XX_PA_TIMER + 0x30, + .end = S3C24XX_PA_TIMER + 0x3B, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 65feaf20d23e..4dbd8e758ea6 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -1152,7 +1152,7 @@ static int __init s3c2410_init_dma(void) printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n"); - dma_base = ioremap(S3C2410_PA_DMA, 0x200); + dma_base = ioremap(S3C24XX_PA_DMA, 0x200); if (dma_base == NULL) { printk(KERN_ERR "dma failed to remap register block\n"); return -ENOMEM; diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c index 23ea3d5fa09c..cd39e8684584 100644 --- a/arch/arm/mach-s3c2410/gpio.c +++ b/arch/arm/mach-s3c2410/gpio.c @@ -31,6 +31,7 @@ * 05-Nov-2004 BJD EXPORT_SYMBOL() added for all code * 13-Mar-2005 BJD Updates for __iomem * 26-Oct-2005 BJD Added generic configuration types + * 15-Jan-2006 LCVR Added support for the S3C2400 */ @@ -48,7 +49,7 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) { - void __iomem *base = S3C2410_GPIO_BASE(pin); + void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long mask; unsigned long con; unsigned long flags; @@ -95,7 +96,7 @@ EXPORT_SYMBOL(s3c2410_gpio_cfgpin); unsigned int s3c2410_gpio_getcfg(unsigned int pin) { - void __iomem *base = S3C2410_GPIO_BASE(pin); + void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long mask; if (pin < S3C2410_GPIO_BANKB) { @@ -111,7 +112,7 @@ EXPORT_SYMBOL(s3c2410_gpio_getcfg); void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) { - void __iomem *base = S3C2410_GPIO_BASE(pin); + void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long offs = S3C2410_GPIO_OFFSET(pin); unsigned long flags; unsigned long up; @@ -133,7 +134,7 @@ EXPORT_SYMBOL(s3c2410_gpio_pullup); void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) { - void __iomem *base = S3C2410_GPIO_BASE(pin); + void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long offs = S3C2410_GPIO_OFFSET(pin); unsigned long flags; unsigned long dat; @@ -152,7 +153,7 @@ EXPORT_SYMBOL(s3c2410_gpio_setpin); unsigned int s3c2410_gpio_getpin(unsigned int pin) { - void __iomem *base = S3C2410_GPIO_BASE(pin); + void __iomem *base = S3C24XX_GPIO_BASE(pin); unsigned long offs = S3C2410_GPIO_OFFSET(pin); return __raw_readl(base + 0x04) & (1<< offs); @@ -166,70 +167,13 @@ unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) unsigned long misccr; local_irq_save(flags); - misccr = __raw_readl(S3C2410_MISCCR); + misccr = __raw_readl(S3C24XX_MISCCR); misccr &= ~clear; misccr ^= change; - __raw_writel(misccr, S3C2410_MISCCR); + __raw_writel(misccr, S3C24XX_MISCCR); local_irq_restore(flags); return misccr; } EXPORT_SYMBOL(s3c2410_modify_misccr); - -int s3c2410_gpio_getirq(unsigned int pin) -{ - if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23) - return -1; /* not valid interrupts */ - - if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) - return -1; /* not valid pin */ - - if (pin < S3C2410_GPF4) - return (pin - S3C2410_GPF0) + IRQ_EINT0; - - if (pin < S3C2410_GPG0) - return (pin - S3C2410_GPF4) + IRQ_EINT4; - - return (pin - S3C2410_GPG0) + IRQ_EINT8; -} - -EXPORT_SYMBOL(s3c2410_gpio_getirq); - -int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, - unsigned int config) -{ - void __iomem *reg = S3C2410_EINFLT0; - unsigned long flags; - unsigned long val; - - if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15) - return -1; - - config &= 0xff; - - pin -= S3C2410_GPG8_EINT16; - reg += pin & ~3; - - local_irq_save(flags); - - /* update filter width and clock source */ - - val = __raw_readl(reg); - val &= ~(0xff << ((pin & 3) * 8)); - val |= config << ((pin & 3) * 8); - __raw_writel(val, reg); - - /* update filter enable */ - - val = __raw_readl(S3C2410_EXTINT2); - val &= ~(1 << ((pin * 4) + 3)); - val |= on << ((pin * 4) + 3); - __raw_writel(val, S3C2410_EXTINT2); - - local_irq_restore(flags); - - return 0; -} - -EXPORT_SYMBOL(s3c2410_gpio_irqfilter); diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 1c316f14ed94..646a3a5d33a5 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -46,10 +46,11 @@ #include <asm/irq.h> #include <asm/mach-types.h> -//#include <asm/debug-ll.h> + #include <asm/arch/regs-serial.h> #include <asm/arch/regs-lcd.h> +#include <asm/arch/h1940-latch.h> #include <asm/arch/fb.h> #include <linux/serial_core.h> @@ -59,7 +60,12 @@ #include "cpu.h" static struct map_desc h1940_iodesc[] __initdata = { - /* nothing here yet */ + [0] = { + .virtual = (unsigned long)H1940_LATCH, + .pfn = __phys_to_pfn(H1940_PA_LATCH), + .length = SZ_16K, + .type = MT_DEVICE + }, }; #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK @@ -92,6 +98,25 @@ static struct s3c2410_uartcfg h1940_uartcfgs[] = { } }; +/* Board control latch control */ + +static unsigned int latch_state = H1940_LATCH_DEFAULT; + +void h1940_latch_control(unsigned int clear, unsigned int set) +{ + unsigned long flags; + + local_irq_save(flags); + + latch_state &= ~clear; + latch_state |= set; + + __raw_writel(latch_state, H1940_LATCH); + + local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(h1940_latch_control); /** diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2410/s3c2400-gpio.c new file mode 100644 index 000000000000..5127f39fa9bf --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2400-gpio.c @@ -0,0 +1,45 @@ +/* linux/arch/arm/mach-s3c2410/gpio.c + * + * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org> + * + * S3C2400 GPIO support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Changelog + * 15-Jan-2006 LCVR Splitted from gpio.c, adding support for the S3C2400 + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> + +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include <asm/arch/regs-gpio.h> + +int s3c2400_gpio_getirq(unsigned int pin) +{ + if (pin < S3C2410_GPE0 || pin > S3C2400_GPE7_EINT7) + return -1; /* not valid interrupts */ + + return (pin - S3C2410_GPE0) + IRQ_EINT0; +} + +EXPORT_SYMBOL(s3c2400_gpio_getirq); diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/arch/arm/mach-s3c2410/s3c2400.h new file mode 100644 index 000000000000..8b2394e1ed40 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2400.h @@ -0,0 +1,31 @@ +/* arch/arm/mach-s3c2410/s3c2400.h + * + * Copyright (c) 2004 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Header file for S3C2400 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 09-Fev-2006 LCVR First version, based on s3c2410.h +*/ + +#ifdef CONFIG_CPU_S3C2400 + +extern int s3c2400_init(void); + +extern void s3c2400_map_io(struct map_desc *mach_desc, int size); + +extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c2400_init_clocks(int xtal); + +#else +#define s3c2400_init_clocks NULL +#define s3c2400_init_uarts NULL +#define s3c2400_map_io NULL +#define s3c2400_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c new file mode 100644 index 000000000000..d5e1caea1d23 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c @@ -0,0 +1,93 @@ +/* linux/arch/arm/mach-s3c2410/gpio.c + * + * Copyright (c) 2004-2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 GPIO support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Changelog + * 15-Jan-2006 LCVR Splitted from gpio.c + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> + +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include <asm/arch/regs-gpio.h> + +int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, + unsigned int config) +{ + void __iomem *reg = S3C2410_EINFLT0; + unsigned long flags; + unsigned long val; + + if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15) + return -1; + + config &= 0xff; + + pin -= S3C2410_GPG8_EINT16; + reg += pin & ~3; + + local_irq_save(flags); + + /* update filter width and clock source */ + + val = __raw_readl(reg); + val &= ~(0xff << ((pin & 3) * 8)); + val |= config << ((pin & 3) * 8); + __raw_writel(val, reg); + + /* update filter enable */ + + val = __raw_readl(S3C2410_EXTINT2); + val &= ~(1 << ((pin * 4) + 3)); + val |= on << ((pin * 4) + 3); + __raw_writel(val, S3C2410_EXTINT2); + + local_irq_restore(flags); + + return 0; +} + +EXPORT_SYMBOL(s3c2410_gpio_irqfilter); + +int s3c2410_gpio_getirq(unsigned int pin) +{ + if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23) + return -1; /* not valid interrupts */ + + if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) + return -1; /* not valid pin */ + + if (pin < S3C2410_GPF4) + return (pin - S3C2410_GPF0) + IRQ_EINT0; + + if (pin < S3C2410_GPG0) + return (pin - S3C2410_GPF4) + IRQ_EINT4; + + return (pin - S3C2410_GPG0) + IRQ_EINT8; +} + +EXPORT_SYMBOL(s3c2410_gpio_getirq); diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index 61768dac7fee..832fb86a03b4 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S @@ -72,7 +72,7 @@ ENTRY(s3c2410_cpu_suspend) @@ prepare cpu to sleep ldr r4, =S3C2410_REFRESH - ldr r5, =S3C2410_MISCCR + ldr r5, =S3C24XX_MISCCR ldr r6, =S3C2410_CLKCON ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB) ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB) @@ -133,12 +133,12 @@ ENTRY(s3c2410_cpu_resume) @@ load UART to allow us to print the two characters for @@ resume debug - mov r2, #S3C2410_PA_UART & 0xff000000 - orr r2, r2, #S3C2410_PA_UART & 0xff000 + mov r2, #S3C24XX_PA_UART & 0xff000000 + orr r2, r2, #S3C24XX_PA_UART & 0xff000 #if 0 /* SMDK2440 LED set */ - mov r14, #S3C2410_PA_GPIO + mov r14, #S3C24XX_PA_GPIO ldr r12, [ r14, #0x54 ] bic r12, r12, #3<<4 orr r12, r12, #1<<7 diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 72966d90e956..d921c1024ae0 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -92,22 +92,16 @@ ENTRY(v6_coherent_kern_range) * - the Icache does not read data from the write buffer */ ENTRY(v6_coherent_user_range) - bic r0, r0, #CACHE_LINE_SIZE - 1 -1: + #ifdef HARVARD_CACHE - mcr p15, 0, r0, c7, c10, 1 @ clean D line + bic r0, r0, #CACHE_LINE_SIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D line mcr p15, 0, r0, c7, c5, 1 @ invalidate I line -#endif - mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry - add r0, r0, #BTB_FLUSH_SIZE - mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry - add r0, r0, #BTB_FLUSH_SIZE - mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry - add r0, r0, #BTB_FLUSH_SIZE - mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry - add r0, r0, #BTB_FLUSH_SIZE + add r0, r0, #CACHE_LINE_SIZE cmp r0, r1 blo 1b +#endif + mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB #ifdef HARVARD_CACHE mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index de3ce1eec2ec..da9b35974118 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -142,7 +142,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, return NULL; addr = (unsigned long)area->addr; if (remap_area_pages(addr, pfn, size, flags)) { - vfree(addr); + vfree((void *)addr); return NULL; } return (void __iomem *) (offset + (char *)addr); diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index d0245a31d4dd..ef8d30a185a9 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -343,6 +343,12 @@ static struct mem_types mem_types[] __initdata = { PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE | PMD_SECT_TEX(1), .domain = DOMAIN_IO, + }, + [MT_NONSHARED_DEVICE] = { + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_NONSHARED_DEV | + PMD_SECT_AP_WRITE, + .domain = DOMAIN_IO, } }; diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 861b35947280..2d3823ec3153 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -241,7 +241,15 @@ ENTRY(xscale_flush_user_cache_range) * it also trashes the mini I-cache used by JTAG debuggers. */ ENTRY(xscale_coherent_kern_range) - /* FALLTHROUGH */ + bic r0, r0, #CACHELINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr /* * coherent_user_range(start, end) @@ -252,18 +260,16 @@ ENTRY(xscale_coherent_kern_range) * * - start - virtual start address * - end - virtual end address - * - * Note: single I-cache line invalidation isn't used here since - * it also trashes the mini I-cache used by JTAG debuggers. */ ENTRY(xscale_coherent_user_range) bic r0, r0, #CACHELINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache entry add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer mov pc, lr diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 1415930ceee1..6f8bc1f0e6a1 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -137,8 +137,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) if (spec) { init_MUTEX(&op_arm_sem); - if (spec->init() < 0) - return -ENODEV; + ret = spec->init(); + if (ret < 0) + return ret; op_arm_model = spec; init_driverfs(); diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 7ebc5a29db8d..3c2bfc0efdaf 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -34,7 +34,7 @@ DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; /*------------------------------------------------------------------------- - * Standard clock functions defined in asm/hardware/clock.h + * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ struct clk * clk_get(struct device *dev, const char *id) @@ -60,12 +60,8 @@ int clk_enable(struct clk *clk) int ret = 0; spin_lock_irqsave(&clockfw_lock, flags); - if (clk->enable) - ret = clk->enable(clk); - else if (arch_clock->clk_enable) + if (arch_clock->clk_enable) ret = arch_clock->clk_enable(clk); - else - printk(KERN_ERR "Could not enable clock %s\n", clk->name); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -77,41 +73,12 @@ void clk_disable(struct clk *clk) unsigned long flags; spin_lock_irqsave(&clockfw_lock, flags); - if (clk->disable) - clk->disable(clk); - else if (arch_clock->clk_disable) + if (arch_clock->clk_disable) arch_clock->clk_disable(clk); - else - printk(KERN_ERR "Could not disable clock %s\n", clk->name); spin_unlock_irqrestore(&clockfw_lock, flags); } EXPORT_SYMBOL(clk_disable); -int clk_use(struct clk *clk) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_use) - ret = arch_clock->clk_use(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; -} -EXPORT_SYMBOL(clk_use); - -void clk_unuse(struct clk *clk) -{ - unsigned long flags; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_unuse) - arch_clock->clk_unuse(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_unuse); - int clk_get_usecount(struct clk *clk) { unsigned long flags; @@ -146,7 +113,7 @@ void clk_put(struct clk *clk) EXPORT_SYMBOL(clk_put); /*------------------------------------------------------------------------- - * Optional clock functions defined in asm/hardware/clock.h + * Optional clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ long clk_round_rate(struct clk *clk, unsigned long rate) diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index ca3681a824ac..b4d5b9e4bfce 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -853,19 +853,19 @@ static int __init _omap_gpio_init(void) if (IS_ERR(gpio_ick)) printk("Could not get arm_gpio_ck\n"); else - clk_use(gpio_ick); + clk_enable(gpio_ick); } if (cpu_is_omap24xx()) { gpio_ick = clk_get(NULL, "gpios_ick"); if (IS_ERR(gpio_ick)) printk("Could not get gpios_ick\n"); else - clk_use(gpio_ick); + clk_enable(gpio_ick); gpio_fck = clk_get(NULL, "gpios_fck"); if (IS_ERR(gpio_ick)) printk("Could not get gpios_fck\n"); else - clk_use(gpio_fck); + clk_enable(gpio_fck); } #ifdef CONFIG_ARCH_OMAP15XX diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index be0e0f32a598..1cd2cace7e1b 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -190,11 +190,11 @@ static int omap_mcbsp_check(unsigned int id) static void omap_mcbsp_dsp_request(void) { if (cpu_is_omap1510() || cpu_is_omap16xx()) { - clk_use(mcbsp_dsp_ck); - clk_use(mcbsp_api_ck); + clk_enable(mcbsp_dsp_ck); + clk_enable(mcbsp_api_ck); /* enable 12MHz clock to mcbsp 1 & 3 */ - clk_use(mcbsp_dspxor_ck); + clk_enable(mcbsp_dspxor_ck); /* * DSP external peripheral reset @@ -208,9 +208,9 @@ static void omap_mcbsp_dsp_request(void) static void omap_mcbsp_dsp_free(void) { if (cpu_is_omap1510() || cpu_is_omap16xx()) { - clk_unuse(mcbsp_dspxor_ck); - clk_unuse(mcbsp_dsp_ck); - clk_unuse(mcbsp_api_ck); + clk_disable(mcbsp_dspxor_ck); + clk_disable(mcbsp_dsp_ck); + clk_disable(mcbsp_api_ck); } } diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index e40fcc8b43d4..5cc6775c789c 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c @@ -88,7 +88,7 @@ static int __init omap_ocpi_init(void) if (IS_ERR(ocpi_ck)) return PTR_ERR(ocpi_ck); - clk_use(ocpi_ck); + clk_enable(ocpi_ck); ocpi_enable(); printk("OMAP OCPI interconnect driver loaded\n"); @@ -102,7 +102,7 @@ static void __exit omap_ocpi_exit(void) if (!cpu_is_omap16xx()) return; - clk_unuse(ocpi_ck); + clk_disable(ocpi_ck); clk_put(ocpi_ck); } diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 792f66375830..ee82763b02b8 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <asm/mach/map.h> +#include <asm/tlb.h> #include <asm/io.h> #include <asm/cacheflush.h> @@ -96,6 +97,14 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].length); /* + * Normally devicemaps_init() would flush caches and tlb after + * mdesc->map_io(), but since we're called from map_io(), we + * must do it here. + */ + local_flush_tlb_all(); + flush_cache_all(); + + /* * Looks like we need to preserve some bootloader code at the * beginning of SRAM for jumping to flash for reboot to work... */ diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig index 274e07019b46..dee23d87fc5a 100644 --- a/arch/arm26/Kconfig +++ b/arch/arm26/Kconfig @@ -53,14 +53,14 @@ config GENERIC_ISA_DMA config ARCH_MAY_HAVE_PC_FDC bool - default y source "init/Kconfig" menu "System Type" -comment "Archimedes/A5000 Implementations (select only ONE)" +choice + prompt "Archimedes/A5000 Implementations" config ARCH_ARC bool "Archimedes" @@ -73,6 +73,7 @@ config ARCH_ARC config ARCH_A5K bool "A5000" + select ARCH_MAY_HAVE_PC_FDC help Say Y here to to support the Acorn A5000. @@ -87,6 +88,7 @@ config PAGESIZE_16 Say Y here if your Archimedes or A5000 system has only 2MB of memory, otherwise say N. The resulting kernel will not run on a machine with 4MB of memory. +endchoice endmenu config ISA_DMA_API diff --git a/arch/arm26/kernel/fiq.c b/arch/arm26/kernel/fiq.c index 08a97c9498ff..a24272b61f30 100644 --- a/arch/arm26/kernel/fiq.c +++ b/arch/arm26/kernel/fiq.c @@ -104,14 +104,14 @@ void set_fiq_regs(struct pt_regs *regs) { register unsigned long tmp, tmp2; __asm__ volatile ( - "mov %0, pc - bic %1, %0, #0x3 - orr %1, %1, %3 - teqp %1, #0 @ select FIQ mode - mov r0, r0 - ldmia %2, {r8 - r14} - teqp %0, #0 @ return to SVC mode - mov r0, r0" + "mov %0, pc \n" + "bic %1, %0, #0x3 \n" + "orr %1, %1, %3 \n" + "teqp %1, #0 @ select FIQ mode \n" + "mov r0, r0 \n" + "ldmia %2, {r8 - r14} \n" + "teqp %0, #0 @ return to SVC mode \n" + "mov r0, r0 " : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26) /* These registers aren't modified by the above code in a way @@ -125,14 +125,14 @@ void get_fiq_regs(struct pt_regs *regs) { register unsigned long tmp, tmp2; __asm__ volatile ( - "mov %0, pc - bic %1, %0, #0x3 - orr %1, %1, %3 - teqp %1, #0 @ select FIQ mode - mov r0, r0 - stmia %2, {r8 - r14} - teqp %0, #0 @ return to SVC mode - mov r0, r0" + "mov %0, pc \n" + "bic %1, %0, #0x3 \n" + "orr %1, %1, %3 \n" + "teqp %1, #0 @ select FIQ mode \n" + "mov r0, r0 \n" + "stmia %2, {r8 - r14} \n" + "teqp %0, #0 @ return to SVC mode \n" + "mov r0, r0 " : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | MODE_FIQ26) /* These registers aren't modified by the above code in a way diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c index ce2055bdc9ee..2a48c12100c0 100644 --- a/arch/arm26/kernel/signal.c +++ b/arch/arm26/kernel/signal.c @@ -480,6 +480,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -493,7 +494,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (current->ptrace & PT_SINGLESTEP) ptrace_cancel_bpt(current); - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_signal(signr, &info, oldset, regs, syscall); if (current->ptrace & PT_SINGLESTEP) diff --git a/arch/cris/Makefile b/arch/cris/Makefile index ea65d585cf5e..ee114699ef8e 100644 --- a/arch/cris/Makefile +++ b/arch/cris/Makefile @@ -119,7 +119,7 @@ $(SRC_ARCH)/.links: @ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib @ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch @ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S - @ln -sfn $(SRC_ARCH)/$(SARCH)/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c + @ln -sfn $(SRC_ARCH)/$(SARCH)/kernel/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c @touch $@ # Create link to sub arch includes diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index f214f74f264e..961c0d58ded4 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -202,18 +202,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int i; unsigned long tmp; + ret = 0; for (i = 0; i <= PT_MAX; i++) { tmp = get_reg(child, i); if (put_user(tmp, datap)) { ret = -EFAULT; - goto out_tsk; + break; } data += sizeof(long); } - ret = 0; break; } @@ -222,10 +222,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int i; unsigned long tmp; + ret = 0; for (i = 0; i <= PT_MAX; i++) { if (get_user(tmp, datap)) { ret = -EFAULT; - goto out_tsk; + break; } if (i == PT_DCCR) { @@ -237,7 +238,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) data += sizeof(long); } - ret = 0; break; } diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c index d11206e467ab..1ba57efff60d 100644 --- a/arch/cris/kernel/setup.c +++ b/arch/cris/kernel/setup.c @@ -24,7 +24,6 @@ /* * Setup options */ -struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info; extern int root_mountflags; diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 5b7146f54fd5..679c1d5cc958 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -35,74 +35,22 @@ struct fdpic_func_descriptor { unsigned long GOT; }; -static int do_signal(sigset_t *oldset); - /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - __frame->gr8 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset)) - /* return the signal number as the return value of this function - * - this is an utterly evil hack. syscalls should not invoke do_signal() - * as entry.S sets regs->gr8 to the return value of the system call - * - we can't just use sigpending() as we'd have to discard SIG_IGN signals - * and call waitpid() if SIGCHLD needed discarding - * - this only works on the i386 because it passes arguments to the signal - * handler on the stack, and the return value in EAX is effectively - * discarded - */ - return __frame->gr8; - } -} - -asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - __frame->gr8 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset)) - /* return the signal number as the return value of this function - * - this is an utterly evil hack. syscalls should not invoke do_signal() - * as entry.S sets regs->gr8 to the return value of the system call - * - we can't just use sigpending() as we'd have to discard SIG_IGN signals - * and call waitpid() if SIGCHLD needed discarding - * - this only works on the i386 because it passes arguments to the signal - * handler on the stack, and the return value in EAX is effectively - * discarded - */ - return __frame->gr8; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int sys_sigaction(int sig, @@ -372,11 +320,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sig(SIGSEGV, current); - return 0; + return -EFAULT; } /* end setup_frame() */ @@ -471,11 +419,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sig(SIGSEGV, current); - return 0; + return -EFAULT; } /* end setup_rt_frame() */ @@ -516,7 +464,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, else ret = setup_frame(sig, ka, oldset); - if (ret) { + if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -536,10 +484,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(sigset_t *oldset) +static void do_signal(void) { struct k_sigaction ka; siginfo_t info; + sigset_t *oldset; int signr; /* @@ -549,43 +498,62 @@ static int do_signal(sigset_t *oldset) * if so. */ if (!user_mode(__frame)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, __frame, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset); + if (signr > 0) { + if (handle_signal(signr, &info, &ka, oldset) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; + } no_signal: /* Did we come from a system call? */ if (__frame->syscallno >= 0) { /* Restart the system call - no handlers present */ - if (__frame->gr8 == -ERESTARTNOHAND || - __frame->gr8 == -ERESTARTSYS || - __frame->gr8 == -ERESTARTNOINTR) { + switch (__frame->gr8) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; - } + break; - if (__frame->gr8 == -ERESTART_RESTARTBLOCK){ + case -ERESTART_RESTARTBLOCK: __frame->gr8 = __NR_restart_syscall; __frame->pc -= 4; + break; } } - return 0; + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* end do_signal() */ /*****************************************************************************/ /* * notification of userspace execution resumption - * - triggered by current->work.notify_resume + * - triggered by the TIF_WORK_MASK flags */ asmlinkage void do_notify_resume(__u32 thread_info_flags) { @@ -594,7 +562,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) clear_thread_flag(TIF_SINGLESTEP); /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(NULL); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(); } /* end do_notify_resume() */ diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index cbde675bc95c..0afec8566e7b 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -47,15 +47,6 @@ config DMI source "init/Kconfig" -config DOUBLEFAULT - default y - bool "Enable doublefault exception handler" if EMBEDDED - help - This option allows trapping of rare doublefault exceptions that - would otherwise cause a system to silently reboot. Disabling this - option saves about 4k and might cause you much additional grey - hair. - menu "Processor type and features" choice @@ -451,12 +442,50 @@ config HIGHMEM4G config HIGHMEM64G bool "64GB" + depends on X86_CMPXCHG64 help Select this if you have a 32-bit processor and more than 4 gigabytes of physical RAM. endchoice +choice + depends on EXPERIMENTAL && !X86_PAE + prompt "Memory split" + default VMSPLIT_3G + help + Select the desired split between kernel and user memory. + + If the address range available to the kernel is less than the + physical memory installed, the remaining memory will be available + as "high memory". Accessing high memory is a little more costly + than low memory, as it needs to be mapped into the kernel first. + Note that increasing the kernel address space limits the range + available to user programs, making the address space there + tighter. Selecting anything other than the default 3G/1G split + will also likely make your kernel incompatible with binary-only + kernel modules. + + If you are not absolutely sure what you are doing, leave this + option alone! + + config VMSPLIT_3G + bool "3G/1G user/kernel split" + config VMSPLIT_3G_OPT + bool "3G/1G user/kernel split (for full 1G low memory)" + config VMSPLIT_2G + bool "2G/2G user/kernel split" + config VMSPLIT_1G + bool "1G/3G user/kernel split" +endchoice + +config PAGE_OFFSET + hex + default 0xB0000000 if VMSPLIT_3G_OPT + default 0x78000000 if VMSPLIT_2G + default 0x40000000 if VMSPLIT_1G + default 0xC0000000 + config HIGHMEM bool depends on HIGHMEM64G || HIGHMEM4G @@ -711,6 +740,15 @@ config HOTPLUG_CPU Say N. +config DOUBLEFAULT + default y + bool "Enable doublefault exception handler" if EMBEDDED + help + This option allows trapping of rare doublefault exceptions that + would otherwise cause a system to silently reboot. Disabling this + option saves about 4k and might cause you much additional grey + hair. + endmenu diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 6a431b926019..3cbe6e9cb9fc 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -644,6 +644,8 @@ CONFIG_8139TOO_PIO=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile index 267ca48e1b6c..d51c7313cae8 100644 --- a/arch/i386/kernel/acpi/Makefile +++ b/arch/i386/kernel/acpi/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o ifneq ($(CONFIG_ACPI_PROCESSOR),) -obj-y += cstate.o +obj-y += cstate.o processor.o endif diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 2111529dea77..79577f0ace98 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -248,10 +248,17 @@ acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end) acpi_table_print_madt_entry(header); - /* Register even disabled CPUs for cpu hotplug */ - - x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + /* Record local apic id only when enabled */ + if (processor->flags.enabled) + x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + /* + * We need to register disabled CPU as well to permit + * counting disabled CPUs. This allows us to size + * cpus_possible_map more accurately, to permit + * to not preallocating memory for all NR_CPUS + * when we use CPU hotplug. + */ mp_register_lapic(processor->id, /* APIC ID */ processor->flags.enabled); /* Enabled? */ @@ -464,7 +471,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) * success: return IRQ number (>=0) * failure: return < 0 */ -int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) +int acpi_register_gsi(u32 gsi, int triggering, int polarity) { unsigned int irq; unsigned int plat_gsi = gsi; @@ -476,14 +483,14 @@ int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { extern void eisa_set_level_irq(unsigned int irq); - if (edge_level == ACPI_LEVEL_SENSITIVE) + if (triggering == ACPI_LEVEL_SENSITIVE) eisa_set_level_irq(gsi); } #endif #ifdef CONFIG_X86_IO_APIC if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { - plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low); + plat_gsi = mp_register_gsi(gsi, triggering, polarity); } #endif acpi_gsi_to_irq(plat_gsi, &irq); diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c index 4c3036ba65df..25db49ef1770 100644 --- a/arch/i386/kernel/acpi/cstate.c +++ b/arch/i386/kernel/acpi/cstate.c @@ -14,64 +14,6 @@ #include <acpi/processor.h> #include <asm/acpi.h> -static void acpi_processor_power_init_intel_pdc(struct acpi_processor_power - *pow) -{ - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } - - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_C_CAPABILITY_SMP; - - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pow->pdc = obj_list; - - return; -} - -/* Initialize _PDC data based on the CPU vendor */ -void acpi_processor_power_init_pdc(struct acpi_processor_power *pow, - unsigned int cpu) -{ - struct cpuinfo_x86 *c = cpu_data + cpu; - - pow->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL) - acpi_processor_power_init_intel_pdc(pow); - - return; -} - -EXPORT_SYMBOL(acpi_processor_power_init_pdc); - /* * Initialize bm_flags based on the CPU cache properties * On SMP it depends on cache configuration diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c new file mode 100644 index 000000000000..9f4cc02717ec --- /dev/null +++ b/arch/i386/kernel/acpi/processor.c @@ -0,0 +1,75 @@ +/* + * arch/i386/kernel/acpi/processor.c + * + * Copyright (C) 2005 Intel Corporation + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * - Added _PDC for platforms with Intel CPUs + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> + +#include <acpi/processor.h> +#include <asm/acpi.h> + +static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + buf[2] = ACPI_PDC_C_CAPABILITY_SMP; + + if (cpu_has(c, X86_FEATURE_EST)) + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + return; +} + +/* Initialize _PDC data based on the CPU vendor */ +void arch_acpi_processor_init_pdc(struct acpi_processor *pr) +{ + unsigned int cpu = pr->id; + struct cpuinfo_x86 *c = cpu_data + cpu; + + pr->pdc = NULL; + if (c->x86_vendor == X86_VENDOR_INTEL) + init_intel_pdc(pr, c); + + return; +} + +EXPORT_SYMBOL(arch_acpi_processor_init_pdc); diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index acd3f1e34ca6..f39e09ef64ec 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -75,8 +75,10 @@ void ack_bad_irq(unsigned int irq) * holds up an irq slot - in excessive cases (when multiple * unexpected vectors occur) that might lock up the APIC * completely. + * But only ack when the APIC is enabled -AK */ - ack_APIC_irq(); + if (cpu_has_apic) + ack_APIC_irq(); } void __init apic_intr_init(void) @@ -1303,6 +1305,7 @@ int __init APIC_init_uniprocessor (void) if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); return -1; } diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 333578a4e91a..0810f81f2a05 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -282,3 +282,11 @@ int __init amd_init_cpu(void) } //early_arch_initcall(amd_init_cpu); + +static int __init amd_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_AMD] = NULL; + return 0; +} + +late_initcall(amd_exit_cpu); diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c index 394814e57672..f52669ecb93f 100644 --- a/arch/i386/kernel/cpu/centaur.c +++ b/arch/i386/kernel/cpu/centaur.c @@ -405,10 +405,6 @@ static void __init init_centaur(struct cpuinfo_x86 *c) winchip2_protect_mcr(); #endif break; - case 10: - name="4"; - /* no info on the WC4 yet */ - break; default: name="??"; } @@ -474,3 +470,11 @@ int __init centaur_init_cpu(void) } //early_arch_initcall(centaur_init_cpu); + +static int __init centaur_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_CENTAUR] = NULL; + return 0; +} + +late_initcall(centaur_exit_cpu); diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 15aee26ec2b6..7eb9213734a3 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -44,6 +44,7 @@ static void default_init(struct cpuinfo_x86 * c) static struct cpu_dev default_cpu = { .c_init = default_init, + .c_vendor = "Unknown", }; static struct cpu_dev * this_cpu = &default_cpu; @@ -150,6 +151,7 @@ static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) { char *v = c->x86_vendor_id; int i; + static int printed; for (i = 0; i < X86_VENDOR_NUM; i++) { if (cpu_devs[i]) { @@ -159,10 +161,17 @@ static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) c->x86_vendor = i; if (!early) this_cpu = cpu_devs[i]; - break; + return; } } } + if (!printed) { + printed++; + printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); + printk(KERN_ERR "CPU: Your system may be unstable.\n"); + } + c->x86_vendor = X86_VENDOR_UNKNOWN; + this_cpu = &default_cpu; } diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 7975e79d5fa4..3852d0a4c1b5 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -295,68 +295,6 @@ acpi_cpufreq_guess_freq ( } -/* - * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities - * of this driver - * @perf: processor-specific acpi_io_data struct - * @cpu: CPU being initialized - * - * To avoid issues with legacy OSes, some BIOSes require to be informed of - * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC - * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in - * driver/acpi/processor.c - */ -static void -acpi_processor_cpu_init_pdc_est( - struct acpi_processor_performance *perf, - unsigned int cpu, - struct acpi_object_list *obj_list - ) -{ - union acpi_object *obj; - u32 *buf; - struct cpuinfo_x86 *c = cpu_data + cpu; - dprintk("acpi_processor_cpu_init_pdc_est\n"); - - if (!cpu_has(c, X86_FEATURE_EST)) - return; - - /* Initialize pdc. It will be used later. */ - if (!obj_list) - return; - - if (!(obj_list->count && obj_list->pointer)) - return; - - obj = obj_list->pointer; - if ((obj->buffer.length == 12) && obj->buffer.pointer) { - buf = (u32 *)obj->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - perf->pdc = obj_list; - } - return; -} - - -/* CPU specific PDC initialization */ -static void -acpi_processor_cpu_init_pdc( - struct acpi_processor_performance *perf, - unsigned int cpu, - struct acpi_object_list *obj_list - ) -{ - struct cpuinfo_x86 *c = cpu_data + cpu; - dprintk("acpi_processor_cpu_init_pdc\n"); - perf->pdc = NULL; - if (cpu_has(c, X86_FEATURE_EST)) - acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list); - return; -} - - static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) @@ -367,14 +305,7 @@ acpi_cpufreq_cpu_init ( unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; - union acpi_object arg0 = {ACPI_TYPE_BUFFER}; - u32 arg0_buf[3]; - struct acpi_object_list arg_list = {1, &arg0}; - dprintk("acpi_cpufreq_cpu_init\n"); - /* setup arg_list for _PDC settings */ - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) @@ -382,9 +313,7 @@ acpi_cpufreq_cpu_init ( acpi_io_data[cpu] = data; - acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list); result = acpi_processor_register_performance(&data->acpi_data, cpu); - data->acpi_data.pdc = NULL; if (result) goto err_free; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 9a826cde4fd1..c173c0fa117a 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -362,22 +362,10 @@ static struct acpi_processor_performance p; */ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { - union acpi_object arg0 = {ACPI_TYPE_BUFFER}; - u32 arg0_buf[3]; - struct acpi_object_list arg_list = {1, &arg0}; unsigned long cur_freq; int result = 0, i; unsigned int cpu = policy->cpu; - /* _PDC settings */ - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0] = ACPI_PDC_REVISION_ID; - arg0_buf[1] = 1; - arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP_MSR; - - p.pdc = &arg_list; - /* register with ACPI core */ if (acpi_processor_register_performance(&p, cpu)) { dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index 75015975d038..00f2e058797c 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -345,7 +345,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) /* * Handle National Semiconductor branded processors */ -static void __devinit init_nsc(struct cpuinfo_x86 *c) +static void __init init_nsc(struct cpuinfo_x86 *c) { /* There may be GX1 processors in the wild that are branded * NSC and not Cyrix. @@ -444,6 +444,14 @@ int __init cyrix_init_cpu(void) //early_arch_initcall(cyrix_init_cpu); +static int __init cyrix_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_CYRIX] = NULL; + return 0; +} + +late_initcall(cyrix_exit_cpu); + static struct cpu_dev nsc_cpu_dev __initdata = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, @@ -458,3 +466,11 @@ int __init nsc_init_cpu(void) } //early_arch_initcall(nsc_init_cpu); + +static int __init nsc_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_NSC] = NULL; + return 0; +} + +late_initcall(nsc_exit_cpu); diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index fbfd374aa336..ffe58cee0c48 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -43,13 +43,23 @@ static struct _cache_table cache_table[] __cpuinitdata = { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */ { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */ { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */ + { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */ { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */ + { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */ + { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */ + { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ + { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */ + { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ + { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */ + { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */ { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ @@ -57,6 +67,7 @@ static struct _cache_table cache_table[] __cpuinitdata = { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */ { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ + { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */ { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */ { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ @@ -141,6 +152,7 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le return 0; } +/* will only be called once; __init is safe here */ static int __init find_num_cache_leaves(void) { unsigned int eax, ebx, ecx, edx; diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 1e9db198c440..3b4618bed70d 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -44,12 +44,10 @@ #include <asm/msr.h> #include "mtrr.h" -#define MTRR_VERSION "2.0 (20020519)" - u32 num_var_ranges = 0; unsigned int *usage_table; -static DECLARE_MUTEX(main_lock); +static DECLARE_MUTEX(mtrr_sem); u32 size_or_mask, size_and_mask; @@ -335,7 +333,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, /* No CPU hotplug when we change MTRR entries */ lock_cpu_hotplug(); /* Search for existing MTRR */ - down(&main_lock); + down(&mtrr_sem); for (i = 0; i < num_var_ranges; ++i) { mtrr_if->get(i, &lbase, &lsize, <ype); if (base >= lbase + lsize) @@ -373,7 +371,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, printk(KERN_INFO "mtrr: no more MTRRs available\n"); error = i; out: - up(&main_lock); + up(&mtrr_sem); unlock_cpu_hotplug(); return error; } @@ -466,7 +464,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) max = num_var_ranges; /* No CPU hotplug when we change MTRR entries */ lock_cpu_hotplug(); - down(&main_lock); + down(&mtrr_sem); if (reg < 0) { /* Search for existing MTRR */ for (i = 0; i < max; ++i) { @@ -505,7 +503,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) set_mtrr(reg, 0, 0, 0); error = reg; out: - up(&main_lock); + up(&mtrr_sem); unlock_cpu_hotplug(); return error; } @@ -671,7 +669,6 @@ void __init mtrr_bp_init(void) break; } } - printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION); if (mtrr_if) { set_num_var_ranges(); @@ -688,7 +685,7 @@ void mtrr_ap_init(void) if (!mtrr_if || !use_intel()) return; /* - * Ideally we should hold main_lock here to avoid mtrr entries changed, + * Ideally we should hold mtrr_sem here to avoid mtrr entries changed, * but this routine will be called in cpu boot time, holding the lock * breaks it. This routine is called in two cases: 1.very earily time * of software resume, when there absolutely isn't mtrr entry changes; diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c index 30898a260a5c..ad87fa58058d 100644 --- a/arch/i386/kernel/cpu/nexgen.c +++ b/arch/i386/kernel/cpu/nexgen.c @@ -61,3 +61,11 @@ int __init nexgen_init_cpu(void) } //early_arch_initcall(nexgen_init_cpu); + +static int __init nexgen_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_NEXGEN] = NULL; + return 0; +} + +late_initcall(nexgen_exit_cpu); diff --git a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c index 8602425628ca..d08d5a2811c8 100644 --- a/arch/i386/kernel/cpu/rise.c +++ b/arch/i386/kernel/cpu/rise.c @@ -51,3 +51,11 @@ int __init rise_init_cpu(void) } //early_arch_initcall(rise_init_cpu); + +static int __init rise_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_RISE] = NULL; + return 0; +} + +late_initcall(rise_exit_cpu); diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index fc426380366b..bdbeb77f4e22 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -84,7 +84,7 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) #endif } -static void transmeta_identify(struct cpuinfo_x86 * c) +static void __init transmeta_identify(struct cpuinfo_x86 * c) { u32 xlvl; generic_identify(c); @@ -111,3 +111,11 @@ int __init transmeta_init_cpu(void) } //early_arch_initcall(transmeta_init_cpu); + +static int __init transmeta_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_TRANSMETA] = NULL; + return 0; +} + +late_initcall(transmeta_exit_cpu); diff --git a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c index 264fcad559d5..2cd988f6dc55 100644 --- a/arch/i386/kernel/cpu/umc.c +++ b/arch/i386/kernel/cpu/umc.c @@ -31,3 +31,11 @@ int __init umc_init_cpu(void) } //early_arch_initcall(umc_init_cpu); + +static int __init umc_exit_cpu(void) +{ + cpu_devs[X86_VENDOR_UMC] = NULL; + return 0; +} + +late_initcall(umc_exit_cpu); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 5884469f6bfe..2bee6499edd9 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -398,7 +398,11 @@ ignore_int: pushl 32(%esp) pushl 40(%esp) pushl $int_msg +#ifdef CONFIG_EARLY_PRINTK + call early_printk +#else call printk +#endif addl $(5*4),%esp popl %ds popl %es diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 91a64016956e..0102f3d50e57 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -1080,7 +1080,7 @@ void __init mp_config_acpi_legacy_irqs (void) #define MAX_GSI_NUM 4096 -int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) +int mp_register_gsi (u32 gsi, int triggering, int polarity) { int ioapic = -1; int ioapic_pin = 0; @@ -1129,7 +1129,7 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit); - if (edge_level) { + if (triggering == ACPI_LEVEL_SENSITIVE) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. @@ -1151,8 +1151,8 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) } io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, - edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1, - active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1); + triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, + polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index d661703ac1cb..63f39a7e2c96 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -138,7 +138,7 @@ static int __init check_nmi_watchdog(void) if (nmi_watchdog == NMI_LOCAL_APIC) smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 2185377fdde1..0480454ebffa 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -297,8 +297,10 @@ void show_regs(struct pt_regs * regs) if (user_mode(regs)) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); - printk(" EFLAGS: %08lx %s (%s)\n", - regs->eflags, print_tainted(), system_utsname.release); + printk(" EFLAGS: %08lx %s (%s %.*s)\n", + regs->eflags, print_tainted(), system_utsname.release, + (int)strcspn(system_utsname.version, " "), + system_utsname.version); printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", regs->eax,regs->ebx,regs->ecx,regs->edx); printk("ESI: %08lx EDI: %08lx EBP: %08lx", diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c index aaf89cb2bc51..87ccdac84928 100644 --- a/arch/i386/kernel/quirks.c +++ b/arch/i386/kernel/quirks.c @@ -25,8 +25,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) /* enable access to config space*/ pci_read_config_byte(dev, 0xf4, &config); - config |= 0x2; - pci_write_config_byte(dev, 0xf4, config); + pci_write_config_byte(dev, 0xf4, config|0x2); /* read xTPR register */ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); @@ -42,9 +41,9 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) #endif } - config &= ~0x2; - /* disable access to config space*/ - pci_write_config_byte(dev, 0xf4, config); + /* put back the original value for config space*/ + if (!(config & 0x2)) + pci_write_config_byte(dev, 0xf4, config); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index adcd069db91e..963616d364ec 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -37,51 +37,17 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - struct pt_regs * regs = (struct pt_regs *) &history0; - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->eax = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - -asmlinkage int -sys_rt_sigsuspend(struct pt_regs regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (regs.ecx != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs.eax = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(®s, &saveset)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int @@ -433,11 +399,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(sig, current); - return 0; + return -EFAULT; } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -527,11 +493,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(sig, current); - return 0; + return -EFAULT; } /* @@ -581,7 +547,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, else ret = setup_frame(sig, ka, oldset, regs); - if (ret) { + if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) @@ -598,11 +564,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) +static void fastcall do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -613,12 +580,14 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) * CS suffices. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -628,38 +597,55 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) * have been cleared if the watchpoint triggered * inside the kernel. */ - if (unlikely(current->thread.debugreg[7])) { + if (unlikely(current->thread.debugreg[7])) set_debugreg(current->thread.debugreg[7], 7); - } /* Whee! Actually deliver the signal. */ - return handle_signal(signr, &info, &ka, oldset, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; } - no_signal: +no_signal: /* Did we come from a system call? */ if (regs->orig_eax >= 0) { /* Restart the system call - no handlers present */ - if (regs->eax == -ERESTARTNOHAND || - regs->eax == -ERESTARTSYS || - regs->eax == -ERESTARTNOINTR) { + switch (regs->eax) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: regs->eax = regs->orig_eax; regs->eip -= 2; - } - if (regs->eax == -ERESTART_RESTARTBLOCK){ + break; + + case -ERESTART_RESTARTBLOCK: regs->eax = __NR_restart_syscall; regs->eip -= 2; + break; } } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* * notification of userspace execution resumption - * - triggered by current->work.notify_resume + * - triggered by the TIF_WORK_MASK flags */ __attribute__((regparm(3))) -void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, +void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags) { /* Pending single-step? */ @@ -667,9 +653,10 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, regs->eflags |= TF_MASK; clear_thread_flag(TIF_SINGLESTEP); } + /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs,oldset); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs); clear_thread_flag(TIF_IRET); } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 255adb498268..fb00ab7b7612 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -87,11 +87,7 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; EXPORT_SYMBOL(cpu_callout_map); -#ifdef CONFIG_HOTPLUG_CPU -cpumask_t cpu_possible_map = CPU_MASK_ALL; -#else cpumask_t cpu_possible_map; -#endif EXPORT_SYMBOL(cpu_possible_map); static cpumask_t smp_commenced_mask; diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 6ff3e5243226..ac687d00a1ce 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -294,3 +294,19 @@ ENTRY(sys_call_table) .long sys_inotify_add_watch .long sys_inotify_rm_watch .long sys_migrate_pages + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_pselect6 + .long sys_ppoll + .long sys_unshare /* 310 */ diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 591a642af884..a7f5a2aceba2 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -45,6 +45,15 @@ static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ static unsigned long long monotonic_base; static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; +/* Avoid compensating for lost ticks before TSCs are synched */ +static int detect_lost_ticks; +static int __init start_lost_tick_compensation(void) +{ + detect_lost_ticks = 1; + return 0; +} +late_initcall(start_lost_tick_compensation); + /* convert from cycles(64bits) => nanoseconds (64bits) * basic equation: * ns = cycles / (freq / ns_per_sec) @@ -196,7 +205,8 @@ static void mark_offset_tsc_hpet(void) /* lost tick compensation */ offset = hpet_readl(HPET_T0_CMP) - hpet_tick; - if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { + if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0)) + && detect_lost_ticks) { int lost_ticks = (offset - hpet_last) / hpet_tick; jiffies_64 += lost_ticks; } @@ -426,7 +436,7 @@ static void mark_offset_tsc(void) delta += delay_at_last_interrupt; lost = delta/(1000000/HZ); delay = delta%(1000000/HZ); - if (lost >= 2) { + if (lost >= 2 && detect_lost_ticks) { jiffies_64 += lost-1; /* sanity check to ensure we're not always losing ticks */ diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 0aaebf3e1cfa..b814dbdcc91e 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -166,7 +166,8 @@ static void show_trace_log_lvl(struct task_struct *task, stack = (unsigned long*)context->previous_esp; if (!stack) break; - printk(KERN_EMERG " =======================\n"); + printk(log_lvl); + printk(" =======================\n"); } } @@ -239,9 +240,11 @@ void show_registers(struct pt_regs *regs) } print_modules(); printk(KERN_EMERG "CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\n" - "EFLAGS: %08lx (%s) \n", + "EFLAGS: %08lx (%s %.*s) \n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, - print_tainted(), regs->eflags, system_utsname.release); + print_tainted(), regs->eflags, system_utsname.release, + (int)strcspn(system_utsname.version, " "), + system_utsname.version); print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip); printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 72a1b9cae2e4..6e4c3baef6cc 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -240,7 +240,7 @@ static cpumask_t smp_commenced_mask = CPU_MASK_NONE; cpumask_t cpu_callin_map = CPU_MASK_NONE; cpumask_t cpu_callout_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_callout_map); -cpumask_t cpu_possible_map = CPU_MASK_ALL; +cpumask_t cpu_possible_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_possible_map); /* The per processor IRQ masks (these are usually kept in sync) */ diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c index 21654be3f73f..acc18138fb22 100644 --- a/arch/i386/oprofile/backtrace.c +++ b/arch/i386/oprofile/backtrace.c @@ -49,7 +49,9 @@ dump_backtrace(struct frame_head * head) * | stack | * --------------- saved regs->ebp value if valid (frame_head address) * . . - * --------------- struct pt_regs stored on stack (struct pt_regs *) + * --------------- saved regs->rsp value if x86_64 + * | | + * --------------- struct pt_regs * stored on stack if 32-bit * | | * . . * | | @@ -57,13 +59,26 @@ dump_backtrace(struct frame_head * head) * | | * | | \/ Lower addresses * - * Thus, &pt_regs <-> stack base restricts the valid(ish) ebp values + * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the + * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other + * exceptions use special stacks, maintained by the interrupt stack table + * (IST). These stacks are set up in trap_init() in + * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point + * to the kernel stack; instead, it points to some location on the NMI + * stack. On the other hand, regs->rsp is the stack pointer saved when the + * NMI occurred. (2) For 32-bit, regs->esp is not valid because the + * processor does not save %esp on the kernel stack when interrupts occur + * in the kernel mode. */ #ifdef CONFIG_FRAME_POINTER static int valid_kernel_stack(struct frame_head * head, struct pt_regs * regs) { unsigned long headaddr = (unsigned long)head; +#ifdef CONFIG_X86_64 + unsigned long stack = (unsigned long)regs->rsp; +#else unsigned long stack = (unsigned long)regs; +#endif unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE; return headaddr > stack && headaddr < stack_base; diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index e715aa930036..3ca59cad05f3 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -539,6 +539,11 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH7_30: case PCI_DEVICE_ID_INTEL_ICH7_31: case PCI_DEVICE_ID_INTEL_ESB2_0: + case PCI_DEVICE_ID_INTEL_ICH8_0: + case PCI_DEVICE_ID_INTEL_ICH8_1: + case PCI_DEVICE_ID_INTEL_ICH8_2: + case PCI_DEVICE_ID_INTEL_ICH8_3: + case PCI_DEVICE_ID_INTEL_ICH8_4: r->name = "PIIX/ICH"; r->get = pirq_piix_get; r->set = pirq_piix_set; diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 4bb4d4b0f73a..0ee8a983708c 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -36,8 +36,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) while (1) { ++cfg_num; if (cfg_num >= pci_mmcfg_config_num) { - /* Not found - fallback to type 1 */ - return 0; + break; } cfg = &pci_mmcfg_config[cfg_num]; if (cfg->pci_segment_group_number != seg) @@ -46,6 +45,18 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) (cfg->end_bus_number >= bus)) return cfg->base_address; } + + /* Handle more broken MCFG tables on Asus etc. + They only contain a single entry for bus 0-0. Assume + this applies to all busses. */ + cfg = &pci_mmcfg_config[0]; + if (pci_mmcfg_config_num == 1 && + cfg->pci_segment_group_number == 0 && + (cfg->start_bus_number | cfg->end_bus_number) == 0) + return cfg->base_address; + + /* Fall back to type 0 */ + return 0; } static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 199eeaf0f4e3..845cd0902a50 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -194,7 +194,6 @@ config IA64_L1_CACHE_SHIFT default "7" if MCKINLEY default "6" if ITANIUM -# align cache-sensitive data to 64 bytes config IA64_CYCLONE bool "Cyclone (EXA) Time Source support" help @@ -374,6 +373,9 @@ config IA64_PALINFO To use this option, you have to ensure that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. +config SGI_SN + def_bool y if (IA64_SGI_SN2 || IA64_GENERIC) + source "drivers/firmware/Kconfig" source "fs/Kconfig.binfmt" diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 1d07d8072ec2..991c07b57c24 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -557,6 +557,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index b1e8f09e9fd5..6859119bc9dd 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -565,6 +565,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 0856ca67dd50..53899dc8eb53 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -548,6 +548,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 275a26c6e5aa..dcbc78a4cfa4 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -565,6 +565,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c index d58003f1ad02..c9104bfff667 100644 --- a/arch/ia64/dig/setup.c +++ b/arch/ia64/dig/setup.c @@ -25,16 +25,6 @@ #include <asm/machvec.h> #include <asm/system.h> -/* - * This is here so we can use the CMOS detection in ide-probe.c to - * determine what drives are present. In theory, we don't need this - * as the auto-detection could be done via ide-probe.c:do_probe() but - * in practice that would be much slower, which is painful when - * running in the simulator. Note that passing zeroes in DRIVE_INFO - * is sufficient (the IDE driver will autodetect the drive geometry). - */ -char drive_info[4*16]; - void __init dig_setup (char **cmdline_p) { diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 5856510210fa..b3355a9ca2c3 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -515,6 +515,7 @@ sys32_signal (int sig, unsigned int handler) sigact_set_handler(&new_sa, handler, 0); new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; + sigemptyset(&new_sa.sa.sa_mask); ret = do_sigaction(sig, &new_sa, &old_sa); diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 3945d378bd7e..70dba1f0e2ee 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -52,9 +52,9 @@ #include <linux/compat.h> #include <linux/vfs.h> #include <linux/mman.h> +#include <linux/mutex.h> #include <asm/intrinsics.h> -#include <asm/semaphore.h> #include <asm/types.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -86,7 +86,7 @@ * while doing so. */ /* XXX make per-mm: */ -static DECLARE_MUTEX(ia32_mmap_sem); +static DEFINE_MUTEX(ia32_mmap_mutex); asmlinkage long sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, @@ -895,11 +895,11 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot prot = get_prot32(prot); #if PAGE_SHIFT > IA32_PAGE_SHIFT - down(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); { addr = emulate_mmap(file, addr, len, prot, flags, offset); } - up(&ia32_mmap_sem); + mutex_unlock(&ia32_mmap_mutex); #else down_write(¤t->mm->mmap_sem); { @@ -1000,11 +1000,9 @@ sys32_munmap (unsigned int start, unsigned int len) if (start >= end) return 0; - down(&ia32_mmap_sem); - { - ret = sys_munmap(start, end - start); - } - up(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); + ret = sys_munmap(start, end - start); + mutex_unlock(&ia32_mmap_mutex); #endif return ret; } @@ -1056,7 +1054,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) if (retval < 0) return retval; - down(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); { if (offset_in_page(start)) { /* start address is 4KB aligned but not page aligned. */ @@ -1080,7 +1078,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) retval = sys_mprotect(start, end - start, prot); } out: - up(&ia32_mmap_sem); + mutex_unlock(&ia32_mmap_mutex); return retval; #endif } @@ -1124,11 +1122,9 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, old_len = PAGE_ALIGN(old_end) - addr; new_len = PAGE_ALIGN(new_end) - addr; - down(&ia32_mmap_sem); - { - ret = sys_mremap(addr, old_len, new_len, flags, new_addr); - } - up(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); + mutex_unlock(&ia32_mmap_mutex); if ((ret >= 0) && (old_len < new_len)) { /* mremap expanded successfully */ diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 307514f7a282..09a0dbc17fb6 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -13,6 +13,11 @@ obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o + +ifneq ($(CONFIG_ACPI_PROCESSOR),) +obj-y += acpi-processor.o +endif + obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c index 13a5b3b49bf8..4a5574ff007b 100644 --- a/arch/ia64/kernel/acpi-ext.c +++ b/arch/ia64/kernel/acpi-ext.c @@ -33,33 +33,33 @@ acpi_vendor_resource_match(struct acpi_resource *resource, void *context) struct acpi_vendor_info *info = (struct acpi_vendor_info *)context; struct acpi_resource_vendor *vendor; struct acpi_vendor_descriptor *descriptor; - u32 length; + u32 byte_length; - if (resource->id != ACPI_RSTYPE_VENDOR) + if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) return AE_OK; vendor = (struct acpi_resource_vendor *)&resource->data; - descriptor = (struct acpi_vendor_descriptor *)vendor->reserved; - if (vendor->length <= sizeof(*info->descriptor) || + descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data; + if (vendor->byte_length <= sizeof(*info->descriptor) || descriptor->guid_id != info->descriptor->guid_id || efi_guidcmp(descriptor->guid, info->descriptor->guid)) return AE_OK; - length = vendor->length - sizeof(struct acpi_vendor_descriptor); - info->data = acpi_os_allocate(length); + byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor); + info->data = acpi_os_allocate(byte_length); if (!info->data) return AE_NO_MEMORY; memcpy(info->data, - vendor->reserved + sizeof(struct acpi_vendor_descriptor), - length); - info->length = length; + vendor->byte_data + sizeof(struct acpi_vendor_descriptor), + byte_length); + info->length = byte_length; return AE_CTRL_TERMINATE; } acpi_status acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id, - u8 ** data, u32 * length) + u8 ** data, u32 * byte_length) { struct acpi_vendor_info info; @@ -72,7 +72,7 @@ acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id, return AE_NOT_FOUND; *data = info.data; - *length = info.length; + *byte_length = info.length; return AE_OK; } diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c new file mode 100644 index 000000000000..e683630c8ce2 --- /dev/null +++ b/arch/ia64/kernel/acpi-processor.c @@ -0,0 +1,67 @@ +/* + * arch/ia64/kernel/cpufreq/processor.c + * + * Copyright (C) 2005 Intel Corporation + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * - Added _PDC for platforms with Intel CPUs + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> + +#include <acpi/processor.h> +#include <asm/acpi.h> + +static void init_intel_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + return; +} + +/* Initialize _PDC data based on the CPU vendor */ +void arch_acpi_processor_init_pdc(struct acpi_processor *pr) +{ + pr->pdc = NULL; + init_intel_pdc(pr); + return; +} + +EXPORT_SYMBOL(arch_acpi_processor_init_pdc); diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 9ad94ddf6687..d2702c419cf8 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -567,16 +567,16 @@ void __init acpi_numa_arch_fixup(void) * success: return IRQ number (>=0) * failure: return < 0 */ -int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) +int acpi_register_gsi(u32 gsi, int triggering, int polarity) { if (has_8259 && gsi < 16) return isa_irq_to_vector(gsi); return iosapic_register_intr(gsi, - (active_high_low == + (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - (edge_level == + (triggering == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); } diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile index f748d34c02f0..4838f2a57c7a 100644 --- a/arch/ia64/kernel/cpufreq/Makefile +++ b/arch/ia64/kernel/cpufreq/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o + diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c index da4d5cf80a48..5a1bf815282d 100644 --- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c +++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c @@ -269,48 +269,6 @@ acpi_cpufreq_verify ( } -/* - * processor_init_pdc - let BIOS know about the SMP capabilities - * of this driver - * @perf: processor-specific acpi_io_data struct - * @cpu: CPU being initialized - * - * To avoid issues with legacy OSes, some BIOSes require to be informed of - * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC - * accordingly. Actual call to _PDC is done in driver/acpi/processor.c - */ -static void -processor_init_pdc ( - struct acpi_processor_performance *perf, - unsigned int cpu, - struct acpi_object_list *obj_list - ) -{ - union acpi_object *obj; - u32 *buf; - - dprintk("processor_init_pdc\n"); - - perf->pdc = NULL; - /* Initialize pdc. It will be used later. */ - if (!obj_list) - return; - - if (!(obj_list->count && obj_list->pointer)) - return; - - obj = obj_list->pointer; - if ((obj->buffer.length == 12) && obj->buffer.pointer) { - buf = (u32 *)obj->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - perf->pdc = obj_list; - } - return; -} - - static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) @@ -320,14 +278,7 @@ acpi_cpufreq_cpu_init ( struct cpufreq_acpi_io *data; unsigned int result = 0; - union acpi_object arg0 = {ACPI_TYPE_BUFFER}; - u32 arg0_buf[3]; - struct acpi_object_list arg_list = {1, &arg0}; - dprintk("acpi_cpufreq_cpu_init\n"); - /* setup arg_list for _PDC settings */ - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) @@ -337,9 +288,7 @@ acpi_cpufreq_cpu_init ( acpi_io_data[cpu] = data; - processor_init_pdc(&data->acpi_data, cpu, &arg_list); result = acpi_processor_register_performance(&data->acpi_data, cpu); - data->acpi_data.pdc = NULL; if (result) goto err_free; diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index c485a3b32ba8..9990320b6f9a 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -410,24 +410,16 @@ efi_init (void) efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; - char *cp, *end, vendor[100] = "unknown"; + char *cp, vendor[100] = "unknown"; extern char saved_command_line[]; int i; /* it's too early to be able to use the standard kernel command line support... */ for (cp = saved_command_line; *cp; ) { if (memcmp(cp, "mem=", 4) == 0) { - cp += 4; - mem_limit = memparse(cp, &end); - if (end != cp) - break; - cp = end; + mem_limit = memparse(cp + 4, &cp); } else if (memcmp(cp, "max_addr=", 9) == 0) { - cp += 9; - max_addr = GRANULEROUNDDOWN(memparse(cp, &end)); - if (end != cp) - break; - cp = end; + max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); } else { while (*cp != ' ' && *cp) ++cp; @@ -458,7 +450,7 @@ efi_init (void) /* Show what we know for posterity */ c16 = __va(efi.systab->fw_vendor); if (c16) { - for (i = 0;i < (int) sizeof(vendor) && *c16; ++i) + for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i) vendor[i] = *c16++; vendor[i] = '\0'; } diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 7a6ffd613789..27b222c277e4 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1601,5 +1601,21 @@ sys_call_table: data8 sys_inotify_add_watch data8 sys_inotify_rm_watch data8 sys_migrate_pages // 1280 + data8 sys_openat + data8 sys_mkdirat + data8 sys_mknodat + data8 sys_fchownat + data8 sys_futimesat // 1285 + data8 sys_newfstatat + data8 sys_unlinkat + data8 sys_renameat + data8 sys_linkat + data8 sys_symlinkat // 1290 + data8 sys_readlinkat + data8 sys_fchmodat + data8 sys_faccessat + data8 sys_ni_syscall // reserved for pselect + data8 sys_ni_syscall // 1295 reserved for ppoll + data8 sys_unshare .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index ce423910ca97..ac6055c83115 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -878,31 +878,8 @@ fsyscall_table: data8 0 // timer_delete data8 0 // clock_settime data8 fsys_clock_gettime // clock_gettime - data8 0 // clock_getres // 1255 - data8 0 // clock_nanosleep - data8 0 // fstatfs64 - data8 0 // statfs64 - data8 0 - data8 0 // 1260 - data8 0 - data8 0 // mq_open - data8 0 // mq_unlink - data8 0 // mq_timedsend - data8 0 // mq_timedreceive // 1265 - data8 0 // mq_notify - data8 0 // mq_getsetattr - data8 0 // kexec_load - data8 0 - data8 0 // 1270 - data8 0 - data8 0 - data8 0 - data8 0 - data8 0 // 1275 - data8 0 - data8 0 - data8 0 - data8 0 - data8 0 // 1280 + #define __NR_syscall_last 1255 + + .space 8*(NR_syscalls + 1024 - __NR_syscall_last), 0 .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index fbc7ea35dd57..f1778a84ea61 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -352,6 +352,7 @@ start_ap: mov ar.rsc=0 // place RSE in enforced lazy mode ;; loadrs // clear the dirty partition + mov IA64_KR(PER_CPU_DATA)=r0 // clear physical per-CPU base ;; mov ar.bspstore=r2 // establish the new RSE stack ;; diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 403a80a58c13..60a464bfd9e2 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -512,7 +512,7 @@ ia64_state_save: st8 [temp1]=r12 // os_status, default is cold boot mov r6=IA64_MCA_SAME_CONTEXT ;; - st8 [temp1]=r6 // context, default is same context + st8 [temp2]=r6 // context, default is same context // Save the pt_regs data that is not in minstate. The previous code // left regs at sos. diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 3492e3211a44..8fd93afa75a7 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -437,6 +437,9 @@ recover_from_read_error(slidx_table_t *slidx, * the process not have any locks of kernel. */ + /* Is minstate valid? */ + if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate)) + return 0; psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr); /* diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 2ea4b39efffa..9c5194b385da 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -40,6 +40,7 @@ #include <linux/bitops.h> #include <linux/capability.h> #include <linux/rcupdate.h> +#include <linux/completion.h> #include <asm/errno.h> #include <asm/intrinsics.h> @@ -286,7 +287,7 @@ typedef struct pfm_context { unsigned long ctx_ovfl_regs[4]; /* which registers overflowed (notification) */ - struct semaphore ctx_restart_sem; /* use for blocking notification mode */ + struct completion ctx_restart_done; /* use for blocking notification mode */ unsigned long ctx_used_pmds[4]; /* bitmask of PMD used */ unsigned long ctx_all_pmds[4]; /* bitmask of all accessible PMDs */ @@ -1991,7 +1992,7 @@ pfm_close(struct inode *inode, struct file *filp) /* * force task to wake up from MASKED state */ - up(&ctx->ctx_restart_sem); + complete(&ctx->ctx_restart_done); DPRINT(("waking up ctx_state=%d\n", state)); @@ -2706,7 +2707,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg /* * init restart semaphore to locked */ - sema_init(&ctx->ctx_restart_sem, 0); + init_completion(&ctx->ctx_restart_done); /* * activation is used in SMP only @@ -3687,7 +3688,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) */ if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) { DPRINT(("unblocking [%d] \n", task->pid)); - up(&ctx->ctx_restart_sem); + complete(&ctx->ctx_restart_done); } else { DPRINT(("[%d] armed exit trap\n", task->pid)); @@ -5089,7 +5090,7 @@ pfm_handle_work(void) * may go through without blocking on SMP systems * if restart has been received already by the time we call down() */ - ret = down_interruptible(&ctx->ctx_restart_sem); + ret = wait_for_completion_interruptible(&ctx->ctx_restart_done); DPRINT(("after block sleeping ret=%d\n", ret)); diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index acc0f132f86c..056f7a6eedc7 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -14,6 +14,7 @@ #include <linux/spinlock.h> #include <linux/string.h> +#include <asm/delay.h> #include <asm/page.h> #include <asm/sal.h> #include <asm/pal.h> @@ -214,6 +215,78 @@ chk_nointroute_opt(void) static void __init sal_desc_ap_wakeup(void *p) { } #endif +/* + * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading + * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as + * "in-service" and masks other interrupts of equal or lower priority. + * + * HP internal defect reports: F1859, F2775, F3031. + */ +static int sal_cache_flush_drops_interrupts; + +static void __init +check_sal_cache_flush (void) +{ + unsigned long flags, itv; + int cpu; + u64 vector; + + cpu = get_cpu(); + local_irq_save(flags); + + /* + * Schedule a timer interrupt, wait until it's reported, and see if + * SAL_CACHE_FLUSH drops it. + */ + itv = ia64_get_itv(); + BUG_ON((itv & (1 << 16)) == 0); + + ia64_set_itv(IA64_TIMER_VECTOR); + ia64_set_itm(ia64_get_itc() + 1000); + + while (!ia64_get_irr(IA64_TIMER_VECTOR)) + cpu_relax(); + + ia64_sal_cache_flush(3); + + if (ia64_get_irr(IA64_TIMER_VECTOR)) { + vector = ia64_get_ivr(); + ia64_eoi(); + WARN_ON(vector != IA64_TIMER_VECTOR); + } else { + sal_cache_flush_drops_interrupts = 1; + printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; " + "PAL_CACHE_FLUSH will be used instead\n"); + ia64_eoi(); + } + + ia64_set_itv(itv); + local_irq_restore(flags); + put_cpu(); +} + +s64 +ia64_sal_cache_flush (u64 cache_type) +{ + struct ia64_sal_retval isrv; + + if (sal_cache_flush_drops_interrupts) { + unsigned long flags; + u64 progress; + s64 rc; + + progress = 0; + local_irq_save(flags); + rc = ia64_pal_cache_flush(cache_type, + PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL); + local_irq_restore(flags); + return rc; + } + + SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); + return isrv.status; +} + void __init ia64_sal_init (struct ia64_sal_systab *systab) { @@ -262,6 +335,8 @@ ia64_sal_init (struct ia64_sal_systab *systab) } p += SAL_DESC_SIZE(*p); } + + check_sal_cache_flush(); } int diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c0766575a3a2..35f7835294a3 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -71,6 +71,8 @@ unsigned long __per_cpu_offset[NR_CPUS]; EXPORT_SYMBOL(__per_cpu_offset); #endif +extern void ia64_setup_printk_clock(void); + DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); DEFINE_PER_CPU(unsigned long, local_per_cpu_offset); DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8); @@ -445,6 +447,8 @@ setup_arch (char **cmdline_p) /* process SAL system table: */ ia64_sal_init(efi.sal_systab); + ia64_setup_printk_clock(); + #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 028a2b95936c..a094ec49ccfa 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -278,3 +278,30 @@ udelay (unsigned long usecs) } } EXPORT_SYMBOL(udelay); + +static unsigned long long ia64_itc_printk_clock(void) +{ + if (ia64_get_kr(IA64_KR_PER_CPU_DATA)) + return sched_clock(); + return 0; +} + +static unsigned long long ia64_default_printk_clock(void) +{ + return (unsigned long long)(jiffies_64 - INITIAL_JIFFIES) * + (1000000000/HZ); +} + +unsigned long long (*ia64_printk_clock)(void) = &ia64_default_printk_clock; + +unsigned long long printk_clock(void) +{ + return ia64_printk_clock(); +} + +void __init +ia64_setup_printk_clock(void) +{ + if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) + ia64_printk_clock = ia64_itc_printk_clock; +} diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 706b7734e191..6e5eea19fa67 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -71,31 +71,33 @@ static int __init topology_init(void) int i, err = 0; #ifdef CONFIG_NUMA - sysfs_nodes = kmalloc(sizeof(struct node) * MAX_NUMNODES, GFP_KERNEL); + sysfs_nodes = kzalloc(sizeof(struct node) * MAX_NUMNODES, GFP_KERNEL); if (!sysfs_nodes) { err = -ENOMEM; goto out; } - memset(sysfs_nodes, 0, sizeof(struct node) * MAX_NUMNODES); - /* MCD - Do we want to register all ONLINE nodes, or all POSSIBLE nodes? */ - for_each_online_node(i) + /* + * MCD - Do we want to register all ONLINE nodes, or all POSSIBLE nodes? + */ + for_each_online_node(i) { if ((err = register_node(&sysfs_nodes[i], i, 0))) goto out; + } #endif - sysfs_cpus = kmalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL); + sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL); if (!sysfs_cpus) { err = -ENOMEM; goto out; } - memset(sysfs_cpus, 0, sizeof(struct ia64_cpu) * NR_CPUS); - for_each_present_cpu(i) + for_each_present_cpu(i) { if((err = arch_register_cpu(i))) goto out; + } out: return err; } -__initcall(topology_init); +subsys_initcall(topology_init); diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 43b45b65ee5a..f9e0ae936d1a 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1283,8 +1283,9 @@ within_logging_rate_limit (void) if (jiffies - last_time > 5*HZ) count = 0; - if (++count < 5) { + if (count < 5) { last_time = jiffies; + count++; return 1; } return 0; diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index b631cf86ed44..fcd2bad0286f 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -210,6 +210,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg) dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end); + touch_softlockup_watchdog(); memset((char *)start, 0, length); node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index d27ecdcb6fca..0b30ca006286 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -193,12 +193,12 @@ add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr) goto free_resource; } - min = addr->min_address_range; + min = addr->minimum; max = min + addr->address_length - 1; - if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) + if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION) sparse = 1; - space_nr = new_space(addr->address_translation_offset, sparse); + space_nr = new_space(addr->translation_offset, sparse); if (space_nr == ~0) goto free_name; @@ -285,7 +285,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) if (addr.resource_type == ACPI_MEMORY_RANGE) { flags = IORESOURCE_MEM; root = &iomem_resource; - offset = addr.address_translation_offset; + offset = addr.translation_offset; } else if (addr.resource_type == ACPI_IO_RANGE) { flags = IORESOURCE_IO; root = &ioport_resource; @@ -298,7 +298,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) window = &info->controller->window[info->controller->windows++]; window->resource.name = info->name; window->resource.flags = flags; - window->resource.start = addr.min_address_range + offset; + window->resource.start = addr.minimum + offset; window->resource.end = window->resource.start + addr.address_length - 1; window->resource.child = NULL; window->offset = offset; diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile index a269f6d84c29..79a7df02e812 100644 --- a/arch/ia64/sn/Makefile +++ b/arch/ia64/sn/Makefile @@ -9,6 +9,4 @@ # Makefile for the sn ia64 subplatform # -CPPFLAGS += -I$(srctree)/arch/ia64/sn/include - obj-y += kernel/ pci/ diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 7c88e9a58516..8182583c762c 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -51,6 +51,15 @@ struct sn_flush_device_kernel { struct sn_flush_device_common *common; }; +/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included + * for older official PROMs to function on the new kernel base. This struct + * will be removed when the next official PROM release occurs. */ + +struct sn_flush_device_war { + struct sn_flush_device_common common; + u32 filler; /* older PROMs expect the default size of a spinlock_t */ +}; + /* * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel. */ diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 4351c4ff9845..3e9b4eea7418 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -7,6 +7,8 @@ # Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. # +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ huberror.o io_init.o iomv.o klconflib.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index dd73c0cb754b..1f11db470d90 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/config.h> @@ -186,18 +186,13 @@ retry_bteop: /* Initialize the notification to a known value. */ *bte->most_rcnt_na = BTE_WORD_BUSY; - notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)); + notif_phys_addr = (u64)bte->most_rcnt_na; - if (is_shub2()) { - src = SH2_TIO_PHYS_TO_DMA(src); - dest = SH2_TIO_PHYS_TO_DMA(dest); - notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr); - } /* Set the source and destination registers */ - BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); - BTE_SRC_STORE(bte, TO_PHYS(src)); - BTE_PRINTKV(("IBDA = 0x%lx)\n", (TO_PHYS(dest)))); - BTE_DEST_STORE(bte, TO_PHYS(dest)); + BTE_PRINTKV(("IBSA = 0x%lx)\n", src)); + BTE_SRC_STORE(bte, src); + BTE_PRINTKV(("IBDA = 0x%lx)\n", dest)); + BTE_DEST_STORE(bte, dest); /* Set the notification register */ BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 233d55115d33..3437c2390429 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -10,6 +10,7 @@ #include <linux/nodemask.h> #include <asm/sn/types.h> #include <asm/sn/addrs.h> +#include <asm/sn/sn_feature_sets.h> #include <asm/sn/geo.h> #include <asm/sn/io.h> #include <asm/sn/pcibr_provider.h> @@ -165,11 +166,49 @@ sn_pcidev_info_get(struct pci_dev *dev) return NULL; } +/* Older PROM flush WAR + * + * 01/16/06 -- This war will be in place until a new official PROM is released. + * Additionally note that the struct sn_flush_device_war also has to be + * removed from arch/ia64/sn/include/xtalk/hubdev.h + */ +static u8 war_implemented = 0; + +static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, + struct sn_flush_device_common *common) +{ + struct sn_flush_device_war *war_list; + struct sn_flush_device_war *dev_entry; + struct ia64_sal_retval isrv = {0,0,0,0}; + + if (!war_implemented) { + printk(KERN_WARNING "PROM version < 4.50 -- implementing old " + "PROM flush WAR\n"); + war_implemented = 1; + } + + war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); + if (!war_list) + BUG(); + + SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, + nasid, widget, __pa(war_list), 0, 0, 0 ,0); + if (isrv.status) + panic("sn_device_fixup_war failed: %s\n", + ia64_sal_strerror(isrv.status)); + + dev_entry = war_list + device; + memcpy(common,dev_entry, sizeof(*common)); + kfree(war_list); + + return isrv.status; +} + /* - * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for + * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for * each node in the system. */ -static void sn_fixup_ionodes(void) +static void __init sn_fixup_ionodes(void) { struct sn_flush_device_kernel *sn_flush_device_kernel; struct sn_flush_device_kernel *dev_entry; @@ -242,12 +281,21 @@ static void sn_fixup_ionodes(void) memset(dev_entry->common, 0x0, sizeof(struct sn_flush_device_common)); - status = sal_get_device_dmaflush_list(nasid, - widget, - device, + if (sn_prom_feature_available( + PRF_DEVICE_FLUSH_LIST)) + status = sal_get_device_dmaflush_list( + nasid, + widget, + device, (u64)(dev_entry->common)); - if (status) - BUG(); + else + status = sn_device_fixup_war(nasid, + widget, + device, + dev_entry->common); + if (status != SALRET_OK) + panic("SAL call failed: %s\n", + ia64_sal_strerror(status)); spin_lock_init(&dev_entry->sfdl_flush_lock); } @@ -419,6 +467,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); } + + /* + * MSI currently not supported on altix. Remove this when + * the MSI abstraction patches are integrated into the kernel + * (sometime after 2.6.16 releases) + */ + dev->no_msi = 1; } /* @@ -562,15 +617,15 @@ void sn_bus_store_sysdata(struct pci_dev *dev) void sn_bus_free_sysdata(void) { struct sysdata_el *element; - struct list_head *list; + struct list_head *list, *safe; -sn_sysdata_free_start: - list_for_each(list, &sn_sysdata_list) { + list_for_each_safe(list, safe, &sn_sysdata_list) { element = list_entry(list, struct sysdata_el, entry); list_del(&element->entry); + list_del(&(((struct pcidev_info *) + (element->sysdata))->pdi_list)); kfree(element->sysdata); kfree(element); - goto sn_sysdata_free_start; } return; } diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index ec37084bdc17..c373113d073a 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,11 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/irq.h> #include <linux/spinlock.h> +#include <linux/init.h> #include <asm/sn/addrs.h> #include <asm/sn/arch.h> #include <asm/sn/intr.h> @@ -76,17 +77,15 @@ static void sn_enable_irq(unsigned int irq) static void sn_ack_irq(unsigned int irq) { - u64 event_occurred, mask = 0; + u64 event_occurred, mask; irq = irq & 0xff; - event_occurred = - HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); + event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); mask = event_occurred & SH_ALL_INT_MASK; - HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), - mask); + HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); - move_irq(irq); + move_native_irq(irq); } static void sn_end_irq(unsigned int irq) @@ -219,9 +218,8 @@ static void register_intr_pda(struct sn_irq_info *sn_irq_info) pdacpu(cpu)->sn_last_irq = irq; } - if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { + if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq; - } } static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) @@ -289,7 +287,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); spin_unlock(&sn_irq_info_lock); - (void)register_intr_pda(sn_irq_info); + register_intr_pda(sn_irq_info); } void sn_irq_unfixup(struct pci_dev *pci_dev) @@ -301,7 +299,9 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) return; sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info; - if (!sn_irq_info || !sn_irq_info->irq_irq) { + if (!sn_irq_info) + return; + if (!sn_irq_info->irq_irq) { kfree(sn_irq_info); return; } @@ -419,7 +419,7 @@ void sn_lb_int_war_check(void) rcu_read_unlock(); } -void sn_irq_lh_init(void) +void __init sn_irq_lh_init(void) { int i; @@ -434,5 +434,4 @@ void sn_irq_lh_init(void) INIT_LIST_HEAD(sn_irq_lh[i]); } - } diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c index 0f11a3299cd2..87682b48ef83 100644 --- a/arch/ia64/sn/kernel/klconflib.c +++ b/arch/ia64/sn/kernel/klconflib.c @@ -78,31 +78,30 @@ format_module_id(char *buffer, moduleid_t m, int fmt) position = MODULE_GET_BPOS(m); if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { - /* Brief module number format, eg. 002c15 */ + /* Brief module number format, eg. 002c15 */ - /* Decompress the rack number */ - *buffer++ = '0' + RACK_GET_CLASS(rack); - *buffer++ = '0' + RACK_GET_GROUP(rack); - *buffer++ = '0' + RACK_GET_NUM(rack); + /* Decompress the rack number */ + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); - /* Add the brick type */ - *buffer++ = brickchar; + /* Add the brick type */ + *buffer++ = brickchar; } else if (fmt == MODULE_FORMAT_LONG) { - /* Fuller hwgraph format, eg. rack/002/bay/15 */ + /* Fuller hwgraph format, eg. rack/002/bay/15 */ - strcpy(buffer, "rack" "/"); buffer += strlen(buffer); + strcpy(buffer, "rack" "/"); buffer += strlen(buffer); - *buffer++ = '0' + RACK_GET_CLASS(rack); - *buffer++ = '0' + RACK_GET_GROUP(rack); - *buffer++ = '0' + RACK_GET_NUM(rack); + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); - strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); + strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); } /* Add the bay position, using at least two digits */ if (position < 10) - *buffer++ = '0'; + *buffer++ = '0'; sprintf(buffer, "%d", position); - } diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 6546db6abdba..3db62f24596c 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c @@ -3,13 +3,14 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/timer.h> #include <linux/vmalloc.h> +#include <linux/mutex.h> #include <asm/mca.h> #include <asm/sal.h> #include <asm/sn/sn_sal.h> @@ -27,7 +28,7 @@ void sn_init_cpei_timer(void); /* Printing oemdata from mca uses data that is not passed through SAL, it is * global. Only one user at a time. */ -static DECLARE_MUTEX(sn_oemdata_mutex); +static DEFINE_MUTEX(sn_oemdata_mutex); static u8 **sn_oemdata; static u64 *sn_oemdata_size, sn_oemdata_bufsize; @@ -89,7 +90,7 @@ static int sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, u64 * oemdata_size) { - down(&sn_oemdata_mutex); + mutex_lock(&sn_oemdata_mutex); sn_oemdata = oemdata; sn_oemdata_size = oemdata_size; sn_oemdata_bufsize = 0; @@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, *sn_oemdata_size = 0; ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header); } - up(&sn_oemdata_mutex); + mutex_unlock(&sn_oemdata_mutex); return 0; } @@ -136,7 +137,8 @@ int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdat static int __init sn_salinfo_init(void) { - salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; + if (ia64_platform_is("sn2")) + salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; return 0; } diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index e510dce9971f..48645ac120fc 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -67,6 +67,7 @@ extern unsigned long last_time_offset; extern void (*ia64_mark_idle) (int); extern void snidle(int); extern unsigned char acpi_kbd_controller_present; +extern unsigned long long (*ia64_printk_clock)(void); unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); @@ -125,20 +126,6 @@ struct screen_info sn_screen_info = { }; /* - * This is here so we can use the CMOS detection in ide-probe.c to - * determine what drives are present. In theory, we don't need this - * as the auto-detection could be done via ide-probe.c:do_probe() but - * in practice that would be much slower, which is painful when - * running in the simulator. Note that passing zeroes in DRIVE_INFO - * is sufficient (the IDE driver will autodetect the drive geometry). - */ -#ifdef CONFIG_IA64_GENERIC -extern char drive_info[4 * 16]; -#else -char drive_info[4 * 16]; -#endif - -/* * This routine can only be used during init, since * smp_boot_data is an init data structure. * We have to use smp_boot_data.cpu_phys_id to find @@ -209,7 +196,7 @@ void __init early_sn_setup(void) } extern int platform_intr_list[]; -static int __initdata shub_1_1_found = 0; +static int __initdata shub_1_1_found; /* * sn_check_for_wars @@ -372,6 +359,16 @@ sn_scan_pcdp(void) } } +static unsigned long sn2_rtc_initial; + +static unsigned long long ia64_sn2_printk_clock(void) +{ + unsigned long rtc_now = rtc_time(); + + return (rtc_now - sn2_rtc_initial) * + (1000000000 / sn_rtc_cycles_per_second); +} + /** * sn_setup - SN platform setup routine * @cmdline_p: kernel command line @@ -386,6 +383,7 @@ void __init sn_setup(char **cmdline_p) u32 version = sn_sal_rev(); extern void sn_cpu_init(void); + sn2_rtc_initial = rtc_time(); ia64_sn_plat_set_error_handling_features(); // obsolete ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV); ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES); @@ -437,19 +435,6 @@ void __init sn_setup(char **cmdline_p) */ build_cnode_tables(); - /* - * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard - * support here so we don't have to listen to failed keyboard probe - * messages. - */ - if (version <= 0x0209 && acpi_kbd_controller_present) { - printk(KERN_INFO "Disabling legacy keyboard support as prom " - "is too old and doesn't provide FADT\n"); - acpi_kbd_controller_present = 0; - } - - printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); - status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift); @@ -463,6 +448,21 @@ void __init sn_setup(char **cmdline_p) platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR; + ia64_printk_clock = ia64_sn2_printk_clock; + + /* + * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard + * support here so we don't have to listen to failed keyboard probe + * messages. + */ + if (version <= 0x0209 && acpi_kbd_controller_present) { + printk(KERN_INFO "Disabling legacy keyboard support as prom " + "is too old and doesn't provide FADT\n"); + acpi_kbd_controller_present = 0; + } + + printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); + /* * we set the default root device to /dev/hda * to make simulation easy @@ -578,13 +578,17 @@ void __init sn_cpu_init(void) sn_prom_type = 2; else sn_prom_type = 1; - printk("Running on medusa with %s PROM\n", (sn_prom_type == 1) ? "real" : "fake"); + printk(KERN_INFO "Running on medusa with %s PROM\n", + (sn_prom_type == 1) ? "real" : "fake"); } memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, - &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, - &sn_coherency_id, &sn_region_size)) + if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, + &sn_hub_info->nasid_bitmask, + &sn_hub_info->nasid_shift, + &sn_system_size, &sn_sharing_domain_size, + &sn_partition_id, &sn_coherency_id, + &sn_region_size)) BUG(); sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; @@ -716,7 +720,8 @@ void __init build_cnode_tables(void) for_each_online_node(node) { kl_config_hdr_t *klgraph_header; nasid = cnodeid_to_nasid(node); - if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL) + klgraph_header = ia64_sn_get_klconfig_addr(nasid); + if (klgraph_header == NULL) BUG(); brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info); while (brd) { @@ -734,7 +739,7 @@ nasid_slice_to_cpuid(int nasid, int slice) { long cpu; - for (cpu=0; cpu < NR_CPUS; cpu++) + for (cpu = 0; cpu < NR_CPUS; cpu++) if (cpuid_to_nasid(cpu) == nasid && cpuid_to_slice(cpu) == slice) return cpu; diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 170bde4549da..99e177693234 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile @@ -9,5 +9,7 @@ # sn2 specific kernel files # +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 471bbaa65d1b..f153a4c35c70 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved. */ #include <linux/init.h> @@ -46,104 +46,28 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); -void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, - volatile unsigned long *, unsigned long data1); +void sn2_ptc_deadlock_recovery(short *, short, short, int, volatile unsigned long *, unsigned long, + volatile unsigned long *, unsigned long); -#ifdef DEBUG_PTC /* - * ptctest: - * - * xyz - 3 digit hex number: - * x - Force PTC purges to use shub: - * 0 - no force - * 1 - force - * y - interupt enable - * 0 - disable interrupts - * 1 - leave interuupts enabled - * z - type of lock: - * 0 - global lock - * 1 - node local lock - * 2 - no lock - * - * Note: on shub1, only ptctest == 0 is supported. Don't try other values! + * Note: some is the following is captured here to make degugging easier + * (the macros make more sense if you see the debug patch - not posted) */ - -static unsigned int sn2_ptctest = 0; - -static int __init ptc_test(char *str) -{ - get_option(&str, &sn2_ptctest); - return 1; -} -__setup("ptctest=", ptc_test); - -static inline int ptc_lock(unsigned long *flagp) -{ - unsigned long opt = sn2_ptctest & 255; - - switch (opt) { - case 0x00: - spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); - break; - case 0x01: - spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp); - break; - case 0x02: - local_irq_save(*flagp); - break; - case 0x10: - spin_lock(&sn2_global_ptc_lock); - break; - case 0x11: - spin_lock(&sn_nodepda->ptc_lock); - break; - case 0x12: - break; - default: - BUG(); - } - return opt; -} - -static inline void ptc_unlock(unsigned long flags, int opt) -{ - switch (opt) { - case 0x00: - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); - break; - case 0x01: - spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags); - break; - case 0x02: - local_irq_restore(flags); - break; - case 0x10: - spin_unlock(&sn2_global_ptc_lock); - break; - case 0x11: - spin_unlock(&sn_nodepda->ptc_lock); - break; - case 0x12: - break; - default: - BUG(); - } -} -#else - #define sn2_ptctest 0 +#define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0) +#define max_active_pio(sh1) ((sh1) ? 32 : 7) +#define reset_max_active_on_deadlock() 1 +#define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock) -static inline int ptc_lock(unsigned long *flagp) +static inline void ptc_lock(int sh1, unsigned long *flagp) { - spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); - return 0; + spin_lock_irqsave(PTC_LOCK(sh1), *flagp); } -static inline void ptc_unlock(unsigned long flags, int opt) +static inline void ptc_unlock(int sh1, unsigned long flags) { - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); + spin_unlock_irqrestore(PTC_LOCK(sh1), flags); } -#endif struct ptc_stats { unsigned long ptc_l; @@ -151,27 +75,30 @@ struct ptc_stats { unsigned long shub_ptc_flushes; unsigned long nodes_flushed; unsigned long deadlocks; + unsigned long deadlocks2; unsigned long lock_itc_clocks; unsigned long shub_itc_clocks; unsigned long shub_itc_clocks_max; + unsigned long shub_ptc_flushes_not_my_mm; }; static inline unsigned long wait_piowc(void) { - volatile unsigned long *piows, zeroval; - unsigned long ws; + volatile unsigned long *piows; + unsigned long zeroval, ws; piows = pda->pio_write_status_addr; zeroval = pda->pio_write_status_val; do { cpu_relax(); } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); - return ws; + return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; } void sn_tlb_migrate_finish(struct mm_struct *mm) { - if (mm == current->mm) + /* flush_tlb_mm is inefficient if more than 1 users of mm */ + if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1) flush_tlb_mm(mm); } @@ -201,12 +128,14 @@ void sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) { - int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; - int mymm = (mm == current->active_mm && current->mm); + int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid; + int mymm = (mm == current->active_mm && mm == current->mm); + int use_cpu_ptcga; volatile unsigned long *ptc0, *ptc1; - unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; + unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; + int active, max_active, deadlock; nodes_clear(nodes_flushed); i = 0; @@ -267,41 +196,56 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, mynasid = get_nasid(); + use_cpu_ptcga = local_node_uses_ptc_ga(shub1); + max_active = max_active_pio(shub1); itc = ia64_get_itc(); - opt = ptc_lock(&flags); + ptc_lock(shub1, &flags); itc2 = ia64_get_itc(); + __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; __get_cpu_var(ptcstats).shub_ptc_flushes++; __get_cpu_var(ptcstats).nodes_flushed += nix; + if (!mymm) + __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++; + if (use_cpu_ptcga && !mymm) { + old_rr = ia64_get_rr(start); + ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8)); + ia64_srlz_d(); + } + + wait_piowc(); do { if (shub1) data1 = start | (1UL << SH1_PTC_1_START_SHFT); else data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); - for (i = 0; i < nix; i++) { + deadlock = 0; + active = 0; + for (ibegin = 0, i = 0; i < nix; i++) { nasid = nasids[i]; - if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) { + if (use_cpu_ptcga && unlikely(nasid == mynasid)) { ia64_ptcga(start, nbits << 2); ia64_srlz_i(); } else { ptc0 = CHANGE_NASID(nasid, ptc0); if (ptc1) ptc1 = CHANGE_NASID(nasid, ptc1); - pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, - data1); - flushed = 1; + pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1); + active++; + } + if (active >= max_active || i == (nix - 1)) { + if ((deadlock = wait_piowc())) { + sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); + if (reset_max_active_on_deadlock()) + max_active = 1; + } + active = 0; + ibegin = i + 1; } } - if (flushed - && (wait_piowc() & - (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) { - sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1); - } - start += (1UL << nbits); - } while (start < end); itc2 = ia64_get_itc() - itc2; @@ -309,7 +253,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; - ptc_unlock(flags, opt); + if (old_rr) { + ia64_set_rr(start, old_rr); + ia64_srlz_d(); + } + + ptc_unlock(shub1, flags); preempt_enable(); } @@ -321,27 +270,30 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, * TLB flush transaction. The recovery sequence is somewhat tricky & is * coded in assembly language. */ -void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, +void sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, volatile unsigned long *ptc0, unsigned long data0, volatile unsigned long *ptc1, unsigned long data1) { - extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, + extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); short nasid, i; - unsigned long *piows, zeroval; + unsigned long *piows, zeroval, n; __get_cpu_var(ptcstats).deadlocks++; piows = (unsigned long *) pda->pio_write_status_addr; zeroval = pda->pio_write_status_val; - for (i=0; i < nix; i++) { + + for (i=ib; i <= ie; i++) { nasid = nasids[i]; - if (!(sn2_ptctest & 3) && nasid == mynasid) + if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid) continue; ptc0 = CHANGE_NASID(nasid, ptc0); if (ptc1) ptc1 = CHANGE_NASID(nasid, ptc1); - sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); + + n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); + __get_cpu_var(ptcstats).deadlocks2 += n; } } @@ -452,20 +404,22 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) cpu = *(loff_t *) data; if (!cpu) { - seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n"); + seq_printf(file, + "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); seq_printf(file, "# ptctest %d\n", sn2_ptctest); } if (cpu < NR_CPUS && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec); + 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, + stat->shub_ptc_flushes_not_my_mm, + stat->deadlocks2); } - return 0; } @@ -476,7 +430,7 @@ static struct seq_operations sn2_ptc_seq_ops = { .show = sn2_ptc_seq_show }; -int sn2_ptc_proc_open(struct inode *inode, struct file *file) +static int sn2_ptc_proc_open(struct inode *inode, struct file *file) { return seq_open(file, &sn2_ptc_seq_ops); } diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 19b54fbcd7ea..70db21f3df21 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved. * * SGI Altix topology and hardware performance monitoring API. * Mark Goodwin <markgw@sgi.com>. @@ -973,6 +973,9 @@ static int __devinit sn_hwperf_misc_register_init(void) { int e; + if (!ia64_platform_is("sn2")) + return 0; + sn_hwperf_init(); /* diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c index 3be52a34c80f..b7ea46645e12 100644 --- a/arch/ia64/sn/kernel/xp_main.c +++ b/arch/ia64/sn/kernel/xp_main.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/mutex.h> #include <asm/sn/intr.h> #include <asm/sn/sn_sal.h> #include <asm/sn/xp.h> @@ -136,13 +137,13 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, registration = &xpc_registrations[ch_number]; - if (down_interruptible(®istration->sema) != 0) { + if (mutex_lock_interruptible(®istration->mutex) != 0) { return xpcInterrupted; } /* if XPC_CHANNEL_REGISTERED(ch_number) */ if (registration->func != NULL) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return xpcAlreadyRegistered; } @@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, registration->key = key; registration->func = func; - up(®istration->sema); + mutex_unlock(®istration->mutex); xpc_interface.connect(ch_number); @@ -190,11 +191,11 @@ xpc_disconnect(int ch_number) * figured XPC's users will just turn around and call xpc_disconnect() * again anyways, so we might as well wait, if need be. */ - down(®istration->sema); + mutex_lock(®istration->mutex); /* if !XPC_CHANNEL_REGISTERED(ch_number) */ if (registration->func == NULL) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return; } @@ -208,7 +209,7 @@ xpc_disconnect(int ch_number) xpc_interface.disconnect(ch_number); - up(®istration->sema); + mutex_unlock(®istration->mutex); return; } @@ -250,9 +251,9 @@ xp_init(void) xp_nofault_PIOR_target = SH1_IPI_ACCESS; } - /* initialize the connection registration semaphores */ + /* initialize the connection registration mutex */ for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) { - sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */ + mutex_init(&xpc_registrations[ch_number].mutex); } return 0; diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 0c0a68902409..36e5437a0fb6 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -22,6 +22,8 @@ #include <linux/cache.h> #include <linux/interrupt.h> #include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/completion.h> #include <asm/sn/bte.h> #include <asm/sn/sn_sal.h> #include <asm/sn/xpc.h> @@ -56,8 +58,8 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid) atomic_set(&ch->n_to_notify, 0); spin_lock_init(&ch->lock); - sema_init(&ch->msg_to_pull_sema, 1); /* mutex */ - sema_init(&ch->wdisconnect_sema, 0); /* event wait */ + mutex_init(&ch->msg_to_pull_mutex); + init_completion(&ch->wdisconnect_wait); atomic_set(&ch->n_on_msg_allocate_wq, 0); init_waitqueue_head(&ch->msg_allocate_wq); @@ -445,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->local_msgqueue_base); if (ch->local_msgqueue == NULL) { continue; @@ -453,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) memset(ch->local_msgqueue, 0, nbytes); nbytes = nentries * sizeof(struct xpc_notify); - ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA)); + ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); if (ch->notify_queue == NULL) { kfree(ch->local_msgqueue_base); ch->local_msgqueue = NULL; @@ -500,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->remote_msgqueue_base); if (ch->remote_msgqueue == NULL) { continue; @@ -534,7 +536,6 @@ static enum xpc_retval xpc_allocate_msgqueues(struct xpc_channel *ch) { unsigned long irq_flags; - int i; enum xpc_retval ret; @@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch) return ret; } - for (i = 0; i < ch->local_nentries; i++) { - /* use a semaphore as an event wait queue */ - sema_init(&ch->notify_queue[i].sema, 0); - } - spin_lock_irqsave(&ch->lock, irq_flags); ch->flags |= XPC_C_SETUP; spin_unlock_irqrestore(&ch->lock, irq_flags); @@ -799,10 +795,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) } if (ch->flags & XPC_C_WDISCONNECT) { - spin_unlock_irqrestore(&ch->lock, *irq_flags); - up(&ch->wdisconnect_sema); - spin_lock_irqsave(&ch->lock, *irq_flags); - + /* we won't lose the CPU since we're holding ch->lock */ + complete(&ch->wdisconnect_wait); } else if (ch->delayed_IPI_flags) { if (part->act_state != XPC_P_DEACTIVATING) { /* time to take action on any delayed IPI flags */ @@ -1092,12 +1086,12 @@ xpc_connect_channel(struct xpc_channel *ch) struct xpc_registration *registration = &xpc_registrations[ch->number]; - if (down_trylock(®istration->sema) != 0) { + if (mutex_trylock(®istration->mutex) == 0) { return xpcRetry; } if (!XPC_CHANNEL_REGISTERED(ch->number)) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return xpcUnregistered; } @@ -1108,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch) if (ch->flags & XPC_C_DISCONNECTING) { spin_unlock_irqrestore(&ch->lock, irq_flags); - up(®istration->sema); + mutex_unlock(®istration->mutex); return ch->reason; } @@ -1140,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch) * channel lock be locked and will unlock and relock * the channel lock as needed. */ - up(®istration->sema); + mutex_unlock(®istration->mutex); XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); @@ -1155,7 +1149,7 @@ xpc_connect_channel(struct xpc_channel *ch) atomic_inc(&xpc_partitions[ch->partid].nchannels_active); } - up(®istration->sema); + mutex_unlock(®istration->mutex); /* initiate the connection */ @@ -2089,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) enum xpc_retval ret; - if (down_interruptible(&ch->msg_to_pull_sema) != 0) { + if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) { /* we were interrupted by a signal */ return NULL; } @@ -2125,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) XPC_DEACTIVATE_PARTITION(part, ret); - up(&ch->msg_to_pull_sema); + mutex_unlock(&ch->msg_to_pull_mutex); return NULL; } @@ -2134,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) ch->next_msg_to_pull += nmsgs; } - up(&ch->msg_to_pull_sema); + mutex_unlock(&ch->msg_to_pull_mutex); /* return the message we were looking for */ msg_offset = (get % ch->remote_nentries) * ch->msg_size; diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 8930586e0eb4..9cd460dfe27e 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -55,6 +55,7 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/reboot.h> +#include <linux/completion.h> #include <asm/sn/intr.h> #include <asm/sn/sn_sal.h> #include <asm/kdebug.h> @@ -177,10 +178,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq); static unsigned long xpc_hb_check_timeout; /* notification that the xpc_hb_checker thread has exited */ -static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited); +static DECLARE_COMPLETION(xpc_hb_checker_exited); /* notification that the xpc_discovery thread has exited */ -static DECLARE_MUTEX_LOCKED(xpc_discovery_exited); +static DECLARE_COMPLETION(xpc_discovery_exited); static struct timer_list xpc_hb_timer; @@ -321,7 +322,7 @@ xpc_hb_checker(void *ignore) /* mark this thread as having exited */ - up(&xpc_hb_checker_exited); + complete(&xpc_hb_checker_exited); return 0; } @@ -341,7 +342,7 @@ xpc_initiate_discovery(void *ignore) dev_dbg(xpc_part, "discovery thread is exiting\n"); /* mark this thread as having exited */ - up(&xpc_discovery_exited); + complete(&xpc_discovery_exited); return 0; } @@ -574,18 +575,21 @@ xpc_activate_partition(struct xpc_partition *part) spin_lock_irqsave(&part->act_lock, irq_flags); - pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); - DBUG_ON(part->act_state != XPC_P_INACTIVE); - if (pid > 0) { - part->act_state = XPC_P_ACTIVATION_REQ; - XPC_SET_REASON(part, xpcCloneKThread, __LINE__); - } else { - XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); - } + part->act_state = XPC_P_ACTIVATION_REQ; + XPC_SET_REASON(part, xpcCloneKThread, __LINE__); spin_unlock_irqrestore(&part->act_lock, irq_flags); + + pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); + + if (unlikely(pid <= 0)) { + spin_lock_irqsave(&part->act_lock, irq_flags); + part->act_state = XPC_P_INACTIVE; + XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); + spin_unlock_irqrestore(&part->act_lock, irq_flags); + } } @@ -893,7 +897,7 @@ xpc_disconnect_wait(int ch_number) continue; } - (void) down(&ch->wdisconnect_sema); + wait_for_completion(&ch->wdisconnect_wait); spin_lock_irqsave(&ch->lock, irq_flags); DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); @@ -946,10 +950,10 @@ xpc_do_exit(enum xpc_retval reason) free_irq(SGI_XPC_ACTIVATE, NULL); /* wait for the discovery thread to exit */ - down(&xpc_discovery_exited); + wait_for_completion(&xpc_discovery_exited); /* wait for the heartbeat checker thread to exit */ - down(&xpc_hb_checker_exited); + wait_for_completion(&xpc_hb_checker_exited); /* sleep for a 1/3 of a second or so */ @@ -1367,7 +1371,7 @@ xpc_init(void) dev_err(xpc_part, "failed while forking discovery thread\n"); /* mark this new thread as a non-starter */ - up(&xpc_discovery_exited); + complete(&xpc_discovery_exited); xpc_do_exit(xpcUnloading); return -EBUSY; diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index 321576b1b425..c6946784a6a8 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile @@ -7,4 +7,6 @@ # # Makefile for the sn pci general routines. +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 9bf9f23b9a1f..5a36292388eb 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -90,14 +90,14 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, */ node = pcibus_to_node(pdev->bus); if (likely(node >=0)) { - struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); + struct page *p = alloc_pages_node(node, flags, get_order(size)); if (likely(p)) cpuaddr = page_address(p); else return NULL; } else - cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + cpuaddr = (void *)__get_free_pages(flags, get_order(size)); if (unlikely(!cpuaddr)) return NULL; diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile index 1850c4a94c41..3b403ea456f9 100644 --- a/arch/ia64/sn/pci/pcibr/Makefile +++ b/arch/ia64/sn/pci/pcibr/Makefile @@ -7,5 +7,7 @@ # # Makefile for the sn2 io routines. +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += pcibr_dma.o pcibr_reg.o \ pcibr_ate.o pcibr_provider.o diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 77a1262751d3..2fac27049bf6 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -24,13 +24,15 @@ sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) { struct ia64_sal_retval ret_stuff; u64 busnum; + u64 segment; ret_stuff.status = 0; ret_stuff.v0 = 0; + segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; - SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum, - (u64) device, (u64) resp, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment, + busnum, (u64) device, (u64) resp, 0, 0, 0); return (int)ret_stuff.v0; } @@ -41,14 +43,16 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, { struct ia64_sal_retval ret_stuff; u64 busnum; + u64 segment; ret_stuff.status = 0; ret_stuff.v0 = 0; + segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE, - (u64) busnum, (u64) device, (u64) action, - (u64) resp, 0, 0, 0); + segment, busnum, (u64) device, (u64) action, + (u64) resp, 0, 0); return (int)ret_stuff.v0; } diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index dbc8a392105f..be8b711367ec 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c @@ -18,11 +18,6 @@ #include <asm/irq.h> #include <asm/tlbflush.h> -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) -extern struct drive_info_struct drive_info; -EXPORT_SYMBOL(drive_info); -#endif - /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); EXPORT_SYMBOL(dump_fpu); diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index c2e4dccf0112..d742037a7ccb 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -37,12 +37,6 @@ extern void init_mmu(void); #endif -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) \ - || defined(CONFIG_BLK_DEV_IDE_MODULE) \ - || defined(CONFIG_BLK_DEV_HD_MODULE) -struct drive_info_struct { char dummy[32]; } drive_info; -#endif - extern char _end[]; /* diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S index 3ba446a99a12..72f1159cb804 100644 --- a/arch/m68k/fpsp040/bindec.S +++ b/arch/m68k/fpsp040/bindec.S @@ -131,9 +131,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |BINDEC idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/binstr.S b/arch/m68k/fpsp040/binstr.S index d53555c0a2b6..8a05ba92a8a0 100644 --- a/arch/m68k/fpsp040/binstr.S +++ b/arch/m68k/fpsp040/binstr.S @@ -60,9 +60,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |BINSTR idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/bugfix.S b/arch/m68k/fpsp040/bugfix.S index 942c4f6f4fd1..3bb9c84bb058 100644 --- a/arch/m68k/fpsp040/bugfix.S +++ b/arch/m68k/fpsp040/bugfix.S @@ -152,9 +152,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/decbin.S b/arch/m68k/fpsp040/decbin.S index 2160609e328d..16ed796bad87 100644 --- a/arch/m68k/fpsp040/decbin.S +++ b/arch/m68k/fpsp040/decbin.S @@ -69,9 +69,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |DECBIN idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/do_func.S b/arch/m68k/fpsp040/do_func.S index 81f6a9856dce..3eff99a80413 100644 --- a/arch/m68k/fpsp040/do_func.S +++ b/arch/m68k/fpsp040/do_func.S @@ -22,9 +22,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. DO_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/fpsp.h b/arch/m68k/fpsp040/fpsp.h index 984a4eb8010a..5df4cd772934 100644 --- a/arch/m68k/fpsp040/fpsp.h +++ b/arch/m68k/fpsp040/fpsp.h @@ -5,9 +5,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. | fpsp.h --- stack frame offsets during FPSP exception handling | diff --git a/arch/m68k/fpsp040/gen_except.S b/arch/m68k/fpsp040/gen_except.S index 401d06f39f73..3642cb7e3641 100644 --- a/arch/m68k/fpsp040/gen_except.S +++ b/arch/m68k/fpsp040/gen_except.S @@ -29,9 +29,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. GEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/get_op.S b/arch/m68k/fpsp040/get_op.S index c7c2f3727425..64c36d79ef83 100644 --- a/arch/m68k/fpsp040/get_op.S +++ b/arch/m68k/fpsp040/get_op.S @@ -54,9 +54,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. GET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/kernel_ex.S b/arch/m68k/fpsp040/kernel_ex.S index 476b711967ce..45bcf3455d34 100644 --- a/arch/m68k/fpsp040/kernel_ex.S +++ b/arch/m68k/fpsp040/kernel_ex.S @@ -12,9 +12,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. KERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/res_func.S b/arch/m68k/fpsp040/res_func.S index 8f6b95217865..d9cdf4383545 100644 --- a/arch/m68k/fpsp040/res_func.S +++ b/arch/m68k/fpsp040/res_func.S @@ -16,9 +16,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. RES_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/round.S b/arch/m68k/fpsp040/round.S index 00f98068783f..f84ae0dd4358 100644 --- a/arch/m68k/fpsp040/round.S +++ b/arch/m68k/fpsp040/round.S @@ -8,9 +8,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |ROUND idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/sacos.S b/arch/m68k/fpsp040/sacos.S index 83b00ab1c48f..513c7cca7318 100644 --- a/arch/m68k/fpsp040/sacos.S +++ b/arch/m68k/fpsp040/sacos.S @@ -38,9 +38,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SACOS idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/sasin.S b/arch/m68k/fpsp040/sasin.S index 5647a6043903..2a269a58ceaa 100644 --- a/arch/m68k/fpsp040/sasin.S +++ b/arch/m68k/fpsp040/sasin.S @@ -38,9 +38,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SASIN idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/satan.S b/arch/m68k/fpsp040/satan.S index 20dae222d51e..c8a664998f92 100644 --- a/arch/m68k/fpsp040/satan.S +++ b/arch/m68k/fpsp040/satan.S @@ -43,9 +43,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |satan idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/satanh.S b/arch/m68k/fpsp040/satanh.S index 20f07810bcda..ba91f77a7571 100644 --- a/arch/m68k/fpsp040/satanh.S +++ b/arch/m68k/fpsp040/satanh.S @@ -45,9 +45,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |satanh idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/scale.S b/arch/m68k/fpsp040/scale.S index 5c9b805265f2..04829dd4f1f4 100644 --- a/arch/m68k/fpsp040/scale.S +++ b/arch/m68k/fpsp040/scale.S @@ -21,9 +21,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SCALE idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/scosh.S b/arch/m68k/fpsp040/scosh.S index e81edbb87642..07d3a4d7c86d 100644 --- a/arch/m68k/fpsp040/scosh.S +++ b/arch/m68k/fpsp040/scosh.S @@ -49,9 +49,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SCOSH idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/setox.S b/arch/m68k/fpsp040/setox.S index 0aa75f9bf7d1..145af5447581 100644 --- a/arch/m68k/fpsp040/setox.S +++ b/arch/m68k/fpsp040/setox.S @@ -331,9 +331,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |setox idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/sgetem.S b/arch/m68k/fpsp040/sgetem.S index 0fcbd045ba75..d9234f4aed57 100644 --- a/arch/m68k/fpsp040/sgetem.S +++ b/arch/m68k/fpsp040/sgetem.S @@ -24,9 +24,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SGETEM idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/sint.S b/arch/m68k/fpsp040/sint.S index 0f9bd28e55a0..0e92d4e5d231 100644 --- a/arch/m68k/fpsp040/sint.S +++ b/arch/m68k/fpsp040/sint.S @@ -51,9 +51,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SINT idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index a1629194e3fd..a8f41615d94a 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S @@ -30,9 +30,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. | | Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk) diff --git a/arch/m68k/fpsp040/slog2.S b/arch/m68k/fpsp040/slog2.S index 517fa4563246..fac2c738382e 100644 --- a/arch/m68k/fpsp040/slog2.S +++ b/arch/m68k/fpsp040/slog2.S @@ -96,9 +96,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SLOG2 idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/slogn.S b/arch/m68k/fpsp040/slogn.S index 2aaa0725c035..d98eaf641ec4 100644 --- a/arch/m68k/fpsp040/slogn.S +++ b/arch/m68k/fpsp040/slogn.S @@ -63,9 +63,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |slogn idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/smovecr.S b/arch/m68k/fpsp040/smovecr.S index a0127fa55e9c..73c36512081b 100644 --- a/arch/m68k/fpsp040/smovecr.S +++ b/arch/m68k/fpsp040/smovecr.S @@ -15,9 +15,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SMOVECR idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/srem_mod.S b/arch/m68k/fpsp040/srem_mod.S index 8c8d7f50cc68..a27e70c9a0eb 100644 --- a/arch/m68k/fpsp040/srem_mod.S +++ b/arch/m68k/fpsp040/srem_mod.S @@ -66,9 +66,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. SREM_MOD: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/ssin.S b/arch/m68k/fpsp040/ssin.S index 043c91cdd657..a1ef8e01bf06 100644 --- a/arch/m68k/fpsp040/ssin.S +++ b/arch/m68k/fpsp040/ssin.S @@ -83,9 +83,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SSIN idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/ssinh.S b/arch/m68k/fpsp040/ssinh.S index c8b3308bb143..8a560edc7653 100644 --- a/arch/m68k/fpsp040/ssinh.S +++ b/arch/m68k/fpsp040/ssinh.S @@ -49,9 +49,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |SSINH idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/stan.S b/arch/m68k/fpsp040/stan.S index b5c2a196e617..f8553aaececb 100644 --- a/arch/m68k/fpsp040/stan.S +++ b/arch/m68k/fpsp040/stan.S @@ -50,9 +50,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |STAN idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/stanh.S b/arch/m68k/fpsp040/stanh.S index 33b009802243..7e12e59ee8c7 100644 --- a/arch/m68k/fpsp040/stanh.S +++ b/arch/m68k/fpsp040/stanh.S @@ -49,9 +49,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |STANH idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/sto_res.S b/arch/m68k/fpsp040/sto_res.S index 0cdca3b060ad..484b47d4eaad 100644 --- a/arch/m68k/fpsp040/sto_res.S +++ b/arch/m68k/fpsp040/sto_res.S @@ -19,9 +19,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. STO_RES: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/stwotox.S b/arch/m68k/fpsp040/stwotox.S index 4e3c1407d3df..0d5e6a1436a6 100644 --- a/arch/m68k/fpsp040/stwotox.S +++ b/arch/m68k/fpsp040/stwotox.S @@ -76,9 +76,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |STWOTOX idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/tbldo.S b/arch/m68k/fpsp040/tbldo.S index fe60cf4d20d7..fd5c37a5a2b9 100644 --- a/arch/m68k/fpsp040/tbldo.S +++ b/arch/m68k/fpsp040/tbldo.S @@ -17,9 +17,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |TBLDO idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S index 452f3d65857b..65b26fa88c60 100644 --- a/arch/m68k/fpsp040/util.S +++ b/arch/m68k/fpsp040/util.S @@ -16,9 +16,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. |UTIL idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_bsun.S b/arch/m68k/fpsp040/x_bsun.S index 039247b09c8b..d5a576bfac79 100644 --- a/arch/m68k/fpsp040/x_bsun.S +++ b/arch/m68k/fpsp040/x_bsun.S @@ -13,9 +13,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_BSUN: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_fline.S b/arch/m68k/fpsp040/x_fline.S index 3917710b0fde..264e126d1db7 100644 --- a/arch/m68k/fpsp040/x_fline.S +++ b/arch/m68k/fpsp040/x_fline.S @@ -13,9 +13,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_FLINE: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_operr.S b/arch/m68k/fpsp040/x_operr.S index b0f54bcb49a7..e2c371c3a45d 100644 --- a/arch/m68k/fpsp040/x_operr.S +++ b/arch/m68k/fpsp040/x_operr.S @@ -43,9 +43,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_OPERR: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_ovfl.S b/arch/m68k/fpsp040/x_ovfl.S index 22cb8b42c7b6..6fe4989ee31f 100644 --- a/arch/m68k/fpsp040/x_ovfl.S +++ b/arch/m68k/fpsp040/x_ovfl.S @@ -35,9 +35,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_OVFL: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_snan.S b/arch/m68k/fpsp040/x_snan.S index 039af573312e..4ed766416378 100644 --- a/arch/m68k/fpsp040/x_snan.S +++ b/arch/m68k/fpsp040/x_snan.S @@ -22,9 +22,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_store.S b/arch/m68k/fpsp040/x_store.S index 4282fa67d449..402dc0c0ebc0 100644 --- a/arch/m68k/fpsp040/x_store.S +++ b/arch/m68k/fpsp040/x_store.S @@ -11,9 +11,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_unfl.S b/arch/m68k/fpsp040/x_unfl.S index 077fcc230fcc..eb772ff3b812 100644 --- a/arch/m68k/fpsp040/x_unfl.S +++ b/arch/m68k/fpsp040/x_unfl.S @@ -21,9 +21,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_UNFL: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_unimp.S b/arch/m68k/fpsp040/x_unimp.S index 920cb9410e9e..6f382b21228b 100644 --- a/arch/m68k/fpsp040/x_unimp.S +++ b/arch/m68k/fpsp040/x_unimp.S @@ -22,9 +22,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_UNIMP: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68k/fpsp040/x_unsupp.S b/arch/m68k/fpsp040/x_unsupp.S index 4ec57285b683..d7cf46208c62 100644 --- a/arch/m68k/fpsp040/x_unsupp.S +++ b/arch/m68k/fpsp040/x_unsupp.S @@ -23,9 +23,8 @@ | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | -| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA -| The copyright notice above does not evidence any -| actual or intended publication of such source code. +| For details on the license for this file, please see the +| file, README, in this same directory. X_UNSUPP: |idnt 2,1 | Motorola 040 Floating Point Software Package diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 99bf43824795..63c117dae0c3 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -39,6 +39,14 @@ asmlinkage void ret_from_fork(void); +/* + * The following aren't currently used. + */ +void (*pm_idle)(void); +EXPORT_SYMBOL(pm_idle); + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); /* * The idle loop on an m68knommu.. diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c3e852e9953e..767de847b4ab 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -595,6 +595,7 @@ config SGI_IP32 select SYS_HAS_CPU_R5000 select SYS_HAS_CPU_R10000 if BROKEN select SYS_HAS_CPU_RM7000 + select SYS_HAS_CPU_NEVADA select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN help diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2a9f2ef27b29..6a57407df1bc 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -53,14 +53,17 @@ CROSS_COMPILE := $(tool-prefix) endif CHECKFLAGS-y += -D__linux__ -D__mips__ \ + -D_MIPS_SZINT=32 \ -D_ABIO32=1 \ -D_ABIN32=2 \ -D_ABI64=3 CHECKFLAGS-$(CONFIG_32BIT) += -D_MIPS_SIM=_ABIO32 \ -D_MIPS_SZLONG=32 \ + -D_MIPS_SZPTR=32 \ -D__PTRDIFF_TYPE__=int CHECKFLAGS-$(CONFIG_64BIT) += -m64 -D_MIPS_SIM=_ABI64 \ -D_MIPS_SZLONG=64 \ + -D_MIPS_SZPTR=64 \ -D__PTRDIFF_TYPE__="long int" CHECKFLAGS-$(CONFIG_CPU_BIG_ENDIAN) += -D__MIPSEB__ CHECKFLAGS-$(CONFIG_CPU_LITTLE_ENDIAN) += -D__MIPSEL__ @@ -166,79 +169,97 @@ echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_i # cflags-$(CONFIG_CPU_R3000) += \ $(call set_gccflags,r3000,mips1,r3000,mips1,mips1) +CHECKFLAGS-$(CONFIG_CPU_R3000) += -D_MIPS_ISA=_MIPS_ISA_MIPS1 cflags-$(CONFIG_CPU_TX39XX) += \ $(call set_gccflags,r3900,mips1,r3000,mips1,mips1) +CHECKFLAGS-$(CONFIG_CPU_TX39XX) += -D_MIPS_ISA=_MIPS_ISA_MIPS1 cflags-$(CONFIG_CPU_R6000) += \ $(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R6000) += -D_MIPS_ISA=_MIPS_ISA_MIPS2 cflags-$(CONFIG_CPU_R4300) += \ $(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R4300) += -D_MIPS_ISA=_MIPS_ISA_MIPS3 cflags-$(CONFIG_CPU_VR41XX) += \ $(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_VR41XX) += -D_MIPS_ISA=_MIPS_ISA_MIPS3 cflags-$(CONFIG_CPU_R4X00) += \ $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R4X00) += -D_MIPS_ISA=_MIPS_ISA_MIPS3 cflags-$(CONFIG_CPU_TX49XX) += \ $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_TX49XX) += -D_MIPS_ISA=_MIPS_ISA_MIPS3 cflags-$(CONFIG_CPU_MIPS32_R1) += \ $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_MIPS32_R1) += -D_MIPS_ISA=_MIPS_ISA_MIPS32 cflags-$(CONFIG_CPU_MIPS32_R2) += \ $(call set_gccflags,mips32r2,mips32r2,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_MIPS32_R2) += -D_MIPS_ISA=_MIPS_ISA_MIPS32 cflags-$(CONFIG_CPU_MIPS64_R1) += \ $(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_MIPS64_R1) += -D_MIPS_ISA=_MIPS_ISA_MIPS64 cflags-$(CONFIG_CPU_MIPS64_R2) += \ $(call set_gccflags,mips64r2,mips64r2,r4600,mips3,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_MIPS64_R2) += -D_MIPS_ISA=_MIPS_ISA_MIPS64 cflags-$(CONFIG_CPU_R5000) += \ $(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R5000) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_R5432) += \ $(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R5432) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_NEVADA) += \ $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \ -Wa,--trap -# $(call cc-option,-mmad) +CHECKFLAGS-$(CONFIG_CPU_NEVADA) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_RM7000) += \ $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_RM7000) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_RM9000) += \ $(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_RM9000) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_SB1) += \ $(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_SB1) += -D_MIPS_ISA=_MIPS_ISA_MIPS64 cflags-$(CONFIG_CPU_R8000) += \ $(call set_gccflags,r8000,mips4,r8000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R8000) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 cflags-$(CONFIG_CPU_R10000) += \ $(call set_gccflags,r10000,mips4,r8000,mips4,mips2) \ -Wa,--trap +CHECKFLAGS-$(CONFIG_CPU_R10000) += -D_MIPS_ISA=_MIPS_ISA_MIPS4 ifdef CONFIG_CPU_SB1 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS @@ -369,7 +390,7 @@ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # Cobalt Server # core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -cflags-$(CONFIG_MIPS_COBALT) += -Iinclude/asm-mips/cobalt +cflags-$(CONFIG_MIPS_COBALT) += -Iinclude/asm-mips/mach-cobalt load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 # diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c index 65b84db800e4..4ffccedf5967 100644 --- a/arch/mips/au1000/common/reset.c +++ b/arch/mips/au1000/common/reset.c @@ -151,7 +151,7 @@ void au1000_restart(char *command) } set_c0_status(ST0_BEV | ST0_ERL); - set_c0_config(CONF_CM_UNCACHED); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); flush_cache_all(); write_c0_wired(0); diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 08c8c855cc9c..eb155c071aa6 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -33,6 +33,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/pm.h> #include <asm/cpu.h> #include <asm/bootinfo.h> @@ -125,7 +126,7 @@ void __init plat_setup(void) #endif _machine_restart = au1000_restart; _machine_halt = au1000_halt; - _machine_power_off = au1000_power_off; + pm_power_off = au1000_power_off; board_time_init = au1xxx_time_init; board_timer_setup = au1xxx_timer_setup; diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S index f92608e8d84f..e75d5e3ca868 100644 --- a/arch/mips/cobalt/int-handler.S +++ b/arch/mips/cobalt/int-handler.S @@ -8,7 +8,7 @@ */ #include <asm/asm.h> #include <asm/mipsregs.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> #include <asm/regdef.h> #include <asm/stackframe.h> diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c index 0d90851f925e..f9a108820d6e 100644 --- a/arch/mips/cobalt/irq.c +++ b/arch/mips/cobalt/irq.c @@ -18,7 +18,7 @@ #include <asm/gt64120.h> #include <asm/ptrace.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> extern void cobalt_handle_int(void); diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c index 805a0e88507b..753dfccae6fa 100644 --- a/arch/mips/cobalt/reset.c +++ b/arch/mips/cobalt/reset.c @@ -16,7 +16,7 @@ #include <asm/reboot.h> #include <asm/system.h> #include <asm/mipsregs.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> void cobalt_machine_halt(void) { diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index d358a118fa31..b9713a723053 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1996, 1997, 2004, 05 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) * */ @@ -13,6 +13,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/pm.h> #include <linux/serial.h> #include <linux/serial_core.h> @@ -25,7 +26,7 @@ #include <asm/gt64120.h> #include <asm/serial.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> extern void cobalt_machine_restart(char *command); extern void cobalt_machine_halt(void); @@ -99,7 +100,7 @@ void __init plat_setup(void) _machine_restart = cobalt_machine_restart; _machine_halt = cobalt_machine_halt; - _machine_power_off = cobalt_machine_power_off; + pm_power_off = cobalt_machine_power_off; board_timer_setup = cobalt_timer_setup; @@ -139,7 +140,7 @@ void __init plat_setup(void) uart.type = PORT_UNKNOWN; uart.uartclk = 18432000; uart.irq = COBALT_SERIAL_IRQ; - uart.flags = STD_COM_FLAGS; + uart.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; uart.iobase = 0xc800000; uart.iotype = UPIO_PORT; diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 967e7acd8e1f..a34db6e82b27 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -102,6 +102,7 @@ CONFIG_CPU_R5000=y # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set CONFIG_SYS_HAS_CPU_R5000=y +CONFIG_SYS_HAS_CPU_NEVADA=y CONFIG_SYS_HAS_CPU_RM7000=y CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig index dee44606164c..c02becab850b 100644 --- a/arch/mips/configs/qemu_defconfig +++ b/arch/mips/configs/qemu_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc2 -# Thu Nov 24 01:07:00 2005 +# Linux kernel version: 2.6.16-rc2 +# Fri Feb 3 17:14:27 2006 # CONFIG_MIPS=y @@ -147,26 +147,27 @@ CONFIG_LOCALVERSION_AUTO=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set CONFIG_PRINTK=y # CONFIG_BUG is not set +CONFIG_ELF_CORE=y # CONFIG_BASE_FULL is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_SHMEM is not set CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y CONFIG_TINY_SHMEM=y CONFIG_BASE_SMALL=1 +# CONFIG_SLOB is not set # # Loadable module support @@ -266,11 +267,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_CRYPT_CCMP=y -CONFIG_IEEE80211_CRYPT_TKIP=y +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -323,7 +320,7 @@ CONFIG_BLK_DEV_RAM_COUNT=16 # # SCSI device support # -CONFIG_RAID_ATTRS=y +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -366,24 +363,16 @@ CONFIG_NETDEVICES=y # # PHY device support # -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -CONFIG_DAVICOM_PHY=y -CONFIG_QSEMI_PHY=y -CONFIG_LXT_PHY=y -CONFIG_CICADA_PHY=y +# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MII=y +# CONFIG_MII is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_SMC is not set +# CONFIG_DM9000 is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set @@ -479,6 +468,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -518,6 +508,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -592,11 +588,14 @@ CONFIG_DUMMY_CONSOLE=y # # +# EDAC - error detection and reporting (RAS) +# + +# # File systems # # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -677,6 +676,7 @@ CONFIG_MSDOS_PARTITION=y # Kernel hacking # # CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_CROSSCOMPILE=y @@ -690,31 +690,7 @@ CONFIG_CMDLINE="console=ttyS0 debug ip=172.20.0.2:172.20.0.1::255.255.0.0" # # Cryptographic options # -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_WP512=y -CONFIG_CRYPTO_TGR192=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_CAST5=y -CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_TEA=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_KHAZAD=y -CONFIG_CRYPTO_ANUBIS=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_CRC32C=y -# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO is not set # # Hardware crypto devices @@ -724,8 +700,6 @@ CONFIG_CRYPTO_CRC32C=y # Library routines # # CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y +# CONFIG_CRC16 is not set CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c index 11535be265b9..91456b068c2e 100644 --- a/arch/mips/ddb5xxx/ddb5074/setup.c +++ b/arch/mips/ddb5xxx/ddb5074/setup.c @@ -14,6 +14,7 @@ #include <linux/ide.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/pm.h> #include <asm/addrspace.h> #include <asm/bcache.h> @@ -95,7 +96,7 @@ void __init plat_setup(void) _machine_restart = ddb_machine_restart; _machine_halt = ddb_machine_halt; - _machine_power_off = ddb_machine_power_off; + pm_power_off = ddb_machine_power_off; ddb_out32(DDB_BAR0, 0); diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c index f4e480a74edf..c902adef5942 100644 --- a/arch/mips/ddb5xxx/ddb5476/setup.c +++ b/arch/mips/ddb5xxx/ddb5476/setup.c @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/sched.h> #include <linux/pci.h> +#include <linux/pm.h> #include <asm/addrspace.h> #include <asm/bcache.h> @@ -133,7 +134,7 @@ void __init plat_setup(void) _machine_restart = ddb_machine_restart; _machine_halt = ddb_machine_halt; - _machine_power_off = ddb_machine_power_off; + pm_power_off = ddb_machine_power_off; /* request io port/mem resources */ if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) || diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c index 81163353c4a8..2f566034cc44 100644 --- a/arch/mips/ddb5xxx/ddb5477/setup.c +++ b/arch/mips/ddb5xxx/ddb5477/setup.c @@ -26,6 +26,7 @@ #include <linux/major.h> #include <linux/kdev_t.h> #include <linux/root_dev.h> +#include <linux/pm.h> #include <asm/cpu.h> #include <asm/bootinfo.h> @@ -182,7 +183,7 @@ void __init plat_setup(void) _machine_restart = ddb_machine_restart; _machine_halt = ddb_machine_halt; - _machine_power_off = ddb_machine_power_off; + pm_power_off = ddb_machine_power_off; /* setup resource limits */ ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1; diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 9ef54fe1feaa..7c1ca8f6330e 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -17,6 +17,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/types.h> +#include <linux/pm.h> #include <asm/bootinfo.h> #include <asm/cpu.h> @@ -158,7 +159,7 @@ void __init plat_setup(void) _machine_restart = dec_machine_restart; _machine_halt = dec_machine_halt; - _machine_power_off = dec_machine_power_off; + pm_power_off = dec_machine_power_off; ioport_resource.start = ~0UL; ioport_resource.end = 0UL; diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c index 98b5a96cc039..6d859d1e7a2d 100644 --- a/arch/mips/gt64120/ev64120/setup.c +++ b/arch/mips/gt64120/ev64120/setup.c @@ -34,6 +34,8 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/timex.h> +#include <linux/pm.h> + #include <asm/bootinfo.h> #include <asm/page.h> #include <asm/io.h> @@ -73,7 +75,7 @@ void __init plat_setup(void) { _machine_restart = galileo_machine_restart; _machine_halt = galileo_machine_halt; - _machine_power_off = galileo_machine_power_off; + pm_power_off = galileo_machine_power_off; board_time_init = gt64120_time_init; set_io_port_base(KSEG1); diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index 0d07c33112d0..20b65d3d2151 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -4,7 +4,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Ocelot (CP7000) - board dependent boot routines * - * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 1996, 1997, 2001, 06 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer @@ -47,6 +47,8 @@ #include <linux/pci.h> #include <linux/timex.h> #include <linux/vmalloc.h> +#include <linux/pm.h> + #include <asm/time.h> #include <asm/bootinfo.h> #include <asm/page.h> @@ -159,7 +161,7 @@ void __init plat_setup(void) _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; - _machine_power_off = momenco_ocelot_power_off; + pm_power_off = momenco_ocelot_power_off; /* * initrd_start = (ulong)ocelot_initrd_start; diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c index 062429dd7ca0..fc73c8d69df7 100644 --- a/arch/mips/ite-boards/generic/it8172_setup.c +++ b/arch/mips/ite-boards/generic/it8172_setup.c @@ -34,6 +34,7 @@ #include <linux/major.h> #include <linux/kdev_t.h> #include <linux/root_dev.h> +#include <linux/pm.h> #include <asm/cpu.h> #include <asm/time.h> @@ -125,7 +126,7 @@ void __init plat_setup(void) _machine_restart = it8172_restart; _machine_halt = it8172_halt; - _machine_power_off = it8172_power_off; + pm_power_off = it8172_power_off; /* * IO/MEM resources. diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index 044df9d4ab7c..4036dc434551 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -19,6 +19,8 @@ #include <linux/console.h> #include <linux/fb.h> #include <linux/ide.h> +#include <linux/pm.h> + #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/jazz.h> @@ -79,7 +81,7 @@ void __init plat_setup(void) _machine_restart = jazz_machine_restart; _machine_halt = jazz_machine_halt; - _machine_power_off = jazz_machine_power_off; + pm_power_off = jazz_machine_power_off; #warning "Somebody should check if screen_info is ok for Jazz." diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 4763957df8fc..9359cc413494 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -44,6 +44,7 @@ #include <linux/ioport.h> #include <linux/param.h> /* for HZ */ #include <linux/delay.h> +#include <linux/pm.h> #ifdef CONFIG_SERIAL_TXX9 #include <linux/tty.h> #include <linux/serial.h> @@ -211,7 +212,7 @@ void __init plat_setup(void) _machine_restart = jmr3927_machine_restart; _machine_halt = jmr3927_machine_halt; - _machine_power_off = jmr3927_machine_power_off; + pm_power_off = jmr3927_machine_power_off; /* * IO/MEM resources. diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index fac48ad27b34..292f8b243a5e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -2,8 +2,8 @@ * Processor capabilities determination functions. * * Copyright (C) xxxx the Anonymous + * Copyright (C) 1994 - 2006 Ralf Baechle * Copyright (C) 2003, 2004 Maciej W. Rozycki - * Copyright (C) 1994 - 2003 Ralf Baechle * Copyright (C) 2001, 2004 MIPS Inc. * * This program is free software; you can redistribute it and/or @@ -641,10 +641,9 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c) switch (c->processor_id & 0xff00) { case PRID_IMP_SB1: c->cputype = CPU_SB1; -#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* FPU in pass1 is known to have issues. */ - c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR); -#endif + if ((c->processor_id & 0xff) < 0x20) + c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR); break; case PRID_IMP_SB1A: c->cputype = CPU_SB1A; diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c index 96d18c43dca0..d4f88e0af24c 100644 --- a/arch/mips/kernel/gdb-stub.c +++ b/arch/mips/kernel/gdb-stub.c @@ -178,7 +178,7 @@ int kgdb_enabled; */ static DEFINE_SPINLOCK(kgdb_lock); static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { - [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED; + [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED, }; /* diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index aa18a8b7b380..13f22d1d0e8b 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -233,11 +233,11 @@ NESTED(except_vec_nmi, 0, sp) NESTED(nmi_handler, PT_SIZE, sp) .set push .set noat - .set mips3 SAVE_ALL move a0, sp jal nmi_exception_handler RESTORE_ALL + .set mips3 eret .set pop END(nmi_handler) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index fa98f10d0132..5232fc752935 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -4,6 +4,7 @@ * for more details. * * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. + * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 2004 Thiemo Seufer */ @@ -58,8 +59,8 @@ ATTRIB_NORET void cpu_idle(void) } } -extern int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); +extern void do_signal(struct pt_regs *regs); +extern void do_signal32(struct pt_regs *regs); /* * Native o32 and N64 ABI without DSP ASE diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 0c82b25d8c6d..0d5cf97af727 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -88,7 +88,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO; if (copied != sizeof(tmp)) break; - ret = put_user(tmp, (unsigned int *) (unsigned long) data); + ret = put_user(tmp, (unsigned int __user *) (unsigned long) data); break; } @@ -174,8 +174,10 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case FPC_EIR: { /* implementation / version register */ unsigned int flags; - if (!cpu_has_fpu) + if (!cpu_has_fpu) { + tmp = 0; break; + } preempt_disable(); if (cpu_has_mipsmt) { @@ -194,15 +196,18 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) preempt_enable(); break; } - case DSP_BASE ... DSP_BASE + 5: + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; + if (!cpu_has_dsp) { tmp = 0; ret = -EIO; goto out_tsk; } - dspreg_t *dregs = __get_dsp_regs(child); + dregs = __get_dsp_regs(child); tmp = (unsigned long) (dregs[addr - DSP_BASE]); break; + } case DSP_CONTROL: if (!cpu_has_dsp) { tmp = 0; @@ -216,7 +221,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = -EIO; goto out_tsk; } - ret = put_user(tmp, (unsigned *) (unsigned long) data); + ret = put_user(tmp, (unsigned __user *) (unsigned long) data); break; } @@ -304,15 +309,18 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) else child->thread.fpu.soft.fcr31 = data; break; - case DSP_BASE ... DSP_BASE + 5: + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; + if (!cpu_has_dsp) { ret = -EIO; break; } - dspreg_t *dregs = __get_dsp_regs(child); + dregs = __get_dsp_regs(child); dregs[addr - DSP_BASE] = data; break; + } case DSP_CONTROL: if (!cpu_has_dsp) { ret = -EIO; diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index 5e37df3111ad..621037db2290 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -3,17 +3,16 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 by Ralf Baechle + * Copyright (C) 2001, 06 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2001 MIPS Technologies, Inc. */ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/pm.h> #include <linux/types.h> #include <linux/reboot.h> -#include <asm/reboot.h> -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); +#include <asm/reboot.h> /* * Urgs ... Too many MIPS machines to handle this in a generic way. @@ -22,23 +21,22 @@ EXPORT_SYMBOL(pm_power_off); */ void (*_machine_restart)(char *command); void (*_machine_halt)(void); -void (*_machine_power_off)(void); +void (*pm_power_off)(void); void machine_restart(char *command) { - _machine_restart(command); + if (_machine_restart) + _machine_restart(command); } void machine_halt(void) { - _machine_halt(); + if (_machine_halt) + _machine_halt(); } void machine_power_off(void) { if (pm_power_off) pm_power_off(); - - _machine_power_off(); } - diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 1d855112bac2..986a9cf23067 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as @@ -20,9 +21,12 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/poll.h> #include <linux/sched.h> #include <linux/wait.h> + #include <asm/mipsmtregs.h> #include <asm/bitops.h> #include <asm/cpu.h> diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index a42e0e8caa7b..d83e033dbc87 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -617,6 +617,23 @@ einval: li v0, -EINVAL sys sys_inotify_init 0 sys sys_inotify_add_watch 3 /* 4285 */ sys sys_inotify_rm_watch 2 + sys sys_migrate_pages 4 + sys sys_openat 4 + sys sys_mkdirat 3 + sys sys_mknodat 4 /* 4290 */ + sys sys_fchownat 5 + sys sys_futimesat 3 + sys sys_fstatat64 4 + sys sys_unlinkat 3 + sys sys_renameat 4 /* 4295 */ + sys sys_linkat 4 + sys sys_symlinkat 3 + sys sys_readlinkat 4 + sys sys_fchmodat 3 + sys sys_faccessat 3 /* 4300 */ + sys sys_pselect6 6 + sys sys_ppoll 5 + sys sys_unshare 1 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 47bfbd416709..98bf25df56f3 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -443,3 +443,20 @@ sys_call_table: PTR sys_inotify_init PTR sys_inotify_add_watch PTR sys_inotify_rm_watch /* 5245 */ + PTR sys_migrate_pages + PTR sys_openat + PTR sys_mkdirat + PTR sys_mknodat + PTR sys_fchownat /* 5250 */ + PTR sys_futimesat + PTR sys_newfstatat + PTR sys_unlinkat + PTR sys_renameat + PTR sys_linkat /* 5255 */ + PTR sys_symlinkat + PTR sys_readlinkat + PTR sys_fchmodat + PTR sys_faccessat + PTR sys_pselect6 /* 5260 */ + PTR sys_ppoll + PTR sys_unshare diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index b465ced1758f..bc4980cefc8b 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -369,3 +369,20 @@ EXPORT(sysn32_call_table) PTR sys_inotify_init PTR sys_inotify_add_watch PTR sys_inotify_rm_watch + PTR sys_migrate_pages /* 6250 */ + PTR sys_openat + PTR sys_mkdirat + PTR sys_mknodat + PTR sys_fchownat + PTR sys_futimesat /* 6255 */ + PTR sys_newfstatat + PTR sys_unlinkat + PTR sys_renameat + PTR sys_linkat + PTR sys_symlinkat /* 6260 */ + PTR sys_readlinkat + PTR sys_fchmodat + PTR sys_faccessat + PTR sys_pselect6 + PTR sys_ppoll /* 6265 */ + PTR sys_unshare diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 3d338ca7eeeb..5b0414018c9a 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -491,4 +491,21 @@ sys_call_table: PTR sys_inotify_init PTR sys_inotify_add_watch /* 4285 */ PTR sys_inotify_rm_watch + PTR sys_migrate_pages + PTR compat_sys_openat + PTR sys_mkdirat + PTR sys_mknodat /* 4290 */ + PTR sys_fchownat + PTR compat_sys_futimesat + PTR compat_sys_newfstatat + PTR sys_unlinkat + PTR sys_renameat /* 4295 */ + PTR sys_linkat + PTR sys_symlinkat + PTR sys_readlinkat + PTR sys_fchmodat + PTR sys_faccessat /* 4300 */ + PTR sys_pselect6 + PTR sys_ppoll + PTR sys_unshare .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index 0f66ae5838b9..0fbc492d24b4 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h @@ -11,7 +11,7 @@ #include <linux/config.h> static inline int -setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; @@ -82,7 +82,7 @@ out: } static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { unsigned int used_math; unsigned long treg; @@ -157,7 +157,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) /* * Determine which stack to use.. */ -static inline void * +static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long sp; @@ -176,7 +176,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; - return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK)); + return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK)); } static inline int install_sigtramp(unsigned int __user *tramp, diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 7d1800fe7038..c974cc9b30eb 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -39,8 +39,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -int do_signal(sigset_t *oldset, struct pt_regs *regs); - /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend); __attribute_used__ noinline static int _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) { - sigset_t saveset, newset; + sigset_t newset; sigset_t __user *uset; uset = (sigset_t __user *) regs.regs[4]; @@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.regs[2] = EINTR; - regs.regs[7] = 1; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, ®s)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } #endif @@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend); __attribute_used__ noinline static int _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { - sigset_t saveset, newset; + sigset_t newset; sigset_t __user *unewset; size_t sigsetsize; @@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.regs[2] = EINTR; - regs.regs[7] = 1; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, ®s)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } #ifdef CONFIG_TRAD_SIGNALS @@ -199,10 +189,10 @@ save_static_function(sys_sigreturn); __attribute_used__ noinline static void _sys_sigreturn(nabi_no_regargs struct pt_regs regs) { - struct sigframe *frame; + struct sigframe __user *frame; sigset_t blocked; - frame = (struct sigframe *) regs.regs[29]; + frame = (struct sigframe __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) @@ -236,11 +226,11 @@ save_static_function(sys_rt_sigreturn); __attribute_used__ noinline static void _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { - struct rt_sigframe *frame; + struct rt_sigframe __user *frame; sigset_t set; stack_t st; - frame = (struct rt_sigframe *) regs.regs[29]; + frame = (struct rt_sigframe __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) @@ -259,7 +249,7 @@ _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.regs[29]); + do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); /* * Don't let your children do this ... @@ -279,7 +269,7 @@ badframe: int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set) { - struct sigframe *frame; + struct sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -315,18 +305,18 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, frame->regs[31]); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(signr, current); - return 0; + return -EFAULT; } #endif int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { - struct rt_sigframe *frame; + struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -340,7 +330,7 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); - err |= __put_user(0, &frame->rs_uc.uc_link); + err |= __put_user(NULL, &frame->rs_uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->rs_uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[29]), @@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(signr, current); - return 0; + return -EFAULT; } static inline int handle_signal(unsigned long sig, siginfo_t *info, @@ -393,7 +383,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, regs->regs[2] = EINTR; break; case ERESTARTSYS: - if(!(ka->sa.sa_flags & SA_RESTART)) { + if (!(ka->sa.sa_flags & SA_RESTART)) { regs->regs[2] = EINTR; break; } @@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, return ret; } -int do_signal(sigset_t *oldset, struct pt_regs *regs) +void do_signal(struct pt_regs *regs) { struct k_sigaction ka; + sigset_t *oldset; siginfo_t info; int signr; @@ -432,17 +423,31 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) * if so. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset, regs); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + } no_signal: /* @@ -463,18 +468,25 @@ no_signal: regs->cp0_epc -= 4; } } - return 0; + + /* + * If there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* * notification of userspace execution resumption - * - triggered by current->work.notify_resume + * - triggered by the TIF_WORK_MASK flags */ -asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, +asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) { - current->thread.abi->do_signal(oldset, regs); - } + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + current->thread.abi->do_signal(regs); } diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 98b185bbc947..da3271e1fdac 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -144,7 +144,7 @@ struct ucontext32 { extern void __put_sigset_unknown_nsig(void); extern void __get_sigset_unknown_nsig(void); -static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf) +static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf) { int err = 0; @@ -269,7 +269,7 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; err |= __get_user(handler, &act->sa_handler); - new_ka.sa.sa_handler = (void*)(s64)handler; + new_ka.sa.sa_handler = (void __user *)(s64)handler; err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); err |= __get_user(mask, &act->sa_mask.sig[0]); if (err) @@ -299,8 +299,8 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) { - const stack32_t *uss = (const stack32_t *) regs.regs[4]; - stack32_t *uoss = (stack32_t *) regs.regs[5]; + const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4]; + stack32_t __user *uoss = (stack32_t __user *) regs.regs[5]; unsigned long usp = regs.regs[29]; stack_t kss, koss; int ret, err = 0; @@ -319,7 +319,8 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) } set_fs (KERNEL_DS); - ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp); + ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL, + uoss ? (stack_t __user *)&koss : NULL, usp); set_fs (old_fs); if (!ret && uoss) { @@ -335,7 +336,7 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) return ret; } -static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc) +static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc) { u32 used_math; int err = 0; @@ -420,7 +421,7 @@ struct rt_sigframe32 { #endif }; -int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) +int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err; @@ -455,7 +456,7 @@ int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_FAULT >> 16: - err |= __put_user((long)from->si_addr, &to->si_addr); + err |= __put_user((unsigned long)from->si_addr, &to->si_addr); break; case __SI_POLL >> 16: err |= __put_user(from->si_band, &to->si_band); @@ -476,10 +477,10 @@ save_static_function(sys32_sigreturn); __attribute_used__ noinline static void _sys32_sigreturn(nabi_no_regargs struct pt_regs regs) { - struct sigframe *frame; + struct sigframe __user *frame; sigset_t blocked; - frame = (struct sigframe *) regs.regs[29]; + frame = (struct sigframe __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) @@ -512,13 +513,13 @@ save_static_function(sys32_rt_sigreturn); __attribute_used__ noinline static void _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { - struct rt_sigframe32 *frame; + struct rt_sigframe32 __user *frame; mm_segment_t old_fs; sigset_t set; stack_t st; s32 sp; - frame = (struct rt_sigframe32 *) regs.regs[29]; + frame = (struct rt_sigframe32 __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) @@ -546,7 +547,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) call it and ignore errors. */ old_fs = get_fs(); set_fs (KERNEL_DS); - do_sigaltstack(&st, NULL, regs.regs[29]); + do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); set_fs (old_fs); /* @@ -564,7 +565,7 @@ badframe: } static inline int setup_sigcontext32(struct pt_regs *regs, - struct sigcontext32 *sc) + struct sigcontext32 __user *sc) { int err = 0; @@ -623,8 +624,9 @@ out: /* * Determine which stack to use.. */ -static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) +static inline void __user *get_sigframe(struct k_sigaction *ka, + struct pt_regs *regs, + size_t frame_size) { unsigned long sp; @@ -642,13 +644,13 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; - return (void *)((sp - frame_size) & ALMASK); + return (void __user *)((sp - frame_size) & ALMASK); } int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set) { - struct sigframe *frame; + struct sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -692,17 +694,17 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, frame->sf_code); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(signr, current); - return 0; + return -EFAULT; } int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { - struct rt_sigframe32 *frame; + struct rt_sigframe32 __user *frame; int err = 0; s32 sp; @@ -763,11 +765,11 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, frame->rs_code); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(signr, current); - return 0; + return -EFAULT; } static inline int handle_signal(unsigned long sig, siginfo_t *info, @@ -855,7 +857,7 @@ no_signal: } asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, - struct sigaction32 *oact, + struct sigaction32 __user *oact, unsigned int sigsetsize) { struct k_sigaction new_sa, old_sa; @@ -872,7 +874,7 @@ asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; err |= __get_user(handler, &act->sa_handler); - new_sa.sa.sa_handler = (void*)(s64)handler; + new_sa.sa.sa_handler = (void __user *)(s64)handler; err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); if (err) @@ -899,7 +901,7 @@ out: } asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, - compat_sigset_t *oset, unsigned int sigsetsize) + compat_sigset_t __user *oset, unsigned int sigsetsize) { sigset_t old_set, new_set; int ret; @@ -909,8 +911,9 @@ asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, return -EFAULT; set_fs (KERNEL_DS); - ret = sys_rt_sigprocmask(how, set ? &new_set : NULL, - oset ? &old_set : NULL, sigsetsize); + ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL, + oset ? (sigset_t __user *)&old_set : NULL, + sigsetsize); set_fs (old_fs); if (!ret && oset && put_sigset(&old_set, oset)) @@ -919,7 +922,7 @@ asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, return ret; } -asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, +asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize) { int ret; @@ -927,7 +930,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_rt_sigpending(&set, sigsetsize); + ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize); set_fs (old_fs); if (!ret && put_sigset(&set, uset)) @@ -936,7 +939,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, return ret; } -asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo) +asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) { siginfo_t info; int ret; @@ -946,7 +949,7 @@ asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo) copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) return -EFAULT; set_fs (KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, &info); + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); set_fs (old_fs); return ret; } diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index ec61b2670ba6..384fc4a639a4 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -48,6 +48,8 @@ #define __NR_N32_rt_sigreturn 6211 #define __NR_N32_restart_syscall 6214 +#define DEBUG_SIG 0 + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) /* IRIX compatible stack_t */ @@ -83,12 +85,12 @@ save_static_function(sysn32_rt_sigreturn); __attribute_used__ noinline static void _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { - struct rt_sigframe_n32 *frame; + struct rt_sigframe_n32 __user *frame; sigset_t set; stack_t st; s32 sp; - frame = (struct rt_sigframe_n32 *) regs.regs[29]; + frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) @@ -114,7 +116,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.regs[29]); + do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); /* * Don't let your children do this ... @@ -133,7 +135,7 @@ badframe: int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { - struct rt_sigframe_n32 *frame; + struct rt_sigframe_n32 __user *frame; int err = 0; s32 sp; @@ -184,9 +186,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka, current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(signr, current); - return 0; + return -EFAULT; } diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 332358430ff5..1da2eeb3ef9e 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -212,12 +212,12 @@ asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) int error; char * filename; - filename = getname((char *) (long)regs.regs[4]); + filename = getname((char __user *) (long)regs.regs[4]); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, (char **) (long)regs.regs[5], - (char **) (long)regs.regs[6], ®s); + error = do_execve(filename, (char __user *__user *) (long)regs.regs[5], + (char __user *__user *) (long)regs.regs[6], ®s); putname(filename); out: @@ -227,7 +227,7 @@ out: /* * Compacrapability ... */ -asmlinkage int sys_uname(struct old_utsname * name) +asmlinkage int sys_uname(struct old_utsname __user * name) { if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) return 0; @@ -237,7 +237,7 @@ asmlinkage int sys_uname(struct old_utsname * name) /* * Compacrapability ... */ -asmlinkage int sys_olduname(struct oldold_utsname * name) +asmlinkage int sys_olduname(struct oldold_utsname __user * name) { int error; @@ -274,7 +274,7 @@ void sys_set_thread_area(unsigned long addr) asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) { int tmp, len; - char *name; + char __user *name; switch(cmd) { case SETNAME: { @@ -283,7 +283,7 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - name = (char *) arg1; + name = (char __user *) arg1; len = strncpy_from_user(nodename, name, __NEW_UTS_LEN); if (len < 0) @@ -324,7 +324,7 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - unsigned long third, void *ptr, long fifth) + unsigned long third, void __user *ptr, long fifth) { int version, ret; @@ -333,24 +333,25 @@ asmlinkage int sys_ipc (uint call, int first, int second, switch (call) { case SEMOP: - return sys_semtimedop (first, (struct sembuf *)ptr, second, - NULL); + return sys_semtimedop (first, (struct sembuf __user *)ptr, + second, NULL); case SEMTIMEDOP: - return sys_semtimedop (first, (struct sembuf *)ptr, second, - (const struct timespec __user *)fifth); + return sys_semtimedop (first, (struct sembuf __user *)ptr, + second, + (const struct timespec __user *)fifth); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) + if (get_user(fourth.__pad, (void *__user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third); case MSGRCV: switch (version) { @@ -360,7 +361,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, return -EINVAL; if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, + (struct ipc_kludge __user *) ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, @@ -368,35 +369,38 @@ asmlinkage int sys_ipc (uint call, int first, int second, } default: return sys_msgrcv (first, - (struct msgbuf *) ptr, + (struct msgbuf __user *) ptr, second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: - return sys_msgctl (first, second, (struct msqid_ds *) ptr); + return sys_msgctl (first, second, + (struct msqid_ds __user *) ptr); case SHMAT: switch (version) { default: { ulong raddr; - ret = do_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char __user *) ptr, second, + &raddr); if (ret) return ret; - return put_user (raddr, (ulong *) third); + return put_user (raddr, (ulong __user *) third); } case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return do_shmat (first, (char *) ptr, second, (ulong *) third); + return do_shmat (first, (char __user *) ptr, second, + (ulong *) third); } case SHMDT: - return sys_shmdt ((char *)ptr); + return sys_shmdt ((char __user *)ptr); case SHMGET: return sys_shmget (first, second, third); case SHMCTL: return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + (struct shmid_ds __user *) ptr); default: return -ENOSYS; } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 59a187956de0..c9d2b5147ca3 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1168,7 +1168,7 @@ void __init per_cpu_trap_init(void) #endif if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) status_set |= ST0_XX; - change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, + change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, status_set); if (cpu_has_dsp) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 25cc856d8e7e..ff699dbb99f7 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -1,4 +1,5 @@ #include <linux/config.h> +#include <asm/asm-offsets.h> #include <asm-generic/vmlinux.lds.h> #undef mips /* CPP really sucks for this job */ @@ -64,10 +65,10 @@ SECTIONS we can shorten the on-disk segment size. */ .sdata : { *(.sdata) } - . = ALIGN(4096); + . = ALIGN(_PAGE_SIZE); __nosave_begin = .; .data_nosave : { *(.data.nosave) } - . = ALIGN(4096); + . = ALIGN(_PAGE_SIZE); __nosave_end = .; . = ALIGN(32); @@ -76,7 +77,7 @@ SECTIONS _edata = .; /* End of data section */ /* will be freed after init */ - . = ALIGN(4096); /* Init code and data */ + . = ALIGN(_PAGE_SIZE); /* Init code and data */ __init_begin = .; .init.text : { _sinittext = .; @@ -105,7 +106,7 @@ SECTIONS .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; SECURITY_INIT - . = ALIGN(4096); + . = ALIGN(_PAGE_SIZE); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } __initramfs_end = .; @@ -113,7 +114,7 @@ SECTIONS __per_cpu_start = .; .data.percpu : { *(.data.percpu) } __per_cpu_end = .; - . = ALIGN(4096); + . = ALIGN(_PAGE_SIZE); __init_end = .; /* freed after init ends here */ diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c index 8d7d7a454f9a..181bf68175fc 100644 --- a/arch/mips/lasat/reset.c +++ b/arch/mips/lasat/reset.c @@ -19,9 +19,12 @@ */ #include <linux/config.h> #include <linux/kernel.h> +#include <linux/pm.h> + #include <asm/reboot.h> #include <asm/system.h> #include <asm/lasat/lasat.h> + #include "picvue.h" #include "prom.h" @@ -63,5 +66,5 @@ void lasat_reboot_setup(void) { _machine_restart = lasat_machine_restart; _machine_halt = lasat_machine_halt; - _machine_power_off = lasat_machine_halt; + pm_power_off = lasat_machine_halt; } diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index dcd819d57dae..83eb08b7a072 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -134,8 +134,8 @@ void __init serial_init(void) memset(&s, 0, sizeof(s)); - s.flags = STD_COM_FLAGS; - s.iotype = SERIAL_IO_MEM; + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + s.iotype = UPIO_MEM; if (mips_machtype == MACH_LASAT_100) { s.uartclk = LASAT_BASE_BAUD_100 * 16; diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c index 46519f4331eb..c49a925d0169 100644 --- a/arch/mips/lib-32/dump_tlb.c +++ b/arch/mips/lib-32/dump_tlb.c @@ -158,29 +158,26 @@ void dump_list_process(struct task_struct *t, void *address) printk("task->mm == %8p\n", t->mm); //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); - if (addr > KSEG0) + if (addr > KSEG0) { page_dir = pgd_offset_k(0); - else if (t->mm) { - page_dir = pgd_offset(t->mm, 0); - printk("page_dir == %08x\n", (unsigned int) page_dir); - } else - printk("Current thread has no mm\n"); - - if (addr > KSEG0) pgd = pgd_offset_k(addr); - else if (t->mm) { + } else if (t->mm) { + page_dir = pgd_offset(t->mm, 0); pgd = pgd_offset(t->mm, addr); - printk("pgd == %08x, ", (unsigned int) pgd); - pud = pud_offset(pgd, addr); - printk("pud == %08x, ", (unsigned int) pud); + } else { + printk("Current thread has no mm\n"); + return; + } + printk("page_dir == %08x\n", (unsigned int) page_dir); + printk("pgd == %08x, ", (unsigned int) pgd); + pud = pud_offset(pgd, addr); + printk("pud == %08x, ", (unsigned int) pud); - pmd = pmd_offset(pud, addr); - printk("pmd == %08x, ", (unsigned int) pmd); + pmd = pmd_offset(pud, addr); + printk("pmd == %08x, ", (unsigned int) pmd); - pte = pte_offset(pmd, addr); - printk("pte == %08x, ", (unsigned int) pte); - } else - printk("Current thread has no mm\n"); + pte = pte_offset(pmd, addr); + printk("pte == %08x, ", (unsigned int) pte); page = *pte; #ifdef CONFIG_64BIT_PHYS_ADDR diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index 495c1ac94298..1c555e6c6a9f 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -48,16 +48,22 @@ ieee754dp ieee754dp_neg(ieee754dp x) CLEARCX; FLUSHXDP; + /* + * Invert the sign ALWAYS to prevent an endless recursion on + * pow() in libc. + */ + /* quick fix up */ + DPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754dp y = ieee754dp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); + DPSIGN(y) = DPSIGN(x); + return ieee754dp_nanxcpt(y, "neg"); } if (ieee754dp_isnan(x)) /* but not infinity */ return ieee754dp_nanxcpt(x, "neg", x); - - /* quick fix up */ - DPSIGN(x) ^= 1; return x; } diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index c809830dffb4..770f0f4677cd 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -48,16 +48,22 @@ ieee754sp ieee754sp_neg(ieee754sp x) CLEARCX; FLUSHXSP; + /* + * Invert the sign ALWAYS to prevent an endless recursion on + * pow() in libc. + */ + /* quick fix up */ + SPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754sp y = ieee754sp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "neg"); + SPSIGN(y) = SPSIGN(x); + return ieee754sp_nanxcpt(y, "neg"); } if (ieee754sp_isnan(x)) /* but not infinity */ return ieee754sp_nanxcpt(x, "neg", x); - - /* quick fix up */ - SPSIGN(x) ^= 1; return x; } diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index 625843b30bed..873cf3141a31 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c @@ -82,8 +82,8 @@ static void __init serial_init(void) #endif s.irq = ATLASINT_UART; s.uartclk = ATLAS_BASE_BAUD * 16; - s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - s.iotype = SERIAL_IO_PORT; + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ; + s.iotype = UPIO_PORT; s.regshift = 3; if (early_serial_setup(&s) != 0) { diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c index 9fdec743bd95..7213c395fb6b 100644 --- a/arch/mips/mips-boards/generic/reset.c +++ b/arch/mips/mips-boards/generic/reset.c @@ -23,6 +23,7 @@ * */ #include <linux/config.h> +#include <linux/pm.h> #include <asm/io.h> #include <asm/reboot.h> @@ -65,9 +66,9 @@ void mips_reboot_setup(void) _machine_restart = mips_machine_restart; _machine_halt = mips_machine_halt; #if defined(CONFIG_MIPS_ATLAS) - _machine_power_off = atlas_machine_power_off; + pm_power_off = atlas_machine_power_off; #endif #if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD) - _machine_power_off = mips_machine_halt; + pm_power_off = mips_machine_halt; #endif } diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c index f966bc161dfa..4266ce445174 100644 --- a/arch/mips/mips-boards/sead/sead_setup.c +++ b/arch/mips/mips-boards/sead/sead_setup.c @@ -71,8 +71,8 @@ static void __init serial_init(void) #endif s.irq = MIPSCPU_INT_BASE + MIPSCPU_INT_UART0; s.uartclk = SEAD_BASE_BAUD * 16; - s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - s.iotype = 0; + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ; + s.iotype = UPIO_PORT; s.regshift = 3; if (early_serial_setup(&s) != 0) { diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c index 485d5a58d9cf..a2fd62997ca3 100644 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ b/arch/mips/mips-boards/sim/sim_setup.c @@ -88,8 +88,8 @@ static void __init serial_init(void) but poll for now */ s.irq = 0; s.uartclk = BASE_BAUD * 16; - s.flags = ASYNC_BOOT_AUTOCONF | UPF_SKIP_TEST; - s.iotype = SERIAL_IO_PORT | ASYNC_SKIP_TEST; + s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + s.iotype = UPIO_PORT; s.regshift = 0; s.timeout = 4; diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 422b55fab07a..e51c38cef88e 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -464,8 +464,8 @@ static void r4k_flush_data_cache_page(unsigned long addr) } struct flush_icache_range_args { - unsigned long __user start; - unsigned long __user end; + unsigned long start; + unsigned long end; }; static inline void local_r4k_flush_icache_range(void *args) @@ -528,8 +528,7 @@ static inline void local_r4k_flush_icache_range(void *args) } } -static void r4k_flush_icache_range(unsigned long __user start, - unsigned long __user end) +static void r4k_flush_icache_range(unsigned long start, unsigned long end) { struct flush_icache_range_args args; diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 314701a66b13..591c22b080e4 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -25,8 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); -void (*flush_icache_range)(unsigned long __user start, - unsigned long __user end); +void (*flush_icache_range)(unsigned long start, unsigned long end); void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); /* MIPS specific cache operations */ @@ -53,7 +52,7 @@ EXPORT_SYMBOL(_dma_cache_inv); * We could optimize the case where the cache argument is not BCACHE but * that seems very atypical use ... */ -asmlinkage int sys_cacheflush(unsigned long __user addr, +asmlinkage int sys_cacheflush(unsigned long addr, unsigned long bytes, unsigned int cache) { if (bytes == 0) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 4ee91c9a556f..0ff9a348b843 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -24,6 +24,7 @@ #include <linux/bootmem.h> #include <linux/highmem.h> #include <linux/swap.h> +#include <linux/proc_fs.h> #include <asm/bootinfo.h> #include <asm/cachectl.h> @@ -200,6 +201,11 @@ static inline int page_is_ram(unsigned long pagenr) return 0; } +static struct kcore_list kcore_mem, kcore_vmalloc; +#ifdef CONFIG_64BIT +static struct kcore_list kcore_kseg0; +#endif + void __init mem_init(void) { unsigned long codesize, reservedpages, datasize, initsize; @@ -249,6 +255,16 @@ void __init mem_init(void) datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; +#ifdef CONFIG_64BIT + if ((unsigned long) &_text > (unsigned long) CKSEG0) + /* The -4 is a hack so that user tools don't have to handle + the overflow. */ + kclist_add(&kcore_kseg0, (void *) CKSEG0, 0x80000000 - 4); +#endif + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); + printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c index da6e1ed34db1..2292d0ec47fc 100644 --- a/arch/mips/momentum/jaguar_atx/ja-console.c +++ b/arch/mips/momentum/jaguar_atx/ja-console.c @@ -93,7 +93,7 @@ static void inline ja_console_probe(void) up.uartclk = JAGUAR_ATX_UART_CLK; up.regshift = 2; up.iotype = UPIO_MEM; - up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; up.line = 0; if (early_serial_setup(&up)) diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index bab192ddc185..301d67226d72 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -50,6 +50,7 @@ #include <linux/pci.h> #include <linux/swap.h> #include <linux/ioport.h> +#include <linux/pm.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/timex.h> @@ -365,7 +366,7 @@ void __init plat_setup(void) _machine_restart = momenco_jaguar_restart; _machine_halt = momenco_jaguar_halt; - _machine_power_off = momenco_jaguar_power_off; + pm_power_off = momenco_jaguar_power_off; /* * initrd_start = (ulong)jaguar_initrd_start; diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index c9b7ff8148ec..f95677f4f06f 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -57,6 +57,8 @@ #include <linux/timex.h> #include <linux/bootmem.h> #include <linux/mv643xx.h> +#include <linux/pm.h> + #include <asm/time.h> #include <asm/page.h> #include <asm/bootinfo.h> @@ -321,7 +323,7 @@ void __init plat_setup(void) _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; - _machine_power_off = momenco_ocelot_power_off; + pm_power_off = momenco_ocelot_power_off; /* Wired TLB entries */ setup_wired_tlb_entries(); diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 2755c1547473..15998d8a9341 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -51,8 +51,10 @@ #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/pm.h> #include <linux/timex.h> #include <linux/vmalloc.h> + #include <asm/time.h> #include <asm/bootinfo.h> #include <asm/page.h> @@ -236,7 +238,7 @@ void __init plat_setup(void) _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; - _machine_power_off = momenco_ocelot_power_off; + pm_power_off = momenco_ocelot_power_off; /* * initrd_start = (ulong)ocelot_initrd_start; diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index 6336751391c3..fed4e8eee116 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -47,8 +47,10 @@ #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/pm.h> #include <linux/timex.h> #include <linux/vmalloc.h> + #include <asm/time.h> #include <asm/bootinfo.h> #include <asm/page.h> @@ -169,7 +171,7 @@ void __init plat_setup(void) _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; - _machine_power_off = momenco_ocelot_power_off; + pm_power_off = momenco_ocelot_power_off; /* * initrd_start = (ulong)ocelot_initrd_start; diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile index 354261d37d62..0a50aad5bbe4 100644 --- a/arch/mips/oprofile/Makefile +++ b/arch/mips/oprofile/Makefile @@ -12,4 +12,5 @@ oprofile-y := $(DRIVER_OBJS) common.o oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o +oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o oprofile-$(CONFIG_CPU_RM9000) += op_model_rm9000.o diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index 53f9889b30ed..935dd851f480 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -79,6 +79,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_20KC: case CPU_24K: case CPU_25KF: + case CPU_34K: + case CPU_SB1: + case CPU_SB1A: lmodel = &op_model_mipsxx; break; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 1d1eee407faf..95d488ca0754 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -201,10 +201,21 @@ static int __init mipsxx_init(void) op_model_mipsxx.cpu_type = "mips/25K"; break; +#ifndef CONFIG_SMP + case CPU_34K: + op_model_mipsxx.cpu_type = "mips/34K"; + break; +#endif + case CPU_5KC: op_model_mipsxx.cpu_type = "mips/5K"; break; + case CPU_SB1: + case CPU_SB1A: + op_model_mipsxx.cpu_type = "mips/sb1"; + break; + default: printk(KERN_ERR "Profiling unsupported for this CPU\n"); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 741e67c9195a..16205b587338 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ obj-$(CONFIG_SGI_IP27) += pci-ip27.o obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o +obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index 909292f50d06..75a01e764898 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -17,7 +17,7 @@ #include <asm/io.h> #include <asm/gt64120.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> extern int cobalt_board_id; @@ -52,7 +52,7 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); if (lt < 64) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, @@ -69,7 +69,7 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev) * host bridge. */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); /* * The code described by the comment below has been removed diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c index c1807934768d..13de45940b19 100644 --- a/arch/mips/pci/ops-gt64111.c +++ b/arch/mips/pci/ops-gt64111.c @@ -15,7 +15,7 @@ #include <asm/io.h> #include <asm/gt64120.h> -#include <asm/cobalt/cobalt.h> +#include <asm/mach-cobalt/cobalt.h> /* * Device 31 on the GT64111 is used to generate PCI special diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index f194b4e4f86a..ca975e7d32ff 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c @@ -234,11 +234,9 @@ static int __init bcm1480_pcibios_init(void) /* turn on ExpMemEn */ cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40)); - printk("PCIFeatureCtrl = %x\n", cmdreg); WRITECFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40), cmdreg | 0x10); cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40)); - printk("PCIFeatureCtrl = %x\n", cmdreg); /* * Establish mappings in KSEG2 (kernel virtual) to PCI I/O diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c index 8aa9bd65b45e..a592260fd673 100644 --- a/arch/mips/philips/pnx8550/common/platform.c +++ b/arch/mips/philips/pnx8550/common/platform.c @@ -66,28 +66,28 @@ struct ip3106_port ip3106_ports[] = { [0] = { .port = { .type = PORT_IP3106, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void __iomem *)PNX8550_UART_PORT0, .mapbase = PNX8550_UART_PORT0, .irq = PNX8550_UART_INT(0), .uartclk = 3692300, .fifosize = 16, .ops = &ip3106_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, }, [1] = { .port = { .type = PORT_IP3106, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void __iomem *)PNX8550_UART_PORT1, .mapbase = PNX8550_UART_PORT1, .irq = PNX8550_UART_INT(1), .uartclk = 3692300, .fifosize = 16, .ops = &ip3106_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, }, diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c index ee6bf72094f6..0d8a77619391 100644 --- a/arch/mips/philips/pnx8550/common/setup.c +++ b/arch/mips/philips/pnx8550/common/setup.c @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/serial_ip3106.h> +#include <linux/pm.h> #include <asm/cpu.h> #include <asm/bootinfo.h> @@ -90,7 +91,7 @@ void __init plat_setup(void) _machine_restart = pnx8550_machine_restart; _machine_halt = pnx8550_machine_halt; - _machine_power_off = pnx8550_machine_power_off; + pm_power_off = pnx8550_machine_power_off; board_time_init = pnx8550_time_init; board_timer_setup = pnx8550_timer_setup; diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c index 555bfacf7647..165275c00cbb 100644 --- a/arch/mips/pmc-sierra/yosemite/prom.c +++ b/arch/mips/pmc-sierra/yosemite/prom.c @@ -13,6 +13,7 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/delay.h> +#include <linux/pm.h> #include <linux/smp.h> #include <asm/io.h> @@ -92,7 +93,7 @@ void __init prom_init(void) /* Callbacks for halt, restart */ _machine_restart = (void (*)(char *)) prom_exit; _machine_halt = prom_halt; - _machine_power_off = prom_halt; + pm_power_off = prom_halt; debug_vectors = cv; arcs_cmdline[0] = '\0'; diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 059755b5ed57..8bce711575de 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -185,7 +185,7 @@ static void __init py_uart_setup(void) up.uartclk = TITAN_UART_CLK; up.regshift = 0; up.iotype = UPIO_MEM; - up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; up.line = 0; if (early_serial_setup(&up)) diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 214ffd2e98a3..92a3b3c15ed3 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c @@ -3,8 +3,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1997, 1998, 2001, 2003 by Ralf Baechle + * Copyright (C) 1997, 1998, 2001, 03, 05, 06 by Ralf Baechle */ +#include <linux/linkage.h> #include <linux/init.h> #include <linux/ds1286.h> #include <linux/module.h> @@ -12,6 +13,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/notifier.h> +#include <linux/pm.h> #include <linux/timer.h> #include <asm/io.h> @@ -41,28 +43,10 @@ static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; #define MACHINE_PANICED 1 #define MACHINE_SHUTTING_DOWN 2 -static int machine_state = 0; -static void sgi_machine_restart(char *command) __attribute__((noreturn)); -static void sgi_machine_halt(void) __attribute__((noreturn)); -static void sgi_machine_power_off(void) __attribute__((noreturn)); +static int machine_state; -static void sgi_machine_restart(char *command) -{ - if (machine_state & MACHINE_SHUTTING_DOWN) - sgi_machine_power_off(); - sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT; - while (1); -} - -static void sgi_machine_halt(void) -{ - if (machine_state & MACHINE_SHUTTING_DOWN) - sgi_machine_power_off(); - ArcEnterInteractiveMode(); -} - -static void sgi_machine_power_off(void) +static void ATTRIB_NORET sgi_machine_power_off(void) { unsigned int tmp; @@ -84,6 +68,21 @@ static void sgi_machine_power_off(void) } } +static void ATTRIB_NORET sgi_machine_restart(char *command) +{ + if (machine_state & MACHINE_SHUTTING_DOWN) + sgi_machine_power_off(); + sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT; + while (1); +} + +static void ATTRIB_NORET sgi_machine_halt(void) +{ + if (machine_state & MACHINE_SHUTTING_DOWN) + sgi_machine_power_off(); + ArcEnterInteractiveMode(); +} + static void power_timeout(unsigned long data) { sgi_machine_power_off(); @@ -95,7 +94,7 @@ static void blink_timeout(unsigned long data) sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF); sgioc->reset = sgi_ioc_reset; - mod_timer(&blink_timer, jiffies+data); + mod_timer(&blink_timer, jiffies + data); } static void debounce(unsigned long data) @@ -103,7 +102,7 @@ static void debounce(unsigned long data) del_timer(&debounce_timer); if (sgint->istat1 & SGINT_ISTAT1_PWR) { /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 5; /* 0.05s */ + debounce_timer.expires = jiffies + (HZ / 20); /* 0.05s */ add_timer(&debounce_timer); sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR | @@ -151,7 +150,7 @@ static inline void volume_up_button(unsigned long data) indy_volume_button(1); if (sgint->istat1 & SGINT_ISTAT1_PWR) { - volume_timer.expires = jiffies + 1; + volume_timer.expires = jiffies + (HZ / 100); add_timer(&volume_timer); } } @@ -164,7 +163,7 @@ static inline void volume_down_button(unsigned long data) indy_volume_button(-1); if (sgint->istat1 & SGINT_ISTAT1_PWR) { - volume_timer.expires = jiffies + 1; + volume_timer.expires = jiffies + (HZ / 100); add_timer(&volume_timer); } } @@ -199,14 +198,14 @@ static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs) if (!(buttons & SGIOC_PANEL_VOLUPINTR)) { init_timer(&volume_timer); volume_timer.function = volume_up_button; - volume_timer.expires = jiffies + 1; + volume_timer.expires = jiffies + (HZ / 100); add_timer(&volume_timer); } /* Volume down button was pressed */ if (!(buttons & SGIOC_PANEL_VOLDNINTR)) { init_timer(&volume_timer); volume_timer.function = volume_down_button; - volume_timer.expires = jiffies + 1; + volume_timer.expires = jiffies + (HZ / 100); add_timer(&volume_timer); } @@ -234,7 +233,7 @@ static int __init reboot_setup(void) { _machine_restart = sgi_machine_restart; _machine_halt = sgi_machine_halt; - _machine_power_off = sgi_machine_power_off; + pm_power_off = sgi_machine_power_off; request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); init_timer(&blink_timer); diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c index 5e59b4c8876b..7018e1833e85 100644 --- a/arch/mips/sgi-ip22/ip22-setup.c +++ b/arch/mips/sgi-ip22/ip22-setup.c @@ -56,6 +56,7 @@ extern void ip22_time_init(void) __init; void __init plat_setup(void) { char *ctype; + char *cserial; board_be_init = ip22_be_init; ip22_time_init(); @@ -81,9 +82,14 @@ void __init plat_setup(void) /* ARCS console environment variable is set to "g?" for * graphics console, it is set to "d" for the first serial * line and "d2" for the second serial line. + * + * Need to check if the case is 'g' but no keyboard: + * (ConsoleIn/Out = serial) */ ctype = ArcGetEnvironmentVariable("console"); - if (ctype && *ctype == 'd') { + cserial = ArcGetEnvironmentVariable("ConsoleOut"); + + if ((ctype && *ctype == 'd') || (cserial && *cserial == 's')) { static char options[8]; char *baud = ArcGetEnvironmentVariable("dbaud"); if (baud) @@ -91,7 +97,7 @@ void __init plat_setup(void) add_preferred_console("ttyS", *(ctype + 1) == '2' ? 1 : 0, baud ? options : NULL); } else if (!ctype || *ctype != 'g') { - /* Use ARC if we don't want serial ('d') or Newport ('g'). */ + /* Use ARC if we don't want serial ('d') or graphics ('g'). */ prom_flags |= PROM_FLAG_USE_AS_CONSOLE; add_preferred_console("arc", 0, NULL); } diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c index 2e16be94c78b..4322db57d3c1 100644 --- a/arch/mips/sgi-ip27/ip27-reset.c +++ b/arch/mips/sgi-ip27/ip27-reset.c @@ -5,7 +5,7 @@ * * Reset an IP27. * - * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1997, 1998, 1999, 2000, 06 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include <linux/config.h> @@ -15,6 +15,7 @@ #include <linux/smp.h> #include <linux/mmzone.h> #include <linux/nodemask.h> +#include <linux/pm.h> #include <asm/io.h> #include <asm/irq.h> @@ -77,5 +78,5 @@ void ip27_reboot_setup(void) { _machine_restart = ip27_machine_restart; _machine_halt = ip27_machine_halt; - _machine_power_off = ip27_machine_power_off; + pm_power_off = ip27_machine_power_off; } diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 88e1f52059ff..0c948008b023 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/ds17287rtc.h> #include <linux/interrupt.h> +#include <linux/pm.h> #include <asm/addrspace.h> #include <asm/irq.h> @@ -188,7 +189,7 @@ static __init int ip32_reboot_setup(void) _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; - _machine_power_off = ip32_machine_power_off; + pm_power_off = ip32_machine_power_off; init_timer(&blink_timer); blink_timer.function = blink_timeout; diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index d10a269aeae1..2c38770b1e1b 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -66,11 +66,6 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str) #include <linux/tty.h> #include <linux/serial.h> #include <linux/serial_core.h> -extern int early_serial_setup(struct uart_port *port); - -#define STD_COM_FLAGS (ASYNC_SKIP_TEST) -#define BASE_BAUD (1843200 / 16) - #endif /* CONFIG_SERIAL_8250 */ /* An arbitrary time; this can be decreased if reliability looks good */ @@ -110,8 +105,8 @@ void __init plat_setup(void) o2_serial[0].type = PORT_16550A; o2_serial[0].line = 0; o2_serial[0].irq = MACEISA_SERIAL1_IRQ; - o2_serial[0].flags = STD_COM_FLAGS; - o2_serial[0].uartclk = BASE_BAUD * 16; + o2_serial[0].flags = UPF_SKIP_TEST; + o2_serial[0].uartclk = 1843200; o2_serial[0].iotype = UPIO_MEM; o2_serial[0].membase = (char *)&mace->isa.serial1; o2_serial[0].fifosize = 14; @@ -121,8 +116,8 @@ void __init plat_setup(void) o2_serial[1].type = PORT_16550A; o2_serial[1].line = 1; o2_serial[1].irq = MACEISA_SERIAL2_IRQ; - o2_serial[1].flags = STD_COM_FLAGS; - o2_serial[1].uartclk = BASE_BAUD * 16; + o2_serial[1].flags = UPF_SKIP_TEST; + o2_serial[1].uartclk = 1843200; o2_serial[1].iotype = UPIO_MEM; o2_serial[1].membase = (char *)&mace->isa.serial2; o2_serial[1].fifosize = 14; diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c index 7a2c7a8510d4..ea308029450e 100644 --- a/arch/mips/sibyte/cfe/setup.c +++ b/arch/mips/sibyte/cfe/setup.c @@ -23,6 +23,7 @@ #include <linux/mm.h> #include <linux/blkdev.h> #include <linux/bootmem.h> +#include <linux/pm.h> #include <linux/smp.h> #include <asm/bootinfo.h> @@ -248,7 +249,7 @@ void __init prom_init(void) _machine_restart = cfe_linux_restart; _machine_halt = cfe_linux_halt; - _machine_power_off = cfe_linux_halt; + pm_power_off = cfe_linux_halt; /* * Check if a loader was used; if NOT, the 4 arguments are diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c index de62ab0f55a2..742043f8d755 100644 --- a/arch/mips/sibyte/sb1250/prom.c +++ b/arch/mips/sibyte/sb1250/prom.c @@ -24,6 +24,7 @@ #include <linux/bootmem.h> #include <linux/smp.h> #include <linux/initrd.h> +#include <linux/pm.h> #include <asm/bootinfo.h> #include <asm/reboot.h> @@ -79,7 +80,7 @@ void __init prom_init(void) { _machine_restart = (void (*)(char *))prom_linux_exit; _machine_halt = prom_linux_exit; - _machine_power_off = prom_linux_exit; + pm_power_off = prom_linux_exit; strcpy(arcs_cmdline, "root=/dev/ram0 "); diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c index df2e266c700c..fde4751c84fe 100644 --- a/arch/mips/sibyte/sb1250/setup.c +++ b/arch/mips/sibyte/sb1250/setup.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/config.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/reboot.h> #include <linux/string.h> @@ -42,7 +43,7 @@ static inline int setup_bcm112x(void); /* Setup code likely to be common to all SiByte platforms */ -static inline int sys_rev_decode(void) +static int __init sys_rev_decode(void) { int ret = 0; @@ -74,7 +75,7 @@ static inline int sys_rev_decode(void) return ret; } -static inline int setup_bcm1250(void) +static int __init setup_bcm1250(void) { int ret = 0; @@ -120,7 +121,7 @@ static inline int setup_bcm1250(void) return ret; } -static inline int setup_bcm112x(void) +static int __init setup_bcm112x(void) { int ret = 0; @@ -146,7 +147,7 @@ static inline int setup_bcm112x(void) return ret; } -void sb1250_setup(void) +void __init sb1250_setup(void) { uint64_t sys_rev; int plldiv; @@ -169,31 +170,42 @@ void sb1250_setup(void) soc_str, pass_str, zbbus_mhz * 2, sb1_pass); prom_printf("Board type: %s\n", get_system_type()); - switch(war_pass) { + switch (war_pass) { case K_SYS_REVISION_BCM1250_PASS1: #ifndef CONFIG_SB1_PASS_1_WORKAROUNDS - prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); + prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, " + "and the kernel doesn't have the proper " + "workarounds compiled in. @@@@\n"); bad_config = 1; #endif break; case K_SYS_REVISION_BCM1250_PASS2: /* Pass 2 - easiest as default for now - so many numbers */ -#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) - prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); +#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \ + !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) + prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the " + "kernel doesn't have the proper workarounds " + "compiled in. @@@@\n"); bad_config = 1; #endif #ifdef CONFIG_CPU_HAS_PREFETCH - prom_printf("@@@@ Prefetches may be enabled in this kernel, but are buggy on this board. @@@@\n"); + prom_printf("@@@@ Prefetches may be enabled in this kernel, " + "but are buggy on this board. @@@@\n"); bad_config = 1; #endif break; case K_SYS_REVISION_BCM1250_PASS2_2: #ifndef CONFIG_SB1_PASS_2_WORKAROUNDS - prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); + prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the " + "kernel doesn't have the proper workarounds " + "compiled in. @@@@\n"); bad_config = 1; #endif -#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || !defined(CONFIG_CPU_HAS_PREFETCH) - prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is conservatively configured for an 'A' stepping. @@@@\n"); +#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \ + !defined(CONFIG_CPU_HAS_PREFETCH) + prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is " + "conservatively configured for an 'A' stepping. " + "@@@@\n"); #endif break; default: diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index 262c85680709..1141fcd13a59 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 97, 98, 2000, 03, 04 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org) */ #include <linux/config.h> #include <linux/eisa.h> @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/mc146818rtc.h> +#include <linux/pm.h> #include <linux/pci.h> #include <linux/console.h> #include <linux/fb.h> @@ -189,7 +190,7 @@ void __init plat_setup(void) _machine_restart = sni_machine_restart; _machine_halt = sni_machine_halt; - _machine_power_off = sni_machine_power_off; + pm_power_off = sni_machine_power_off; sni_display_setup(); diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c index e4d095d3e192..e19e2be70f76 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c @@ -60,7 +60,6 @@ void __init prom_init_cmdline(void) void __init prom_init(void) { - const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES; extern int tx4927_get_mem_size(void); extern char* toshiba_name; int msize; @@ -69,12 +68,13 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_TOSHIBA; - if ((read_c0_prid() & 0xff) == PRID_REV_TX4927) + if ((read_c0_prid() & 0xff) == PRID_REV_TX4927) { mips_machtype = MACH_TOSHIBA_RBTX4927; - else + toshiba_name = "TX4927"; + } else { mips_machtype = MACH_TOSHIBA_RBTX4937; - - toshiba_name = toshiba_name_list[mips_machtype]; + toshiba_name = "TX4937"; + } msize = tx4927_get_mem_size(); add_memory_region(0, msize << 20, BOOT_MEM_RAM); diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index 990fcb294bab..2ad6401d2af4 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -53,6 +53,8 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/timex.h> +#include <linux/pm.h> + #include <asm/bootinfo.h> #include <asm/page.h> #include <asm/io.h> @@ -537,19 +539,10 @@ void tx4927_pci_setup(void) TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "0x%08lx=mips_io_port_base", mips_io_port_base); - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, - "setup pci_io_resource to 0x%08lx 0x%08lx\n", - pci_io_resource.start, - pci_io_resource.end); - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, - "setup pci_mem_resource to 0x%08lx 0x%08lx\n", - pci_mem_resource.start, - pci_mem_resource.end); - if (!called) { printk - ("TX4927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n", + ("%s PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n", + toshiba_name, (unsigned short) (tx4927_pcicptr->pciid >> 16), (unsigned short) (tx4927_pcicptr->pciid & 0xffff), (unsigned short) (tx4927_pcicptr->pciccrev & 0xff), @@ -562,21 +555,52 @@ void tx4927_pci_setup(void) (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) ? " PCI66" : ""); if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) { int pciclk = 0; - switch ((unsigned long) tx4927_ccfgptr-> - ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { - case TX4927_CCFG_PCIDIVMODE_2_5: - pciclk = tx4927_cpu_clock * 2 / 5; - break; - case TX4927_CCFG_PCIDIVMODE_3: - pciclk = tx4927_cpu_clock / 3; - break; - case TX4927_CCFG_PCIDIVMODE_5: - pciclk = tx4927_cpu_clock / 5; - break; - case TX4927_CCFG_PCIDIVMODE_6: - pciclk = tx4927_cpu_clock / 6; - break; - } + if (mips_machtype == MACH_TOSHIBA_RBTX4937) + switch ((unsigned long) tx4927_ccfgptr-> + ccfg & TX4937_CCFG_PCIDIVMODE_MASK) { + case TX4937_CCFG_PCIDIVMODE_4: + pciclk = tx4927_cpu_clock / 4; + break; + case TX4937_CCFG_PCIDIVMODE_4_5: + pciclk = tx4927_cpu_clock * 2 / 9; + break; + case TX4937_CCFG_PCIDIVMODE_5: + pciclk = tx4927_cpu_clock / 5; + break; + case TX4937_CCFG_PCIDIVMODE_5_5: + pciclk = tx4927_cpu_clock * 2 / 11; + break; + case TX4937_CCFG_PCIDIVMODE_8: + pciclk = tx4927_cpu_clock / 8; + break; + case TX4937_CCFG_PCIDIVMODE_9: + pciclk = tx4927_cpu_clock / 9; + break; + case TX4937_CCFG_PCIDIVMODE_10: + pciclk = tx4927_cpu_clock / 10; + break; + case TX4937_CCFG_PCIDIVMODE_11: + pciclk = tx4927_cpu_clock / 11; + break; + } + + else + switch ((unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { + case TX4927_CCFG_PCIDIVMODE_2_5: + pciclk = tx4927_cpu_clock * 2 / 5; + break; + case TX4927_CCFG_PCIDIVMODE_3: + pciclk = tx4927_cpu_clock / 3; + break; + case TX4927_CCFG_PCIDIVMODE_5: + pciclk = tx4927_cpu_clock / 5; + break; + case TX4927_CCFG_PCIDIVMODE_6: + pciclk = tx4927_cpu_clock / 6; + break; + } + printk("Internal(%dMHz)", pciclk / 1000000); } else { int pciclk = 0; @@ -814,24 +838,40 @@ void __init toshiba_rbtx4927_setup(void) ":ResetRoutines\n"); _machine_restart = toshiba_rbtx4927_restart; _machine_halt = toshiba_rbtx4927_halt; - _machine_power_off = toshiba_rbtx4927_power_off; + pm_power_off = toshiba_rbtx4927_power_off; #ifdef CONFIG_PCI /* PCIC */ /* * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz. - * PCIDIVMODE[12:11]'s initial value are given by S9[4:3] (ON:0, OFF:1). + * + * For TX4927: + * PCIDIVMODE[12:11]'s initial value is given by S9[4:3] (ON:0, OFF:1). * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5) * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3) * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5) * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6) * i.e. S9[3]: ON (83MHz), OFF (100MHz) + * + * For TX4937: + * PCIDIVMODE[12:11]'s initial value is given by S1[5:4] (ON:0, OFF:1) + * PCIDIVMODE[10] is 0. + * CPU 266MHz: PCI 33MHz : PCIDIVMODE: 000 (1/8) + * CPU 266MHz: PCI 66MHz : PCIDIVMODE: 001 (1/4) + * CPU 300MHz: PCI 33MHz : PCIDIVMODE: 010 (1/9) + * CPU 300MHz: PCI 66MHz : PCIDIVMODE: 011 (1/4.5) + * CPU 333MHz: PCI 33MHz : PCIDIVMODE: 100 (1/10) + * CPU 333MHz: PCI 66MHz : PCIDIVMODE: 101 (1/5) + * */ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, - "ccfg is %lx, DIV is %x\n", - (unsigned long) tx4927_ccfgptr-> - ccfg, TX4927_CCFG_PCIDIVMODE_MASK); + "ccfg is %lx, PCIDIVMODE is %x\n", + (unsigned long) tx4927_ccfgptr->ccfg, + (unsigned long) tx4927_ccfgptr->ccfg & + (mips_machtype == MACH_TOSHIBA_RBTX4937 ? + TX4937_CCFG_PCIDIVMODE_MASK : + TX4927_CCFG_PCIDIVMODE_MASK)); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, "PCI66 mode is %lx, PCI mode is %lx, pci arb is %lx\n", @@ -842,20 +882,30 @@ void __init toshiba_rbtx4927_setup(void) (unsigned long) tx4927_ccfgptr-> ccfg & TX4927_CCFG_PCIXARB); - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, - "PCIDIVMODE is %lx\n", - (unsigned long) tx4927_ccfgptr-> - ccfg & TX4927_CCFG_PCIDIVMODE_MASK); - - switch ((unsigned long) tx4927_ccfgptr-> - ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { - case TX4927_CCFG_PCIDIVMODE_2_5: - case TX4927_CCFG_PCIDIVMODE_5: - tx4927_cpu_clock = 166000000; /* 166MHz */ - break; - default: - tx4927_cpu_clock = 200000000; /* 200MHz */ - } + if (mips_machtype == MACH_TOSHIBA_RBTX4937) + switch ((unsigned long)tx4927_ccfgptr-> + ccfg & TX4937_CCFG_PCIDIVMODE_MASK) { + case TX4937_CCFG_PCIDIVMODE_8: + case TX4937_CCFG_PCIDIVMODE_4: + tx4927_cpu_clock = 266666666; /* 266MHz */ + break; + case TX4937_CCFG_PCIDIVMODE_9: + case TX4937_CCFG_PCIDIVMODE_4_5: + tx4927_cpu_clock = 300000000; /* 300MHz */ + break; + default: + tx4927_cpu_clock = 333333333; /* 333MHz */ + } + else + switch ((unsigned long)tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { + case TX4927_CCFG_PCIDIVMODE_2_5: + case TX4927_CCFG_PCIDIVMODE_5: + tx4927_cpu_clock = 166666666; /* 166MHz */ + break; + default: + tx4927_cpu_clock = 200000000; /* 200MHz */ + } /* CCFG */ /* enable Timeout BusError */ diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 9f1dcc8ca5a3..5c7ace982a49 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -20,6 +20,8 @@ #include <linux/interrupt.h> #include <linux/console.h> #include <linux/pci.h> +#include <linux/pm.h> + #include <asm/wbflush.h> #include <asm/reboot.h> #include <asm/irq.h> @@ -1003,7 +1005,7 @@ void __init toshiba_rbtx4938_setup(void) _machine_restart = rbtx4938_machine_restart; _machine_halt = rbtx4938_machine_halt; - _machine_power_off = rbtx4938_machine_power_off; + pm_power_off = rbtx4938_machine_power_off; *rbtx4938_led_ptr = 0xff; printk("RBTX4938 --- FPGA(Rev %02x)", *rbtx4938_fpga_rev_ptr); diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index 02bf4f7d06ba..5e469796413f 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/kernel.h> +#include <linux/pm.h> #include <linux/smp.h> #include <linux/types.h> @@ -114,7 +115,7 @@ static int __init vr41xx_pmu_init(void) _machine_restart = vr41xx_restart; _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; + pm_power_off = vr41xx_power_off; return 0; } diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index e77a06e9621e..7c914a4c67c3 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -149,14 +149,20 @@ config HOTPLUG_CPU default y if SMP select HOTPLUG +config ARCH_SELECT_MEMORY_MODEL + def_bool y + depends on 64BIT + config ARCH_DISCONTIGMEM_ENABLE - bool "Discontiguous memory support (EXPERIMENTAL)" - depends on 64BIT && EXPERIMENTAL - help - Say Y to support efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See <file:Documentation/vm/numa> for more. + def_bool y + depends on 64BIT + +config ARCH_FLATMEM_ENABLE + def_bool y + +config ARCH_DISCONTIGMEM_DEFAULT + def_bool y + depends on ARCH_DISCONTIGMEM_ENABLE source "kernel/Kconfig.hz" source "mm/Kconfig" diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index 8caaed187a1f..9166bd117267 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -11,4 +11,14 @@ config DEBUG_RWLOCK too many attempts. If you suspect a rwlock problem or a kernel hacker asks for this option then say Y. Otherwise say N. +config DEBUG_RODATA + bool "Write protect kernel read-only data structures" + depends on DEBUG_KERNEL + help + Mark the kernel read-only data as write-protected in the pagetables, + in order to catch accidental (and incorrect) writes to such const + data. This option may have a slight performance impact because a + portion of the kernel code won't be covered by a TLB anymore. + If in doubt, say "N". + endmenu diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index 955ef5084f3e..959ad3c4e372 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -602,6 +602,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig index 8819e7e6ae3f..37e98241ce4b 100644 --- a/arch/parisc/configs/b180_defconfig +++ b/arch/parisc/configs/b180_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc5-pa1 -# Fri Oct 21 23:06:10 2005 +# Linux kernel version: 2.6.16-rc1-pa0 +# Tue Jan 17 08:21:01 2006 # CONFIG_PARISC=y CONFIG_MMU=y @@ -29,8 +29,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" @@ -38,8 +36,10 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -48,8 +48,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -57,10 +59,28 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set # +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# # Processor type and features # # CONFIG_PA7000 is not set @@ -77,6 +97,7 @@ CONFIG_HZ=250 CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_PREEMPT is not set # CONFIG_HPUX is not set @@ -84,8 +105,8 @@ CONFIG_FLAT_NODE_MEM_MAP=y # Bus options (PCI, PCMCIA, EISA, GSC, ISA) # CONFIG_GSC=y -# CONFIG_HPPB is not set -# CONFIG_IOMMU_CCIO is not set +CONFIG_HPPB=y +CONFIG_IOMMU_CCIO=y CONFIG_GSC_LASI=y CONFIG_GSC_WAX=y CONFIG_EISA=y @@ -165,8 +186,11 @@ CONFIG_IPV6=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -205,6 +229,7 @@ CONFIG_STANDALONE=y CONFIG_PARPORT=y CONFIG_PARPORT_PC=y # CONFIG_PARPORT_SERIAL is not set +CONFIG_PARPORT_NOT_PC=y CONFIG_PARPORT_GSC=y # CONFIG_PARPORT_1284 is not set @@ -230,14 +255,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_ATA_OVER_ETH=y # @@ -281,6 +298,7 @@ CONFIG_SCSI_SPI_ATTRS=y # # SCSI low-level drivers # +# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -313,21 +331,19 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_ZALON is not set +CONFIG_SCSI_ZALON=y +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=40 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set @@ -397,7 +413,7 @@ CONFIG_NETDEVICES=y # CONFIG_NET_ETHERNET=y # CONFIG_MII is not set -# CONFIG_LASI_82596 is not set +CONFIG_LASI_82596=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set @@ -464,6 +480,7 @@ CONFIG_NET_RADIO=y # Wireless 802.11b ISA/PCI cards support # # CONFIG_HERMES is not set +# CONFIG_ATMEL is not set # # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support @@ -527,7 +544,7 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_HIL_OLD is not set -# CONFIG_KEYBOARD_HIL is not set +CONFIG_KEYBOARD_HIL=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set @@ -535,7 +552,7 @@ CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_LOGIBM is not set # CONFIG_MOUSE_PC110PAD is not set # CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_HIL is not set +CONFIG_MOUSE_HIL=y # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y @@ -549,7 +566,8 @@ CONFIG_SERIO=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_PARKBD is not set CONFIG_SERIO_GSCPS2=y -# CONFIG_HP_SDC is not set +CONFIG_HP_SDC=y +CONFIG_HIL_MLC=y # CONFIG_SERIO_PCIPS2 is not set CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set @@ -569,6 +587,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=13 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y @@ -582,11 +601,10 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y # # Non-8250 serial port support # -# CONFIG_SERIAL_MUX is not set -# CONFIG_PDC_CONSOLE is not set +CONFIG_SERIAL_MUX=y +CONFIG_SERIAL_MUX_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -626,6 +644,12 @@ CONFIG_GEN_RTC=y # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -661,7 +685,6 @@ CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_SOFT_CURSOR=y # CONFIG_FB_MACMODES is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set @@ -671,6 +694,7 @@ CONFIG_FB_SOFT_CURSOR=y # CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set CONFIG_FB_STI=y +# CONFIG_FB_S1D13XXX is not set # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set @@ -683,9 +707,7 @@ CONFIG_FB_STI=y # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set -# CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # @@ -695,6 +717,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=160 CONFIG_DUMMY_CONSOLE_ROWS=64 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_STI_CONSOLE=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y @@ -713,7 +736,85 @@ CONFIG_LOGO_PARISC_CLUT224=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_SEQUENCER=y +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# PCI devices +# +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# GSC devices +# +CONFIG_SND_HARMONY=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set # # USB support @@ -723,6 +824,10 @@ CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_USB is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set @@ -877,18 +982,23 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_IOREMAP is not set # CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_RODATA is not set # # Security options diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index 9d86b6b1ebd1..0b1c8c1fa8a3 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -626,6 +626,7 @@ CONFIG_ACENIC=m # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S index fa9bf38787e7..31c8cccfba31 100644 --- a/arch/parisc/hpux/entry_hpux.S +++ b/arch/parisc/hpux/entry_hpux.S @@ -22,10 +22,9 @@ #include <linux/linkage.h> #include <asm/unistd.h> - .text - #define ENTRY_NAME(_name_) .word _name_ + .section .rodata,"a" .align 4 .export hpux_call_table .import hpux_unimplemented_wrapper diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 29b4d61898f2..05273ccced0e 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -468,19 +468,23 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2) if ( opcode == 1 ) { /* GETFSIND */ len = strlen_user((char *)arg1); printk(KERN_DEBUG "len of arg1 = %d\n", len); - - fsname = (char *) kmalloc(len+1, GFP_KERNEL); + if (len == 0) + return 0; + fsname = (char *) kmalloc(len, GFP_KERNEL); if ( !fsname ) { printk(KERN_DEBUG "failed to kmalloc fsname\n"); return 0; } - if ( copy_from_user(fsname, (char *)arg1, len+1) ) { + if ( copy_from_user(fsname, (char *)arg1, len) ) { printk(KERN_DEBUG "failed to copy_from_user fsname\n"); kfree(fsname); return 0; } + /* String could be altered by userspace after strlen_user() */ + fsname[len] = '\0'; + printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname); if ( !strcmp(fsname, "hfs") ) { fstype = 0; diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 2d804e2d16d1..3d569a485a1a 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -408,11 +408,10 @@ static void setup_bus_id(struct parisc_device *padev) struct parisc_device * create_tree_node(char id, struct device *parent) { - struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL); + struct parisc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(*dev)); dev->hw_path = id; dev->id.hw_type = HPHW_FAULTY; diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index f40a777dd388..1d00c365f2b1 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -48,9 +48,6 @@ EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strpbrk); -#include <linux/pm.h> -EXPORT_SYMBOL(pm_power_off); - #include <asm/atomic.h> EXPORT_SYMBOL(__xchg8); EXPORT_SYMBOL(__xchg32); diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 88cba49c5301..79c7db2705fd 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -47,18 +47,17 @@ * this makes the boot time much longer than necessary. * 20ms seems to work for all the HP PCI implementations to date. * - * XXX: turn into a #defined constant in <asm/pci.h> ? + * #define pci_post_reset_delay 50 */ -int pci_post_reset_delay = 50; -struct pci_port_ops *pci_port; -struct pci_bios_ops *pci_bios; +struct pci_port_ops *pci_port __read_mostly; +struct pci_bios_ops *pci_bios __read_mostly; -int pci_hba_count = 0; +static int pci_hba_count __read_mostly; /* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */ #define PCI_HBA_MAX 32 -struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; +static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __read_mostly; /******************************************************************** @@ -259,8 +258,10 @@ void __devinit pcibios_resource_to_bus(struct pci_dev *dev, void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, struct pci_bus_region *region) { +#ifdef CONFIG_64BIT struct pci_bus *bus = dev->bus; struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data); +#endif if (res->flags & IORESOURCE_MEM) { res->start = PCI_HOST_ADDR(hba, region->start); diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 11d406cd0b3e..53f861c82f93 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -68,20 +68,20 @@ struct rdr_tbl_ent { }; static int perf_processor_interface __read_mostly = UNKNOWN_INTF; -static int perf_enabled __read_mostly = 0; +static int perf_enabled __read_mostly; static spinlock_t perf_lock; -struct parisc_device *cpu_device __read_mostly = NULL; +struct parisc_device *cpu_device __read_mostly; /* RDRs to write for PCX-W */ -static int perf_rdrs_W[] = +static const int perf_rdrs_W[] = { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; /* RDRs to write for PCX-U */ -static int perf_rdrs_U[] = +static const int perf_rdrs_U[] = { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; /* RDR register descriptions for PCX-W */ -static struct rdr_tbl_ent perf_rdr_tbl_W[] = { +static const struct rdr_tbl_ent perf_rdr_tbl_W[] = { { 19, 1, 8 }, /* RDR 0 */ { 16, 1, 16 }, /* RDR 1 */ { 72, 2, 0 }, /* RDR 2 */ @@ -117,7 +117,7 @@ static struct rdr_tbl_ent perf_rdr_tbl_W[] = { }; /* RDR register descriptions for PCX-U */ -static struct rdr_tbl_ent perf_rdr_tbl_U[] = { +static const struct rdr_tbl_ent perf_rdr_tbl_U[] = { { 19, 1, 8 }, /* RDR 0 */ { 32, 1, 16 }, /* RDR 1 */ { 20, 1, 0 }, /* RDR 2 */ @@ -156,7 +156,7 @@ static struct rdr_tbl_ent perf_rdr_tbl_U[] = { * A non-zero write_control in the above tables is a byte offset into * this array. */ -static uint64_t perf_bitmasks[] = { +static const uint64_t perf_bitmasks[] = { 0x0000000000000000ul, /* first dbl word must be zero */ 0xfdffe00000000000ul, /* RDR0 bitmask */ 0x003f000000000000ul, /* RDR1 bitmask */ @@ -173,7 +173,7 @@ static uint64_t perf_bitmasks[] = { * Write control bitmasks for Pa-8700 processor given * somethings have changed slightly. */ -static uint64_t perf_bitmasks_piranha[] = { +static const uint64_t perf_bitmasks_piranha[] = { 0x0000000000000000ul, /* first dbl word must be zero */ 0xfdffe00000000000ul, /* RDR0 bitmask */ 0x003f000000000000ul, /* RDR1 bitmask */ @@ -186,7 +186,7 @@ static uint64_t perf_bitmasks_piranha[] = { 0xfffc000000000000ul }; -static uint64_t *bitmask_array; /* array of bitmasks to use */ +static const uint64_t *bitmask_array; /* array of bitmasks to use */ /****************************************************************************** * Function Prototypes @@ -200,7 +200,7 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static void perf_start_counters(void); static int perf_stop_counters(uint32_t *raddr); -static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num); +static const struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num); static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer); static int perf_rdr_clear(uint32_t rdr_num); static int perf_write_image(uint64_t *memaddr); @@ -444,7 +444,6 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) uint32_t raddr[4]; int error = 0; - lock_kernel(); switch (cmd) { case PA_PERF_ON: @@ -477,8 +476,6 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) error = -ENOTTY; } - unlock_kernel(); - return error; } @@ -655,7 +652,7 @@ static int perf_stop_counters(uint32_t *raddr) * Retrieve a pointer to the description of what this * RDR contains. */ -static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num) +static const struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num) { if (perf_processor_interface == ONYX_INTF) { return &perf_rdr_tbl_U[rdr_num]; @@ -673,7 +670,7 @@ static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) { uint64_t data, data_mask = 0; uint32_t width, xbits, i; - struct rdr_tbl_ent *tentry; + const struct rdr_tbl_ent *tentry; tentry = perf_rdr_get_entry(rdr_num); if ((width = tentry->width) == 0) @@ -721,7 +718,7 @@ static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) */ static int perf_rdr_clear(uint32_t rdr_num) { - struct rdr_tbl_ent *tentry; + const struct rdr_tbl_ent *tentry; int32_t i; tentry = perf_rdr_get_entry(rdr_num); @@ -753,10 +750,11 @@ static int perf_write_image(uint64_t *memaddr) uint64_t buffer[MAX_RDR_WORDS]; uint64_t *bptr; uint32_t dwords; - uint32_t *intrigue_rdr; - uint64_t *intrigue_bitmask, tmp64; + const uint32_t *intrigue_rdr; + const uint64_t *intrigue_bitmask; + uint64_t tmp64; void __iomem *runway; - struct rdr_tbl_ent *tentry; + const struct rdr_tbl_ent *tentry; int i; /* Clear out counters */ @@ -830,7 +828,7 @@ static int perf_write_image(uint64_t *memaddr) */ static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer) { - struct rdr_tbl_ent *tentry; + const struct rdr_tbl_ent *tentry; int32_t i; printk("perf_rdr_write\n"); diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h index d9562fe3f75c..7fef9644df47 100644 --- a/arch/parisc/kernel/perf_images.h +++ b/arch/parisc/kernel/perf_images.h @@ -25,7 +25,7 @@ #define PCXU_IMAGE_SIZE 584 -static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = { +static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = { /* * CPI: * @@ -2093,7 +2093,7 @@ static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = { }; #define PCXW_IMAGE_SIZE 576 -static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = { +static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = { /* * CPI: FROM CPI.IDF (Image 0) * diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 5da41677e70b..e8dea4177113 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -54,27 +54,6 @@ #include <asm/uaccess.h> #include <asm/unwind.h> -static int hlt_counter __read_mostly; - -/* - * Power off function, if any - */ -void (*pm_power_off)(void); - -void disable_hlt(void) -{ - hlt_counter++; -} - -EXPORT_SYMBOL(disable_hlt); - -void enable_hlt(void) -{ - hlt_counter--; -} - -EXPORT_SYMBOL(enable_hlt); - void default_idle(void) { barrier(); @@ -102,12 +81,7 @@ void cpu_idle(void) } -#ifdef __LP64__ -#define COMMAND_GLOBAL 0xfffffffffffe0030UL -#else -#define COMMAND_GLOBAL 0xfffe0030 -#endif - +#define COMMAND_GLOBAL F_EXTEND(0xfffe0030) #define CMD_RESET 5 /* reset any module */ /* @@ -162,6 +136,7 @@ void machine_halt(void) */ } +void (*chassis_power_off)(void); /* * This routine is called from sys_reboot to actually turn off the @@ -170,8 +145,8 @@ void machine_halt(void) void machine_power_off(void) { /* If there is a registered power off handler, call it. */ - if(pm_power_off) - pm_power_off(); + if (chassis_power_off) + chassis_power_off(); /* Put the soft power button back under hardware control. * If the user had already pressed the power button, the @@ -187,6 +162,8 @@ void machine_power_off(void) KERN_EMERG "Please power this system off now."); } +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); /* * Create a kernel thread diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 27160e8bf15b..413292f1a4a3 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -91,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied; #ifdef __LP64__ - if (is_compat_task(child)) { + if (personality(child->personality) == PER_LINUX32) { unsigned int tmp; addr &= 0xffffffffL; @@ -123,7 +123,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_POKEDATA: ret = 0; #ifdef __LP64__ - if (is_compat_task(child)) { + if (personality(child->personality) == PER_LINUX32) { unsigned int tmp = (unsigned int)data; DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", request == PTRACE_POKETEXT ? "TEXT" : "DATA", @@ -146,7 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_PEEKUSR: { ret = -EIO; #ifdef __LP64__ - if (is_compat_task(child)) { + if (personality(child->personality) == PER_LINUX32) { unsigned int tmp; if (addr & (sizeof(int)-1)) @@ -205,7 +205,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) goto out_tsk; } #ifdef __LP64__ - if (is_compat_task(child)) { + if (personality(child->personality) == PER_LINUX32) { if (addr & (sizeof(int)-1)) goto out_tsk; if ((addr = translate_usr_offset(addr)) < 0) diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 3a25a7bd673e..05767e83cf2d 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -317,7 +317,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if(personality(current->personality) == PER_LINUX32) { DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); - err |= compat_copy_siginfo_to_user(&compat_frame->info, info); + err |= copy_siginfo_to_user32(&compat_frame->info, info); DBG(1,"SETUP_RT_FRAME: 1\n"); compat_val = (compat_int_t)current->sas_ss_sp; err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp); diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 0792e20efef3..a6b4231cafa1 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -31,7 +31,6 @@ #include <linux/types.h> #include <linux/errno.h> -#include <asm/compat_signal.h> #include <asm/uaccess.h> #include "signal32.h" @@ -398,3 +397,104 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __ return err; } + +int +copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) +{ + unsigned long tmp; + int err; + + if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) + return -EFAULT; + + err = __get_user(to->si_signo, &from->si_signo); + err |= __get_user(to->si_errno, &from->si_errno); + err |= __get_user(to->si_code, &from->si_code); + + if (to->si_code < 0) + err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); + else { + switch (to->si_code >> 16) { + case __SI_CHLD >> 16: + err |= __get_user(to->si_utime, &from->si_utime); + err |= __get_user(to->si_stime, &from->si_stime); + err |= __get_user(to->si_status, &from->si_status); + default: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + break; + case __SI_FAULT >> 16: + err |= __get_user(tmp, &from->si_addr); + to->si_addr = (void __user *) tmp; + break; + case __SI_POLL >> 16: + err |= __get_user(to->si_band, &from->si_band); + err |= __get_user(to->si_fd, &from->si_fd); + break; + case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ + case __SI_MESGQ >> 16: + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + err |= __get_user(to->si_int, &from->si_int); + break; + } + } + return err; +} + +int +copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) +{ + unsigned int addr; + int err; + + if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) + return -EFAULT; + + /* If you change siginfo_t structure, please be sure + this code is fixed accordingly. + It should never copy any pad contained in the structure + to avoid security leaks, but must copy the generic + 3 ints plus the relevant union member. + This routine must convert siginfo from 64bit to 32bit as well + at the same time. */ + err = __put_user(from->si_signo, &to->si_signo); + err |= __put_user(from->si_errno, &to->si_errno); + err |= __put_user((short)from->si_code, &to->si_code); + if (from->si_code < 0) + err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); + else { + switch (from->si_code >> 16) { + case __SI_CHLD >> 16: + err |= __put_user(from->si_utime, &to->si_utime); + err |= __put_user(from->si_stime, &to->si_stime); + err |= __put_user(from->si_status, &to->si_status); + default: + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); + break; + case __SI_FAULT >> 16: + /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */ + err |= __put_user(from->_sifields._pad[0], &to->si_addr); + break; + case __SI_POLL >> 16: + err |= __put_user(from->si_band, &to->si_band); + err |= __put_user(from->si_fd, &to->si_fd); + break; + case __SI_TIMER >> 16: + err |= __put_user(from->si_tid, &to->si_tid); + err |= __put_user(from->si_overrun, &to->si_overrun); + addr = (unsigned long) from->si_ptr; + err |= __put_user(addr, &to->si_ptr); + break; + case __SI_RT >> 16: /* Not generated by the kernel as of now. */ + case __SI_MESGQ >> 16: + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(from->si_pid, &to->si_pid); + addr = (unsigned long) from->si_ptr; + err |= __put_user(addr, &to->si_ptr); + break; + } + } + return err; +} diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h index 4d1569e717cc..e39b38a67a87 100644 --- a/arch/parisc/kernel/signal32.h +++ b/arch/parisc/kernel/signal32.h @@ -20,8 +20,34 @@ #define _PARISC64_KERNEL_SIGNAL32_H #include <linux/compat.h> -#include <asm/compat_signal.h> -#include <asm/compat_rt_sigframe.h> + +typedef compat_uptr_t compat_sighandler_t; + +typedef struct compat_sigaltstack { + compat_uptr_t ss_sp; + compat_int_t ss_flags; + compat_size_t ss_size; +} compat_stack_t; + +/* Most things should be clean enough to redefine this at will, if care + is taken to make libc match. */ + +struct compat_sigaction { + compat_sighandler_t sa_handler; + compat_uint_t sa_flags; + compat_sigset_t sa_mask; /* mask last for extensibility */ +}; + +/* 32-bit ucontext as seen from an 64-bit kernel */ +struct compat_ucontext { + compat_uint_t uc_flags; + compat_uptr_t uc_link; + compat_stack_t uc_stack; /* struct compat_sigaltstack (12 bytes)*/ + /* FIXME: Pad out to get uc_mcontext to start at an 8-byte aligned boundary */ + compat_uint_t pad[1]; + struct compat_sigcontext uc_mcontext; + compat_sigset_t uc_sigmask; /* mask last for extensibility */ +}; /* ELF32 signal handling */ @@ -29,6 +55,103 @@ struct k_sigaction32 { struct compat_sigaction sa; }; +typedef struct compat_siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[((128/sizeof(int)) - 3)]; + + /* kill() */ + struct { + unsigned int _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + compat_timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof(unsigned int) - sizeof(int)]; + compat_sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + unsigned int _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + unsigned int _pid; /* which child */ + unsigned int _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + unsigned int _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} compat_siginfo_t; + +int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from); +int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from); + +/* In a deft move of uber-hackery, we decide to carry the top half of all + * 64-bit registers in a non-portable, non-ABI, hidden structure. + * Userspace can read the hidden structure if it *wants* but is never + * guaranteed to be in the same place. Infact the uc_sigmask from the + * ucontext_t structure may push the hidden register file downards + */ +struct compat_regfile { + /* Upper half of all the 64-bit registers that were truncated + on a copy to a 32-bit userspace */ + compat_int_t rf_gr[32]; + compat_int_t rf_iasq[2]; + compat_int_t rf_iaoq[2]; + compat_int_t rf_sar; +}; + +#define COMPAT_SIGRETURN_TRAMP 4 +#define COMPAT_SIGRESTARTBLOCK_TRAMP 5 +#define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \ + COMPAT_SIGRESTARTBLOCK_TRAMP) + +struct compat_rt_sigframe { + /* XXX: Must match trampoline size in arch/parisc/kernel/signal.c + Secondary to that it must protect the ERESTART_RESTARTBLOCK + trampoline we left on the stack (we were bad and didn't + change sp so we could run really fast.) */ + compat_uint_t tramp[COMPAT_TRAMP_SIZE]; + compat_siginfo_t info; + struct compat_ucontext uc; + /* Hidden location of truncated registers, *must* be last. */ + struct compat_regfile regs; +}; + +/* + * The 32-bit ABI wants at least 48 bytes for a function call frame: + * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of + * which Linux/parisc uses is sp-20 for the saved return pointer...) + * Then, the stack pointer must be rounded to a cache line (64 bytes). + */ +#define SIGFRAME32 64 +#define FUNCTIONCALLFRAME32 48 +#define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32) + void sigset_32to64(sigset_t *s64, compat_sigset_t *s32); void sigset_64to32(compat_sigset_t *s32, sigset_t *s64); int do_sigaltstack32 (const compat_stack_t __user *uss32, diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index d66163492890..af88afef41bd 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -650,6 +650,8 @@ end_linux_gateway_page: #define LWS_ENTRY(_name_) .word (lws_##_name_ - linux_gateway_page) #endif + .section .rodata,"a" + .align 4096 /* Light-weight-syscall table */ /* Start of lws table. */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 32cbc0489324..51d2480627d1 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -374,5 +374,24 @@ ENTRY_SAME(keyctl) ENTRY_SAME(ioprio_set) ENTRY_SAME(ioprio_get) + ENTRY_SAME(inotify_init) + ENTRY_SAME(inotify_add_watch) /* 270 */ + ENTRY_SAME(inotify_rm_watch) + ENTRY_COMP(pselect6) + ENTRY_COMP(ppoll) + ENTRY_SAME(migrate_pages) + ENTRY_COMP(openat) /* 275 */ + ENTRY_SAME(mkdirat) + ENTRY_SAME(mknodat) + ENTRY_SAME(fchownat) + ENTRY_COMP(futimesat) + ENTRY_COMP(newfstatat) /* 280 */ + ENTRY_SAME(unlinkat) + ENTRY_SAME(renameat) + ENTRY_SAME(linkat) + ENTRY_SAME(symlinkat) + ENTRY_SAME(readlinkat) /* 285 */ + ENTRY_SAME(fchmodat) + ENTRY_SAME(faccessat) /* Nothing yet */ diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 15914f0235a0..ff200608c851 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -193,10 +193,9 @@ void show_stack(struct task_struct *task, unsigned long *s) HERE: asm volatile ("copy %%r30, %0" : "=r"(sp)); - r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL); + r = kzalloc(sizeof(struct pt_regs), GFP_KERNEL); if (!r) return; - memset(r, 0, sizeof(struct pt_regs)); r->iaoq[0] = (unsigned long)&&HERE; r->gr[2] = (unsigned long)__builtin_return_address(0); r->gr[30] = sp; diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c index f84f2586672b..66c8a9f6a27e 100644 --- a/arch/parisc/math-emu/decode_exc.c +++ b/arch/parisc/math-emu/decode_exc.c @@ -337,6 +337,7 @@ decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[]) } break; case INVALIDEXCEPTION: + case OPC_2E_INVALIDEXCEPTION: update_trap_counts(Fpu_register, aflags, bflags, trap_counts); return SIGNALCODE(SIGFPE, FPE_FLTINV); case DIVISIONBYZEROEXCEPTION: diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 720287d46e55..7847ca13d6c2 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -371,17 +371,11 @@ static void __init setup_bootmem(void) void free_initmem(void) { - /* FIXME: */ -#if 0 - printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n", - (&__init_end - &__init_begin) >> 10); - return; -#else unsigned long addr; printk(KERN_INFO "Freeing unused kernel memory: "); -#if 1 +#ifdef CONFIG_DEBUG_KERNEL /* Attempt to catch anyone trying to execute code here * by filling the page with BRK insns. * @@ -414,9 +408,21 @@ void free_initmem(void) pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE); printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10); -#endif } + +#ifdef CONFIG_DEBUG_RODATA +void mark_rodata_ro(void) +{ + extern char __start_rodata, __end_rodata; + /* rodata memory was already mapped with KERNEL_RO access rights by + pagetable_init() and map_pages(). No need to do additional stuff here */ + printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n", + (unsigned long)(&__end_rodata - &__start_rodata) >> 10); +} +#endif + + /* * Just an arbitrary offset to serve as a "hole" between mapping areas * (between top of physical memory and a potential pcxl dma mapping @@ -477,11 +483,6 @@ void __init mem_init(void) } -int do_check_pgt_cache(int low, int high) -{ - return 0; -} - unsigned long *empty_zero_page __read_mostly; void show_mem(void) @@ -690,7 +691,7 @@ static void __init pagetable_init(void) #ifdef CONFIG_BLK_DEV_INITRD if (initrd_end && initrd_end > mem_limit) { - printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); + printk(KERN_INFO "initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); map_pages(initrd_start, __pa(initrd_start), initrd_end - initrd_start, PAGE_KERNEL); } @@ -792,8 +793,6 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) EXPORT_SYMBOL(map_hpux_gateway_page); #endif -extern void flush_tlb_all_local(void); - void __init paging_init(void) { int i; @@ -802,7 +801,7 @@ void __init paging_init(void) pagetable_init(); gateway_init(); flush_cache_all_local(); /* start with known state */ - flush_tlb_all_local(); + flush_tlb_all_local(NULL); for (i = 0; i < npmem_ranges; i++) { unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 }; @@ -993,7 +992,7 @@ void flush_tlb_all(void) do_recycle++; } spin_unlock(&sid_lock); - on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); + on_each_cpu(flush_tlb_all_local, NULL, 1, 1); if (do_recycle) { spin_lock(&sid_lock); recycle_sids(recycle_ndirty,recycle_dirty_array); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index df338c5cc910..80d114a3a837 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -83,6 +83,12 @@ config GENERIC_TBSYNC default y if PPC32 && SMP default n +config DEFAULT_UIMAGE + bool + help + Used to allow a board to specify it wants a uImage built by default + default n + menu "Processor support" choice prompt "Processor Type" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 44dd82b791d1..5500ab55d042 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -142,6 +142,7 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ # Default to zImage, override when needed defaultimage-y := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux +defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage KBUILD_IMAGE := $(defaultimage-y) all: $(KBUILD_IMAGE) @@ -167,6 +168,8 @@ endef archclean: $(Q)$(MAKE) $(clean)=$(boot) + +archmrproper: $(Q)rm -rf arch/$(ARCH)/include archprepare: checkbin diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index b657f7e44762..063b84f2cbea 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -533,6 +533,7 @@ CONFIG_MII=y # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 3c22ccb18519..d6fed3f56580 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -675,6 +675,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index 751a622fb7a7..c775027947f9 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig @@ -567,6 +567,7 @@ CONFIG_ACENIC=m # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 07b6d3d23360..68194c03f6d1 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -454,6 +454,7 @@ CONFIG_AMD8111_ETH=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 0b2b55a79c3c..6f6c6bed1aa5 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -724,6 +724,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index a50ce0fa9243..aa9893a1f6e8 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -671,6 +671,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index c287980b7e65..80e9fe2632b8 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -12,10 +12,10 @@ endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \ - init_task.o process.o + init_task.o process.o systbl.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ - signal_64.o ptrace32.o systbl.o \ + signal_64.o ptrace32.o \ paca.o cpu_setup_power4.o \ firmware.o sysfs.o idle_64.o obj-$(CONFIG_PPC64) += vdso64/ @@ -46,7 +46,7 @@ extra-$(CONFIG_8xx) := head_8xx.o extra-y += vmlinux.lds obj-y += time.o prom.o traps.o setup-common.o udbg.o -obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o +obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o obj-$(CONFIG_MODULES) += ppc_ksyms.o diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index d8da2a35c0a4..f20a67261ec7 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -227,7 +227,7 @@ ret_from_syscall: MTMSRD(r10) lwz r9,TI_FLAGS(r12) li r8,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) bne- syscall_exit_work cmplw 0,r3,r8 blt+ syscall_exit_cont @@ -357,7 +357,7 @@ save_user_nvgprs_cont: lwz r5,_MSR(r1) andi. r5,r5,MSR_PR beq ret_from_except - andi. r0,r9,_TIF_SIGPENDING + andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK beq ret_from_except b do_user_signal 8: @@ -683,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ /* Check current_thread_info()->flags */ rlwinm r9,r1,0,0,(31-THREAD_SHIFT) lwz r9,TI_FLAGS(r9) - andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) bne do_work restore_user: @@ -917,7 +917,7 @@ recheck: lwz r9,TI_FLAGS(r9) andi. r0,r9,_TIF_NEED_RESCHED bne- do_resched - andi. r0,r9,_TIF_SIGPENDING + andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK beq restore_user do_user_signal: /* r10 contains MSR_KERNEL here */ ori r10,r10,MSR_EE diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 542036318866..388f861b8ed1 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -160,7 +160,7 @@ syscall_exit: mtmsrd r10,1 ld r9,TI_FLAGS(r12) li r11,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK) bne- syscall_exit_work cmpld r3,r11 ld r5,_CCR(r1) diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e4362dfa37fb..340730fb8c91 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -66,7 +66,7 @@ _GLOBAL(load_up_fpu) #else ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - ld r4,THREAD_FPEXC_MODE(r5) + lwz r4,THREAD_FPEXC_MODE(r5) ori r12,r12,MSR_FP or r12,r12,r4 std r12,_MSR(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 308268466342..415659629394 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -749,11 +749,12 @@ iSeries_secondary_smp_loop: .globl decrementer_iSeries_masked decrementer_iSeries_masked: + /* We may not have a valid TOC pointer in here. */ li r11,1 ld r12,PACALPPACAPTR(r13) stb r11,LPPACADECRINT(r12) - LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) - lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) + LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy) + lwz r12,0(r12) mtspr SPRN_DEC,r12 /* fall through */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4d9b4388918b..946f3219fd29 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -334,9 +334,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, spin_unlock_irqrestore(&(tbl->it_lock), flags); - /* Make sure updates are seen by hardware */ - mb(); - DBG("mapped %d elements:\n", outcount); /* For the sake of iommu_unmap_sg, we clear out the length in the @@ -347,6 +344,10 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, outs->dma_address = DMA_ERROR_CODE; outs->dma_length = 0; } + + /* Make sure updates are seen by hardware */ + mb(); + return outcount; failure: @@ -358,6 +359,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) >> PAGE_SHIFT; __iommu_free(tbl, vaddr, npages); + s->dma_address = DMA_ERROR_CODE; + s->dma_length = 0; } } spin_unlock_irqrestore(&(tbl->it_lock), flags); diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index f970ace208d3..c7a799a09516 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -134,7 +134,6 @@ static int __init add_legacy_soc_port(struct device_node *np, return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags); } -#ifdef CONFIG_ISA static int __init add_legacy_isa_port(struct device_node *np, struct device_node *isa_brg) { @@ -168,7 +167,6 @@ static int __init add_legacy_isa_port(struct device_node *np, return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF); } -#endif #ifdef CONFIG_PCI static int __init add_legacy_pci_port(struct device_node *np, @@ -276,7 +274,6 @@ void __init find_legacy_serial_ports(void) of_node_put(soc); } -#ifdef CONFIG_ISA /* First fill our array with ISA ports */ for (np = NULL; (np = of_find_node_by_type(np, "serial"));) { struct device_node *isa = of_get_parent(np); @@ -287,7 +284,6 @@ void __init find_legacy_serial_ports(void) } of_node_put(isa); } -#endif #ifdef CONFIG_PCI /* Next, try to locate PCI ports */ diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d50c8df0183e..294832a7e0a6 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -491,7 +491,12 @@ void __init finish_device_tree(void) size = 16; finish_node(allnodes, &size, 1); size -= 16; - end = start = (unsigned long) __va(lmb_alloc(size, 128)); + + if (0 == size) + end = start = 0; + else + end = start = (unsigned long)__va(lmb_alloc(size, 128)); + finish_node(allnodes, &end, 0); BUG_ON(end != start + size); @@ -1398,8 +1403,8 @@ struct device_node *of_find_node_by_name(struct device_node *from, read_lock(&devtree_lock); np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->name != 0 && strcasecmp(np->name, name) == 0 + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcasecmp(np->name, name) == 0 && of_node_get(np)) break; if (from) @@ -1917,3 +1922,30 @@ int prom_update_property(struct device_node *np, return 0; } + +#ifdef CONFIG_KEXEC +/* We may have allocated the flat device tree inside the crash kernel region + * in prom_init. If so we need to move it out into regular memory. */ +void kdump_move_device_tree(void) +{ + unsigned long start, end; + struct boot_param_header *new; + + start = __pa((unsigned long)initial_boot_params); + end = start + initial_boot_params->totalsize; + + if (end < crashk_res.start || start > crashk_res.end) + return; + + new = (struct boot_param_header*) + __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); + + memcpy(new, initial_boot_params, initial_boot_params->totalsize); + + initial_boot_params = new; + + DBG("Flat device tree blob moved to %p\n", initial_boot_params); + + /* XXX should we unreserve the old DT? */ +} +#endif /* CONFIG_KEXEC */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7881ec96ef11..ec7153f4d47c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2098,6 +2098,10 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ prom_init_stdout(); + /* Bail if this is a kdump kernel. */ + if (PHYSICAL_START > 0) + prom_panic("Error: You can't boot a kdump kernel from OF!\n"); + /* * Check for an initrd */ diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index a8099c806150..3934c227549b 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -465,8 +465,10 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, if (parent == NULL) return NULL; bus = of_match_bus(parent); - if (strcmp(bus->name, "pci")) + if (strcmp(bus->name, "pci")) { + of_node_put(parent); return NULL; + } bus->count_cells(dev, &na, &ns); of_node_put(parent); if (!OF_CHECK_COUNTS(na, ns)) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 7fe4a5c944c9..b5b2add7ad1e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -22,6 +22,7 @@ #include <asm/prom.h> #include <asm/rtas.h> +#include <asm/hvcall.h> #include <asm/semaphore.h> #include <asm/machdep.h> #include <asm/page.h> @@ -565,6 +566,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; #ifdef CONFIG_PPC_PSERIES static void rtas_percpu_suspend_me(void *info) { + int i; long rc; long flags; struct rtas_suspend_me_data *data = @@ -587,18 +589,16 @@ static void rtas_percpu_suspend_me(void *info) if (rc == H_Continue) { data->waiting = 0; - rtas_call(ibm_suspend_me_token, 0, 1, - data->args->args); + data->args->args[data->args->nargs] = + rtas_call(ibm_suspend_me_token, 0, 1, NULL); + for_each_cpu(i) + plpar_hcall_norets(H_PROD,i); } else { data->waiting = -EBUSY; printk(KERN_ERR "Error on H_Join hypervisor call\n"); } out: - /* before we restore interrupts, make sure we don't - * generate a spurious soft lockup errors - */ - touch_softlockup_watchdog(); local_irq_restore(flags); return; } diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 50500093c97f..aaf384c3f04a 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -672,8 +672,7 @@ static void rtas_flash_firmware(int reboot_type) static void remove_flash_pde(struct proc_dir_entry *dp) { if (dp) { - if (dp->data != NULL) - kfree(dp->data); + kfree(dp->data); dp->owner = NULL; remove_proc_entry(dp->name, dp->parent); } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index e29b275e09e0..a717dff695ef 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -398,6 +398,9 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); +#ifdef CONFIG_KEXEC + kdump_move_device_tree(); +#endif /* * Unflatten the device-tree passed by prom_init or kexec */ diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 177bba78fb0b..bd837b5dbf06 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -142,11 +142,7 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka, return 0; } -static inline compat_uptr_t to_user_ptr(void *kp) -{ - return (compat_uptr_t)(u64)kp; -} - +#define to_user_ptr(p) ptr_to_compat(p) #define from_user_ptr(p) compat_ptr(p) static inline int save_general_regs(struct pt_regs *regs, @@ -213,8 +209,8 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka, return 0; } -#define to_user_ptr(p) (p) -#define from_user_ptr(p) (p) +#define to_user_ptr(p) ((unsigned long)(p)) +#define from_user_ptr(p) ((void __user *)(p)) static inline int save_general_regs(struct pt_regs *regs, struct mcontext __user *frame) @@ -252,67 +248,19 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs); /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, - struct pt_regs *regs) +long sys_sigsuspend(old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } -} - -long sys_rt_sigsuspend( -#ifdef CONFIG_PPC64 - compat_sigset_t __user *unewset, -#else - sigset_t __user *unewset, -#endif - size_t sigsetsize, int p3, int p4, - int p6, int p7, struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (get_sigset_t(&newset, unewset)) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } #ifdef CONFIG_PPC32 @@ -574,7 +522,7 @@ long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); + ret = put_user(to_user_ptr(old_ka.sa.sa_handler), &oact->sa_handler); ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); } @@ -723,8 +671,8 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, int r6, int r7, int r8, struct pt_regs *regs) { - stack_32_t __user * newstack = (stack_32_t __user *)(long) __new; - stack_32_t __user * oldstack = (stack_32_t __user *)(long) __old; + stack_32_t __user * newstack = compat_ptr(__new); + stack_32_t __user * oldstack = compat_ptr(__old); stack_t uss, uoss; int ret; mm_segment_t old_fs; @@ -756,7 +704,7 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, set_fs(old_fs); /* Copy the stack information to the user output buffer */ if (!ret && oldstack && - (put_user((long)uoss.ss_sp, &oldstack->ss_sp) || + (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || __put_user(uoss.ss_flags, &oldstack->ss_flags) || __put_user(uoss.ss_size, &oldstack->ss_size))) return -EFAULT; @@ -1174,7 +1122,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; struct k_sigaction ka; - unsigned int frame, newsp; + unsigned int newsp; int signr, ret; #ifdef CONFIG_PPC32 @@ -1185,11 +1133,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) } #endif - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); #ifdef CONFIG_PPC32 no_signal: @@ -1219,8 +1167,14 @@ no_signal: } } - if (signr == 0) + if (signr == 0) { + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return 0; /* no signals delivered */ + } if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && !on_sig_stack(regs->gpr[1])) @@ -1253,6 +1207,10 @@ no_signal: sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + /* A signal was successfully delivered; the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); } return ret; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 7b9d999e2115..497a5d3df359 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -60,49 +60,13 @@ struct rt_sigframe { struct ucontext uc; unsigned long _unused[2]; unsigned int tramp[TRAMP_SIZE]; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; struct siginfo info; /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ char abigap[288]; } __attribute__ ((aligned (16))); - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4, - int p6, int p7, struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } -} - long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs *regs) @@ -556,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (test_thread_flag(TIF_32BIT)) return do_signal32(oldset, regs); - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { + int ret; + /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) syscall_restart(regs, &ka); @@ -573,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (current->thread.dabr) set_dabr(current->thread.dabr); - return handle_signal(signr, &ka, &info, oldset, regs); + ret = handle_signal(signr, &ka, &info, oldset, regs); + + /* If a signal was successfully delivered, the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return ret; } if (TRAP(regs) == 0x0C00) { /* System Call! */ @@ -589,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) regs->result = 0; } } + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return 0; } diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index c8458c531b25..13595a64f013 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -540,6 +540,9 @@ int __devinit start_secondary(void *unused) if (smp_ops->take_timebase) smp_ops->take_timebase(); + if (system_state > SYSTEM_BOOTING) + per_cpu(last_jiffy, cpu) = get_tb(); + spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); spin_unlock(&call_lock); diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 68013179a503..8a9f994ed917 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -36,8 +36,6 @@ #ifdef CONFIG_PPC64 #define sys_sigpending sys_ni_syscall #define sys_old_getrlimit sys_ni_syscall -#else -#define ppc_rtas sys_ni_syscall #endif _GLOBAL(sys_call_table) @@ -321,3 +319,6 @@ SYSCALL(inotify_add_watch) SYSCALL(inotify_rm_watch) SYSCALL(spu_run) SYSCALL(spu_create) +COMPAT_SYS(pselect6) +COMPAT_SYS(ppoll) +SYSCALL(unshare) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index c4a294d657b9..1886045a2fd8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -612,10 +612,10 @@ void __init generic_calibrate_decr(void) ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ node_found = 0; - if (cpu != 0) { + if (cpu) { fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL); - if (fp != 0) { + if (fp) { node_found = 1; ppc_tb_freq = *fp; } @@ -626,10 +626,10 @@ void __init generic_calibrate_decr(void) ppc_proc_freq = DEFAULT_PROC_FREQ; node_found = 0; - if (cpu != 0) { + if (cpu) { fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL); - if (fp != 0) { + if (fp) { node_found = 1; ppc_proc_freq = *fp; } diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 2da65a9c93f6..5d29dcca523c 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -144,7 +144,7 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) } #ifdef CONFIG_PPC_MAPLE -void udbg_maple_real_putc(unsigned char c) +void udbg_maple_real_putc(char c) { if (udbg_comport) { while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 9584608fd768..bbe3eac918e8 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -197,6 +197,8 @@ long __init lmb_reserve(unsigned long base, unsigned long size) { struct lmb_region *_rgn = &(lmb.reserved); + BUG_ON(0 == size); + return lmb_add_region(_rgn, base, size); } @@ -227,6 +229,8 @@ unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, long i, j; unsigned long base = 0; + BUG_ON(0 == size); + #ifdef CONFIG_PPC32 /* On 32-bit, make sure we allocate lowmem */ if (max_addr == LMB_ALLOC_ANYWHERE) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 15aac0d78dfa..550517c2dd42 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -435,17 +435,12 @@ void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); - if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) - return; /* * We shouldnt have to do this, but some versions of glibc * require it (ld.so assumes zero filled pages are icache clean) * - Anton */ - - /* avoid an atomic op if possible */ - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); + flush_dcache_page(pg); } EXPORT_SYMBOL(clear_user_page); @@ -469,12 +464,7 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, return; #endif - if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) - return; - - /* avoid an atomic op if possible */ - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); + flush_dcache_page(pg); } void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 16031b565be4..3b998a393e3f 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -2,7 +2,7 @@ obj-y += interrupt.o iommu.o setup.o spider-pic.o obj-y += pervasive.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SPU_FS) += spufs/ spu-base.o +obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ spu-base-y += spu_base.o spu_priv1.o diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 3a2057fa314a..814f54742e0f 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h @@ -5,7 +5,6 @@ extern void chrp_nvram_init(void); extern void chrp_get_rtc_time(struct rtc_time *); extern int chrp_set_rtc_time(struct rtc_time *); -extern void chrp_calibrate_decr(void); extern long chrp_time_init(void); extern void chrp_find_bridges(void); diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 00c52f27ef4f..8ef279ad36ad 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -204,9 +204,11 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d struct device_node *root = find_path_device("/"); struct device_node *rtas; + of_node_get(root); rtas = of_find_node_by_name (root, "rtas"); if (rtas) { hose->ops = &rtas_pci_ops; + of_node_put(rtas); } else { printk ("RTAS supporting Pegasos OF not found, please upgrade" " your firmware\n"); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 2dc87aa5962f..e1fadbf49150 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -506,7 +506,7 @@ void __init chrp_init(void) ppc_md.halt = rtas_halt; ppc_md.time_init = chrp_time_init; - ppc_md.calibrate_decr = chrp_calibrate_decr; + ppc_md.calibrate_decr = generic_calibrate_decr; /* this may get overridden with rtas routines later... */ ppc_md.set_rtc_time = chrp_set_rtc_time; diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 36a0f97bb7b1..78df2e7ca88a 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -167,24 +167,3 @@ void chrp_get_rtc_time(struct rtc_time *tm) tm->tm_mon = mon; tm->tm_year = year; } - - -void __init chrp_calibrate_decr(void) -{ - struct device_node *cpu; - unsigned int freq, *fp; - - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ - freq = 16666000; /* hardcoded default */ - cpu = find_type_devices("cpu"); - if (cpu != 0) { - fp = (unsigned int *) - get_property(cpu, "timebase-frequency", NULL); - if (fp != 0) - freq = *fp; - } - ppc_tb_freq = freq; -} diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 535c802b369f..87eb6bb7f0e7 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -1052,8 +1052,7 @@ struct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter) } EXPORT_SYMBOL_GPL(pmac_i2c_adapter_to_bus); -extern int pmac_i2c_match_adapter(struct device_node *dev, - struct i2c_adapter *adapter) +int pmac_i2c_match_adapter(struct device_node *dev, struct i2c_adapter *adapter) { struct pmac_i2c_bus *bus = pmac_i2c_find_bus(dev); diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index f671ed253901..de3f30e6b333 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -136,14 +136,14 @@ static void __init fixup_bus_range(struct device_node *bridge) |(((unsigned int)(off)) & 0xFCUL) \ |1UL) -static unsigned long macrisc_cfg_access(struct pci_controller* hose, +static volatile void __iomem *macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) { unsigned int caddr; if (bus == hose->first_busno) { if (dev_fn < (11 << 3)) - return 0; + return NULL; caddr = MACRISC_CFA0(dev_fn, offset); } else caddr = MACRISC_CFA1(bus, dev_fn, offset); @@ -154,14 +154,14 @@ static unsigned long macrisc_cfg_access(struct pci_controller* hose, } while (in_le32(hose->cfg_addr) != caddr); offset &= has_uninorth ? 0x07 : 0x03; - return ((unsigned long)hose->cfg_data) + offset; + return hose->cfg_data + offset; } static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -177,13 +177,13 @@ static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - *val = in_8((u8 *)addr); + *val = in_8(addr); break; case 2: - *val = in_le16((u16 *)addr); + *val = in_le16(addr); break; default: - *val = in_le32((u32 *)addr); + *val = in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -193,7 +193,7 @@ static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -209,16 +209,16 @@ static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - out_8((u8 *)addr, val); - (void) in_8((u8 *)addr); + out_8(addr, val); + (void) in_8(addr); break; case 2: - out_le16((u16 *)addr, val); - (void) in_le16((u16 *)addr); + out_le16(addr, val); + (void) in_le16(addr); break; default: - out_le32((u32 *)addr, val); - (void) in_le32((u32 *)addr); + out_le32(addr, val); + (void) in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -348,25 +348,23 @@ static int u3_ht_skip_device(struct pci_controller *hose, + (((unsigned int)bus) << 16) \ + 0x01000000UL) -static unsigned long u3_ht_cfg_access(struct pci_controller* hose, +static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) { if (bus == hose->first_busno) { /* For now, we don't self probe U3 HT bridge */ if (PCI_SLOT(devfn) == 0) - return 0; - return ((unsigned long)hose->cfg_data) + - U3_HT_CFA0(devfn, offset); + return NULL; + return hose->cfg_data + U3_HT_CFA0(devfn, offset); } else - return ((unsigned long)hose->cfg_data) + - U3_HT_CFA1(bus, devfn, offset); + return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); } static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -400,13 +398,13 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - *val = in_8((u8 *)addr); + *val = in_8(addr); break; case 2: - *val = in_le16((u16 *)addr); + *val = in_le16(addr); break; default: - *val = in_le32((u32 *)addr); + *val = in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -416,7 +414,7 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -442,16 +440,16 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - out_8((u8 *)addr, val); - (void) in_8((u8 *)addr); + out_8(addr, val); + (void) in_8(addr); break; case 2: - out_le16((u16 *)addr, val); - (void) in_le16((u16 *)addr); + out_le16(addr, val); + (void) in_le16(addr); break; default: - out_le32((u32 *)addr, val); - (void) in_le32((u32 *)addr); + out_le32((u32 __iomem *)addr, val); + (void) in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -476,7 +474,7 @@ static struct pci_ops u3_ht_pci_ops = |(((unsigned int)(off)) & 0xfcU) \ |1UL) -static unsigned long u4_pcie_cfg_access(struct pci_controller* hose, +static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, int offset) { unsigned int caddr; @@ -492,14 +490,14 @@ static unsigned long u4_pcie_cfg_access(struct pci_controller* hose, } while (in_le32(hose->cfg_addr) != caddr); offset &= 0x03; - return ((unsigned long)hose->cfg_data) + offset; + return hose->cfg_data + offset; } static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -515,13 +513,13 @@ static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - *val = in_8((u8 *)addr); + *val = in_8(addr); break; case 2: - *val = in_le16((u16 *)addr); + *val = in_le16(addr); break; default: - *val = in_le32((u32 *)addr); + *val = in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -531,7 +529,7 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - unsigned long addr; + volatile void __iomem *addr; hose = pci_bus_to_host(bus); if (hose == NULL) @@ -547,16 +545,16 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, */ switch (len) { case 1: - out_8((u8 *)addr, val); - (void) in_8((u8 *)addr); + out_8(addr, val); + (void) in_8(addr); break; case 2: - out_le16((u16 *)addr, val); - (void) in_le16((u16 *)addr); + out_le16(addr, val); + (void) in_le16(addr); break; default: - out_le32((u32 *)addr, val); - (void) in_le32((u32 *)addr); + out_le32(addr, val); + (void) in_le32(addr); break; } return PCIBIOS_SUCCESSFUL; @@ -773,8 +771,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) * the reg address cell, we shall fix that by killing struct * reg_property and using some accessor functions instead */ - hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, - 0x02000000); + hose->cfg_data = ioremap(0xf2000000, 0x02000000); /* * /ht node doesn't expose a "ranges" property, so we "remove" diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index c32c623001dc..356a739e52b2 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -862,21 +862,28 @@ int pmf_register_irq_client(struct device_node *target, spin_unlock_irqrestore(&pmf_lock, flags); return -ENODEV; } + if (list_empty(&func->irq_clients)) + func->dev->handlers->irq_enable(func); list_add(&client->link, &func->irq_clients); + client->func = func; spin_unlock_irqrestore(&pmf_lock, flags); return 0; } EXPORT_SYMBOL_GPL(pmf_register_irq_client); -void pmf_unregister_irq_client(struct device_node *np, - const char *name, - struct pmf_irq_client *client) +void pmf_unregister_irq_client(struct pmf_irq_client *client) { + struct pmf_function *func = client->func; unsigned long flags; + BUG_ON(func == NULL); + spin_lock_irqsave(&pmf_lock, flags); + client->func = NULL; list_del(&client->link); + if (list_empty(&func->irq_clients)) + func->dev->handlers->irq_disable(func); spin_unlock_irqrestore(&pmf_lock, flags); } EXPORT_SYMBOL_GPL(pmf_unregister_irq_client); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 89c4c3636161..1955462f4082 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -82,8 +82,6 @@ #undef SHOW_GATWICK_IRQS -unsigned char drive_info; - int ppc_override_l2cr = 0; int ppc_override_l2cr_value; int has_l2cache = 0; diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 6373372932ba..e3cbba49fd6e 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -333,7 +333,7 @@ void handle_eeh_events (struct eeh_event *event) rc = eeh_reset_device(frozen_pdn, NULL); if (rc) goto hard_fail; - pci_walk_bus(frozen_bus, eeh_report_reset, 0); + pci_walk_bus(frozen_bus, eeh_report_reset, NULL); } /* If all devices reported they can proceed, the re-enable PIO */ @@ -342,11 +342,11 @@ void handle_eeh_events (struct eeh_event *event) rc = eeh_reset_device(frozen_pdn, NULL); if (rc) goto hard_fail; - pci_walk_bus(frozen_bus, eeh_report_reset, 0); + pci_walk_bus(frozen_bus, eeh_report_reset, NULL); } /* Tell all device drivers that they can resume operations */ - pci_walk_bus(frozen_bus, eeh_report_resume, 0); + pci_walk_bus(frozen_bus, eeh_report_resume, NULL); return; @@ -367,7 +367,7 @@ hard_fail: eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); /* Notify all devices that they're about to go down. */ - pci_walk_bus(frozen_bus, eeh_report_failure, 0); + pci_walk_bus(frozen_bus, eeh_report_failure, NULL); /* Shut down the device drivers for good. */ pcibios_remove_pci_devices(frozen_bus); diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 21934784f936..bdaa8aabdaa6 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -58,6 +58,7 @@ pcibios_find_pci_bus(struct device_node *dn) return find_bus_among_children(pdn->phb->bus, dn); } +EXPORT_SYMBOL_GPL(pcibios_find_pci_bus); /** * pcibios_remove_pci_devices - remove all devices under this bus @@ -106,6 +107,7 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) } } } +EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); static int pcibios_pci_config_bridge(struct pci_dev *dev) @@ -172,3 +174,4 @@ pcibios_add_pci_devices(struct pci_bus * bus) pcibios_pci_config_bridge(dev); } } +EXPORT_SYMBOL_GPL(pcibios_add_pci_devices); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index da6cebaf72cd..9edeca83f434 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -585,7 +585,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ - if (!crash_shutdown) { + if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { unsigned long vpa = __pa(get_lppaca()); if (unregister_vpa(hard_smp_processor_id(), vpa)) { diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 977de9db8754..6298264efe36 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -59,7 +59,7 @@ static unsigned long dart_tablesize; static u32 *dart_vbase; /* Mapped base address for the dart */ -static unsigned int *__iomem dart; +static unsigned int __iomem *dart; /* Dummy val that entries are set to when unused */ static unsigned int dart_emptyval; diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig index 0ba4e70d50b6..41fd3938fa5c 100644 --- a/arch/ppc/configs/bamboo_defconfig +++ b/arch/ppc/configs/bamboo_defconfig @@ -499,6 +499,7 @@ CONFIG_NATSEMI=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig index 0f3bb9af9c22..7311fe6b42de 100644 --- a/arch/ppc/configs/katana_defconfig +++ b/arch/ppc/configs/katana_defconfig @@ -488,6 +488,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig index 673dc64ebcb1..b96a6d6dad0e 100644 --- a/arch/ppc/configs/mpc834x_sys_defconfig +++ b/arch/ppc/configs/mpc834x_sys_defconfig @@ -402,6 +402,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig index 93da595a4738..a1ef929bca59 100644 --- a/arch/ppc/configs/power3_defconfig +++ b/arch/ppc/configs/power3_defconfig @@ -442,6 +442,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index 3e6ca7f5843f..c1e89ad0684d 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -810,13 +810,16 @@ initial_mmu: mtspr SPRN_MD_TWC, r9 li r11, MI_BOOTINIT /* Create RPN for address 0 */ addis r11, r11, 0x0080 /* Add 8M */ - mtspr SPRN_MD_RPN, r8 + mtspr SPRN_MD_RPN, r11 + + addi r10, r10, 0x0100 + mtspr SPRN_MD_CTR, r10 addis r8, r8, 0x0080 /* Add 8M */ mtspr SPRN_MD_EPN, r8 mtspr SPRN_MD_TWC, r9 addis r11, r11, 0x0080 /* Add 8M */ - mtspr SPRN_MD_RPN, r8 + mtspr SPRN_MD_RPN, r11 #endif /* Since the cache is enabled according to the information we diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index c3427eed8345..5a936566fd61 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1048,286 +1048,3 @@ _GLOBAL(name) \ blr SYSCALL(execve) - -/* Why isn't this a) automatic, b) written in 'C'? */ - .data - .align 4 -_GLOBAL(sys_call_table) - .long sys_restart_syscall /* 0 */ - .long sys_exit - .long ppc_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid - .long sys_getuid - .long sys_stime /* 25 */ - .long sys_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid - .long sys_getgid - .long sys_signal - .long sys_geteuid - .long sys_getegid /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys() */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_olduname - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid /* 70 */ - .long sys_setregid - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups /* 80 */ - .long sys_setgroups - .long ppc_select - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long old_readdir - .long sys_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_uname - .long sys_ni_syscall /* 110 */ - .long sys_vhangup - .long sys_ni_syscall /* old 'idle' syscall */ - .long sys_ni_syscall - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .long sys_fsync - .long sys_sigreturn - .long ppc_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old sys_create_module */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* old sys_get_kernel_syms */ /* 130 */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid - .long sys_setfsgid - .long sys_llseek /* 140 */ - .long sys_getdents - .long ppc_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .long sys_mlock /* 150 */ - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid - .long sys_getresuid /* 165 */ - .long sys_ni_syscall /* old sys_query_module */ - .long sys_poll - .long sys_nfsservctl - .long sys_setresgid - .long sys_getresgid /* 170 */ - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask - .long sys_rt_sigpending /* 175 */ - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 - .long sys_pwrite64 /* 180 */ - .long sys_chown - .long sys_getcwd - .long sys_capget - .long sys_capset - .long sys_sigaltstack /* 185 */ - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long ppc_vfork - .long sys_getrlimit /* 190 */ - .long sys_readahead - .long sys_mmap2 - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_pciconfig_read - .long sys_pciconfig_write - .long sys_pciconfig_iobase /* 200 */ - .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */ - .long sys_getdents64 - .long sys_pivot_root - .long sys_fcntl64 - .long sys_madvise /* 205 */ - .long sys_mincore - .long sys_gettid - .long sys_tkill - .long sys_setxattr - .long sys_lsetxattr /* 210 */ - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr /* 215 */ - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr /* 220 */ - .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall - .long sys_ni_syscall /* 225 - reserved for Tux */ - .long sys_sendfile64 - .long sys_io_setup - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit /* 230 */ - .long sys_io_cancel - .long sys_set_tid_address - .long sys_fadvise64 - .long sys_exit_group - .long sys_lookup_dcookie /* 235 */ - .long sys_epoll_create - .long sys_epoll_ctl - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_timer_create /* 240 */ - .long sys_timer_settime - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime /* 245 */ - .long sys_clock_gettime - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_swapcontext - .long sys_tgkill /* 250 */ - .long sys_utimes - .long sys_statfs64 - .long sys_fstatfs64 - .long ppc_fadvise64_64 - .long sys_ni_syscall /* 255 - rtas (used on ppc64) */ - .long sys_debug_setcontext - .long sys_ni_syscall /* 257 reserved for vserver */ - .long sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */ - .long sys_ni_syscall /* 259 reserved for new sys_mbind */ - .long sys_ni_syscall /* 260 reserved for new sys_get_mempolicy */ - .long sys_ni_syscall /* 261 reserved for new sys_set_mempolicy */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 265 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_kexec_load - .long sys_add_key - .long sys_request_key /* 270 */ - .long sys_keyctl - .long sys_waitid - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init /* 275 */ - .long sys_inotify_add_watch - .long sys_inotify_rm_watch diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 3a6e4bcb3c53..15bd9b448a48 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -186,11 +186,15 @@ EXPORT_SYMBOL(flush_tlb_kernel_range); EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(_tlbie); #ifdef CONFIG_ALTIVEC +#ifndef CONFIG_SMP EXPORT_SYMBOL(last_task_used_altivec); +#endif EXPORT_SYMBOL(giveup_altivec); #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SPE +#ifndef CONFIG_SMP EXPORT_SYMBOL(last_task_used_spe); +#endif EXPORT_SYMBOL(giveup_spe); #endif /* CONFIG_SPE */ #ifdef CONFIG_SMP diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c index 159b228eca1e..0ec53f049338 100644 --- a/arch/ppc/platforms/4xx/bamboo.c +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -332,8 +332,8 @@ bamboo_early_serial_map(void) port.irq = 0; port.uartclk = clocks.uart0; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 8110f55668c5..ce48a4f08cbb 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c @@ -97,8 +97,8 @@ bubinga_early_serial_map(void) port.irq = ACTING_UART0_INT; port.uartclk = uart_clock; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 64ebae19cdbb..9a828b623417 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -225,8 +225,8 @@ ebony_early_serial_map(void) port.irq = 0; port.uartclk = clocks.uart0; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index d810b736d9bf..21d29132aebd 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -279,8 +279,8 @@ luan_early_serial_map(void) port.irq = UART0_INT; port.uartclk = clocks.uart0; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 73b2c98158f6..4f355b6acab2 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -248,8 +248,8 @@ ocotea_early_serial_map(void) port.irq = UART0_INT; port.uartclk = clocks.uart0; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index 0b1b77d986bf..e90d97f64f76 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -95,8 +95,8 @@ ml300_early_serial_map(void) port.irq = old_ports[i].irq; port.uartclk = old_ports[i].baud_base * 16; port.regshift = old_ports[i].iomem_reg_shift; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = i; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c index e60f4bd437ec..b065b8babcd3 100644 --- a/arch/ppc/platforms/4xx/yucca.c +++ b/arch/ppc/platforms/4xx/yucca.c @@ -305,8 +305,8 @@ yucca_early_serial_map(void) port.irq = UART0_INT; port.uartclk = clocks.uart0; port.regshift = 0; - port.iotype = SERIAL_IO_MEM; - port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.line = 0; if (early_serial_setup(&port) != 0) { diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 012e1e652c03..1a659bbc1860 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -301,14 +301,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, struct uart_port p; memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500); p.uartclk = binfo->bi_busfreq; gen550_init(0, &p); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600); p.uartclk = binfo->bi_busfreq; diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 2eceb1e6f4eb..408d64f18e1a 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -162,14 +162,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET; p.uartclk = binfo->bi_busfreq; gen550_init(0, &p); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET; p.uartclk = binfo->bi_busfreq; diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index b332ebae6bd3..1801ab392e22 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -534,14 +534,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET; p.uartclk = binfo->bi_busfreq; gen550_init(0, &p); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET; p.uartclk = binfo->bi_busfreq; diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index e777ba824aa9..8a72221f816c 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -64,7 +64,7 @@ sbc8560_early_serial_map(void) uart_req.irq = MPC85xx_IRQ_EXT9; uart_req.flags = STD_COM_FLAGS; uart_req.uartclk = BASE_BAUD * 16; - uart_req.iotype = SERIAL_IO_MEM; + uart_req.iotype = UPIO_MEM; uart_req.mapbase = UARTA_ADDR; uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE); uart_req.type = PORT_16650; diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index b436f4d0a3fa..a5e38ba62732 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -346,14 +346,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET; p.uartclk = binfo->bi_busfreq; gen550_init(0, &p); memset(&p, 0, sizeof (p)); - p.iotype = SERIAL_IO_MEM; + p.iotype = UPIO_MEM; p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET; p.uartclk = binfo->bi_busfreq; diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c index 48a4a510d598..aefcc0e7be57 100644 --- a/arch/ppc/platforms/chestnut.c +++ b/arch/ppc/platforms/chestnut.c @@ -116,7 +116,7 @@ chestnut_early_serial_map(void) port.uartclk = BASE_BAUD * 16; port.irq = UART0_INT; port.flags = STD_COM_FLAGS | UPF_IOREMAP; - port.iotype = SERIAL_IO_MEM; + port.iotype = UPIO_MEM; port.mapbase = CHESTNUT_UART0_IO_BASE; port.regshift = 0; diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c index 32358b3fb236..ffde8f6f6302 100644 --- a/arch/ppc/platforms/ev64260.c +++ b/arch/ppc/platforms/ev64260.c @@ -330,7 +330,7 @@ ev64260_early_serial_map(void) port.irq = EV64260_UART_0_IRQ; port.uartclk = BASE_BAUD * 16; port.regshift = 2; - port.iotype = SERIAL_IO_MEM; + port.iotype = UPIO_MEM; port.flags = STD_COM_FLAGS; #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 708b8739ecdd..872c0a3ba3c7 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -100,7 +100,7 @@ static void __init ppc7d_early_serial_map(void) serial_req.uartclk = UART_CLK; serial_req.irq = 4; serial_req.flags = STD_COM_FLAGS; - serial_req.iotype = SERIAL_IO_MEM; + serial_req.iotype = UPIO_MEM; serial_req.membase = (u_char *) PPC7D_SERIAL_0; gen550_init(0, &serial_req); diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c index 5ad70d357cb9..69e1de7971f2 100644 --- a/arch/ppc/platforms/spruce.c +++ b/arch/ppc/platforms/spruce.c @@ -176,8 +176,8 @@ spruce_early_serial_map(void) memset(&serial_req, 0, sizeof(serial_req)); serial_req.uartclk = uart_clk; serial_req.irq = UART0_INT; - serial_req.flags = ASYNC_BOOT_AUTOCONF; - serial_req.iotype = SERIAL_IO_MEM; + serial_req.flags = UPF_BOOT_AUTOCONF; + serial_req.iotype = UPIO_MEM; serial_req.membase = (u_char *)UART0_IO_BASE; serial_req.regshift = 0; diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 94ea346b7b4b..1f01b7e2376b 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -313,7 +313,7 @@ static struct platform_device mpsc1_device = { }; #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) static struct resource mv64x60_eth_shared_resources[] = { [0] = { .name = "ethernet shared base", @@ -456,7 +456,7 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = { &mpsc0_device, &mpsc1_device, #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) &mv64x60_eth_shared_device, #endif #ifdef CONFIG_MV643XX_ETH_0 diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c index ab34b1d6072f..2fe28ded2c60 100644 --- a/arch/ppc/syslib/ocp.c +++ b/arch/ppc/syslib/ocp.c @@ -189,8 +189,8 @@ ocp_device_resume(struct device *dev) struct bus_type ocp_bus_type = { .name = "ocp", .match = ocp_device_match, - .probe = ocp_driver_probe, - .remove = ocp_driver_remove, + .probe = ocp_device_probe, + .remove = ocp_device_remove, .suspend = ocp_device_suspend, .resume = ocp_device_resume, }; diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 1b5fe9e398d4..7bada82527a8 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c @@ -108,7 +108,7 @@ mpc83xx_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) memset(&serial_req, 0, sizeof (serial_req)); - serial_req.iotype = SERIAL_IO_MEM; + serial_req.iotype = UPIO_MEM; serial_req.mapbase = pdata[0].mapbase; serial_req.membase = pdata[0].membase; serial_req.regshift = 0; diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index 1a47ff4b831d..e4dda43fdaa7 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -90,7 +90,7 @@ mpc85xx_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) memset(&serial_req, 0, sizeof (serial_req)); - serial_req.iotype = SERIAL_IO_MEM; + serial_req.iotype = UPIO_MEM; serial_req.mapbase = pdata[0].mapbase; serial_req.membase = pdata[0].membase; serial_req.regshift = 0; diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 7d23edc6facb..f8d0cd540a06 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,19 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc2 -# Mon Nov 21 13:51:30 2005 +# Linux kernel version: 2.6.16-rc2 +# Wed Feb 8 10:44:39 2006 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_S390=y -CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -29,18 +27,20 @@ CONFIG_POSIX_MQUEUE=y CONFIG_SYSCTL=y CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -49,8 +49,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -76,11 +78,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_DEFAULT_IOSCHED="deadline" # # Base setup @@ -151,6 +153,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -193,6 +196,11 @@ CONFIG_IPV6=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -362,6 +370,7 @@ CONFIG_DM_MULTIPATH=y # CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=2048 +# CONFIG_HANGCHECK_TIMER is not set # # Watchdog Cards @@ -488,6 +497,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -520,6 +530,7 @@ CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -584,6 +595,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -592,27 +604,30 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set # -# Profiling support +# Instrumentation Support # # CONFIG_PROFILING is not set +# CONFIG_STATISTICS is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 -CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_DETECT_SOFTLOCKUP is not set # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index bf9a7a361b34..2d021626c1a6 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -100,12 +100,12 @@ #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) -asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group) +asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) { return sys_chown(filename, low2highuid(user), low2highgid(group)); } -asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group) +asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) { return sys_lchown(filename, low2highuid(user), low2highgid(group)); } @@ -141,7 +141,7 @@ asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) low2highuid(suid)); } -asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid) +asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) { int retval; @@ -158,7 +158,7 @@ asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) low2highgid(sgid)); } -asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid) +asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) { int retval; @@ -179,7 +179,7 @@ asmlinkage long sys32_setfsgid16(u16 gid) return sys_setfsgid((gid_t)gid); } -static int groups16_to_user(u16 *grouplist, struct group_info *group_info) +static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) { int i; u16 group; @@ -193,7 +193,7 @@ static int groups16_to_user(u16 *grouplist, struct group_info *group_info) return 0; } -static int groups16_from_user(struct group_info *group_info, u16 *grouplist) +static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) { int i; u16 group; @@ -207,7 +207,7 @@ static int groups16_from_user(struct group_info *group_info, u16 *grouplist) return 0; } -asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) +asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) { int i; @@ -231,7 +231,7 @@ out: return i; } -asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) +asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) { struct group_info *group_info; int retval; @@ -278,14 +278,14 @@ asmlinkage long sys32_getegid16(void) /* 32-bit timeval and related flotsam. */ -static inline long get_tv32(struct timeval *o, struct compat_timeval *i) +static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i) { return (!access_ok(VERIFY_READ, o, sizeof(*o)) || (__get_user(o->tv_sec, &i->tv_sec) || __get_user(o->tv_usec, &i->tv_usec))); } -static inline long put_tv32(struct compat_timeval *o, struct timeval *i) +static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || (__put_user(i->tv_sec, &o->tv_sec) || @@ -341,7 +341,7 @@ asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) return -ENOSYS; } -asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low) +asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) { if ((int)high < 0) return -EINVAL; @@ -357,7 +357,7 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned return sys_ftruncate(fd, (high << 32) | low); } -int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) +int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) { int err; @@ -591,7 +591,7 @@ sys32_delete_module(const char __user *name_user, unsigned int flags) extern struct timezone sys_tz; -asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) +asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { if (tv) { struct timeval ktv; @@ -606,7 +606,7 @@ asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *t return 0; } -static inline long get_ts32(struct timespec *o, struct compat_timeval *i) +static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) { long usec; @@ -620,7 +620,7 @@ static inline long get_ts32(struct timespec *o, struct compat_timeval *i) return 0; } -asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) +asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { struct timespec kts; struct timezone ktz; @@ -645,7 +645,7 @@ asmlinkage long sys32_pause(void) return -ERESTARTNOHAND; } -asmlinkage long sys32_pread64(unsigned int fd, char *ubuf, +asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo) { if ((compat_ssize_t) count < 0) @@ -653,7 +653,7 @@ asmlinkage long sys32_pread64(unsigned int fd, char *ubuf, return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -asmlinkage long sys32_pwrite64(unsigned int fd, const char *ubuf, +asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, size_t count, u32 poshi, u32 poslo) { if ((compat_ssize_t) count < 0) @@ -666,7 +666,7 @@ asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 coun return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); } -asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size_t count) +asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count) { mm_segment_t old_fs = get_fs(); int ret; @@ -686,7 +686,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size } asmlinkage long sys32_sendfile64(int out_fd, int in_fd, - compat_loff_t *offset, s32 count) + compat_loff_t __user *offset, s32 count) { mm_segment_t old_fs = get_fs(); int ret; @@ -722,7 +722,7 @@ struct timex32 { extern int do_adjtimex(struct timex *); -asmlinkage long sys32_adjtimex(struct timex32 *utp) +asmlinkage long sys32_adjtimex(struct timex32 __user *utp) { struct timex txc; int ret; @@ -789,12 +789,13 @@ struct __sysctl_args32 { u32 __unused[4]; }; -asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) +asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) { struct __sysctl_args32 tmp; int error; - size_t oldlen, *oldlenp = NULL; - unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; + size_t oldlen; + size_t __user *oldlenp = NULL; + unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; @@ -806,20 +807,20 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) basically copy the whole sysctl.c here, and glibc's __sysctl uses rw memory for the structure anyway. */ - if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) || - put_user(oldlen, (size_t *)addr)) + if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) || + put_user(oldlen, (size_t __user *)addr)) return -EFAULT; - oldlenp = (size_t *)addr; + oldlenp = (size_t __user *)addr; } lock_kernel(); - error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval), - oldlenp, (void *)A(tmp.newval), tmp.newlen); + error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval), + oldlenp, compat_ptr(tmp.newval), tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { - if (get_user(oldlen, (size_t *)addr) || - put_user(oldlen, (u32 *)A(tmp.oldlenp))) + if (get_user(oldlen, (size_t __user *)addr) || + put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp))) error = -EFAULT; } copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); @@ -853,7 +854,7 @@ struct stat64_emu31 { unsigned long st_ino; }; -static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat) +static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) { struct stat64_emu31 tmp; @@ -877,7 +878,7 @@ static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat) return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } -asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf) +asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf) { struct kstat stat; int ret = vfs_stat(filename, &stat); @@ -886,7 +887,7 @@ asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf) return ret; } -asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf) +asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf) { struct kstat stat; int ret = vfs_lstat(filename, &stat); @@ -895,7 +896,7 @@ asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf) return ret; } -asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf) +asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) { struct kstat stat; int ret = vfs_fstat(fd, &stat); @@ -904,6 +905,26 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf) return ret; } +asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename, + struct stat64_emu31 __user* statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_stat64(statbuf, &stat); +out: + return error; +} + /* * Linux/i386 didn't use to be able to handle more than * 4 system call parameters, so these system calls used a memory @@ -952,7 +973,7 @@ out: asmlinkage unsigned long -old32_mmap(struct mmap_arg_struct_emu31 *arg) +old32_mmap(struct mmap_arg_struct_emu31 __user *arg) { struct mmap_arg_struct_emu31 a; int error = -EFAULT; @@ -970,7 +991,7 @@ out: } asmlinkage long -sys32_mmap2(struct mmap_arg_struct_emu31 *arg) +sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) { struct mmap_arg_struct_emu31 a; int error = -EFAULT; @@ -982,7 +1003,7 @@ out: return error; } -asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count) +asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) { if ((compat_ssize_t) count < 0) return -EINVAL; @@ -990,7 +1011,7 @@ asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count) return sys_read(fd, buf, count); } -asmlinkage long sys32_write(unsigned int fd, char * buf, size_t count) +asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) { if ((compat_ssize_t) count < 0) return -EINVAL; @@ -1002,12 +1023,12 @@ asmlinkage long sys32_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; - int *parent_tidptr, *child_tidptr; + int __user *parent_tidptr, *child_tidptr; clone_flags = regs.gprs[3] & 0xffffffffUL; newsp = regs.orig_gpr2 & 0x7fffffffUL; - parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL); - child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL); + parent_tidptr = compat_ptr(regs.gprs[4]); + child_tidptr = compat_ptr(regs.gprs[5]); if (!newsp) newsp = regs.gprs[15]; return do_fork(clone_flags, newsp, ®s, 0, diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index fa2b3bc22f20..5291b5f8788d 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -1,8 +1,7 @@ /* - * arch/s390/kernel/signal32.c + * arch/s390/kernel/compat_signal.c * - * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 2000,2006 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * Gerhard Tonn (ton@de.ibm.com) * @@ -52,8 +51,6 @@ typedef struct struct ucontext32 uc; } rt_sigframe32; -asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); - int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err; @@ -161,66 +158,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) return err; } -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->gprs[2] = -EINTR; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - -asmlinkage int -sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset, - size_t sigsetsize) -{ - sigset_t saveset, newset; - compat_sigset_t set32; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&set32, unewset, sizeof(set32))) - return -EFAULT; - switch (_NSIG_WORDS) { - case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32); - case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32); - case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32); - case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32); - } - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->gprs[2] = -EINTR; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - asmlinkage long sys32_sigaction(int sig, const struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) @@ -258,9 +195,6 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act, return ret; } -int -do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact); - asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact, size_t sigsetsize) @@ -520,7 +454,7 @@ static inline int map_signal(int sig) return sig; } -static void setup_frame32(int sig, struct k_sigaction *ka, +static int setup_frame32(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); @@ -565,13 +499,14 @@ static void setup_frame32(int sig, struct k_sigaction *ka, /* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) goto give_sigsegv; - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } -static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { int err = 0; @@ -615,31 +550,37 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, regs->gprs[2] = map_signal(sig); regs->gprs[3] = (__u64) &frame->info; regs->gprs[4] = (__u64) &frame->uc; - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } /* * OK, we're invoking a handler */ -void +int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { + int ret; + /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(sig, ka, info, oldset, regs); + ret = setup_rt_frame32(sig, ka, info, oldset, regs); else - setup_frame32(sig, ka, oldset, regs); - - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + ret = setup_frame32(sig, ka, oldset, regs); + + if (ret == 0) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + return ret; } diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index cfde1905d07d..dd2d6c3e8df8 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1,9 +1,8 @@ /* -* arch/s390/kernel/sys_wrapper31.S +* arch/s390/kernel/compat_wrapper.S * wrapper for 31 bit compatible system calls. * -* S390 version -* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation +* Copyright (C) IBM Corp. 2000,2006 * Author(s): Gerhard Tonn (ton@de.ibm.com), * Thomas Spatzier (tspat@de.ibm.com) */ @@ -288,7 +287,12 @@ sys32_setregid16_wrapper: llgfr %r3,%r3 # __kernel_old_gid_emu31_t jg sys32_setregid16 # branch to system call -#sys32_sigsuspend_wrapper # done in sigsuspend_glue + .globl sys_sigsuspend_wrapper +sys_sigsuspend_wrapper: + lgfr %r2,%r2 # int + lgfr %r3,%r3 # int + llgfr %r4,%r4 # old_sigset_t + jg sys_sigsuspend .globl compat_sys_sigpending_wrapper compat_sys_sigpending_wrapper: @@ -855,7 +859,11 @@ sys32_rt_sigqueueinfo_wrapper: llgtr %r4,%r4 # siginfo_emu31_t * jg sys32_rt_sigqueueinfo # branch to system call -#sys32_rt_sigsuspend_wrapper # done in rt_sigsuspend_glue + .globl compat_sys_rt_sigsuspend_wrapper +compat_sys_rt_sigsuspend_wrapper: + llgtr %r2,%r2 # compat_sigset_t * + llgfr %r3,%r3 # compat_size_t + jg compat_sys_rt_sigsuspend .globl sys32_pread64_wrapper sys32_pread64_wrapper: @@ -1475,3 +1483,127 @@ sys_inotify_rm_watch_wrapper: lgfr %r2,%r2 # int llgfr %r3,%r3 # u32 jg sys_inotify_rm_watch + + .globl compat_sys_openat_wrapper +compat_sys_openat_wrapper: + llgfr %r2,%r2 # unsigned int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + lgfr %r5,%r5 # int + jg compat_sys_openat + + .globl sys_mkdirat_wrapper +sys_mkdirat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + jg sys_mkdirat + + .globl sys_mknodat_wrapper +sys_mknodat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + llgfr %r5,%r5 # unsigned int + jg sys_mknodat + + .globl sys_fchownat_wrapper +sys_fchownat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + llgfr %r4,%r4 # uid_t + llgfr %r5,%r5 # gid_t + lgfr %r6,%r6 # int + jg sys_fchownat + + .globl compat_sys_futimesat_wrapper +compat_sys_futimesat_wrapper: + llgfr %r2,%r2 # unsigned int + llgtr %r3,%r3 # char * + llgtr %r4,%r4 # struct timeval * + jg compat_sys_futimesat + + .globl sys32_fstatat_wrapper +sys32_fstatat_wrapper: + llgfr %r2,%r2 # unsigned int + llgtr %r3,%r3 # char * + llgtr %r4,%r4 # struct stat64 * + lgfr %r5,%r5 # int + jg sys32_fstatat + + .globl sys_unlinkat_wrapper +sys_unlinkat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + jg sys_unlinkat + + .globl sys_renameat_wrapper +sys_renameat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + llgtr %r5,%r5 # const char * + jg sys_renameat + + .globl sys_linkat_wrapper +sys_linkat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + llgtr %r5,%r5 # const char * + jg sys_linkat + + .globl sys_symlinkat_wrapper +sys_symlinkat_wrapper: + llgtr %r2,%r2 # const char * + lgfr %r3,%r3 # int + llgtr %r4,%r4 # const char * + jg sys_symlinkat + + .globl sys_readlinkat_wrapper +sys_readlinkat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + llgtr %r4,%r4 # char * + lgfr %r5,%r5 # int + jg sys_readlinkat + + .globl sys_fchmodat_wrapper +sys_fchmodat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + llgfr %r4,%r4 # mode_t + jg sys_fchmodat + + .globl sys_faccessat_wrapper +sys_faccessat_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + lgfr %r4,%r4 # int + jg sys_faccessat + + .globl compat_sys_pselect6_wrapper +compat_sys_pselect6_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # fd_set * + llgtr %r4,%r4 # fd_set * + llgtr %r5,%r5 # fd_set * + llgtr %r6,%r6 # struct timespec * + llgt %r0,164(%r15) # void * + stg %r0,160(%r15) + jg compat_sys_pselect6 + + .globl compat_sys_ppoll_wrapper +compat_sys_ppoll_wrapper: + llgtr %r2,%r2 # struct pollfd * + llgfr %r3,%r3 # unsigned int + llgtr %r4,%r4 # struct timespec * + llgtr %r5,%r5 # const sigset_t * + llgfr %r6,%r6 # size_t + jg compat_sys_ppoll + + .globl sys_unshare_wrapper +sys_unshare_wrapper: + llgfr %r2,%r2 # unsigned long + jg sys_unshare diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 27b07730b7b8..b2448487854c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -2,8 +2,7 @@ * arch/s390/kernel/entry.S * S390 low-level entry points. * - * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 1999,2006 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Hartmut Penner (hp@de.ibm.com), * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), @@ -50,9 +49,10 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \ - _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ + _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ + _TIF_MCCK_PENDING) STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER STACK_SIZE = 1 << STACK_SHIFT @@ -251,8 +251,8 @@ sysc_work: bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(sysc_reschedule) - tm __TI_flags+3(%r9),_TIF_SIGPENDING - bo BASED(sysc_sigpending) + tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + bnz BASED(sysc_sigpending) tm __TI_flags+3(%r9),_TIF_RESTART_SVC bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP @@ -276,12 +276,11 @@ sysc_mcck_pending: br %r1 # TIF bit will be cleared by handler # -# _TIF_SIGPENDING is set, call do_signal +# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # sysc_sigpending: ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP la %r2,SP_PTREGS(%r15) # load pt_regs - sr %r3,%r3 # clear *oldset l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal tm __TI_flags+3(%r9),_TIF_RESTART_SVC @@ -397,30 +396,6 @@ sys_rt_sigreturn_glue: l %r1,BASED(.Lrt_sigreturn) br %r1 # branch to sys_sigreturn -# -# sigsuspend and rt_sigsuspend need pt_regs as an additional -# parameter and they have to skip the store of %r2 into the -# user register %r2 because the return value was set in -# sigsuspend and rt_sigsuspend already and must not be overwritten! -# - -sys_sigsuspend_glue: - lr %r5,%r4 # move mask back - lr %r4,%r3 # move history1 parameter - lr %r3,%r2 # move history0 parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - l %r1,BASED(.Lsigsuspend) - la %r14,4(%r14) # skip store of return value - br %r1 # branch to sys_sigsuspend - -sys_rt_sigsuspend_glue: - lr %r4,%r3 # move sigsetsize parameter - lr %r3,%r2 # move unewset parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - l %r1,BASED(.Lrt_sigsuspend) - la %r14,4(%r14) # skip store of return value - br %r1 # branch to sys_rt_sigsuspend - sys_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter l %r1,BASED(.Lsigaltstack) @@ -604,15 +579,16 @@ io_work: lr %r15,%r1 # # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING +# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED +# and _TIF_MCCK_PENDING # io_work_loop: tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(io_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(io_reschedule) - tm __TI_flags+3(%r9),_TIF_SIGPENDING - bo BASED(io_sigpending) + tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + bnz BASED(io_sigpending) b BASED(io_leave) # @@ -636,12 +612,11 @@ io_reschedule: b BASED(io_work_loop) # -# _TIF_SIGPENDING is set, call do_signal +# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # io_sigpending: stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs - sr %r3,%r3 # clear *oldset l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 369ab4413ec7..2ac095bc0e25 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -1,9 +1,8 @@ /* - * arch/s390/kernel/entry.S + * arch/s390/kernel/entry64.S * S390 low-level entry points. * - * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 1999,2006 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Hartmut Penner (hp@de.ibm.com), * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), @@ -53,9 +52,10 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER STACK_SIZE = 1 << STACK_SHIFT -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \ - _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ + _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ + _TIF_MCCK_PENDING) #define BASED(name) name-system_call(%r13) @@ -249,8 +249,8 @@ sysc_work: jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo sysc_reschedule - tm __TI_flags+7(%r9),_TIF_SIGPENDING - jo sysc_sigpending + tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + jnz sysc_sigpending tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP @@ -272,12 +272,11 @@ sysc_mcck_pending: jg s390_handle_mcck # TIF bit will be cleared by handler # -# _TIF_SIGPENDING is set, call do_signal +# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # sysc_sigpending: ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP la %r2,SP_PTREGS(%r15) # load pt_regs - sgr %r3,%r3 # clear *oldset brasl %r14,do_signal # call do_signal tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart @@ -414,52 +413,6 @@ sys32_rt_sigreturn_glue: jg sys32_rt_sigreturn # branch to sys32_sigreturn #endif -# -# sigsuspend and rt_sigsuspend need pt_regs as an additional -# parameter and they have to skip the store of %r2 into the -# user register %r2 because the return value was set in -# sigsuspend and rt_sigsuspend already and must not be overwritten! -# - -sys_sigsuspend_glue: - lgr %r5,%r4 # move mask back - lgr %r4,%r3 # move history1 parameter - lgr %r3,%r2 # move history0 parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - la %r14,6(%r14) # skip store of return value - jg sys_sigsuspend # branch to sys_sigsuspend - -#ifdef CONFIG_COMPAT -sys32_sigsuspend_glue: - llgfr %r4,%r4 # unsigned long - lgr %r5,%r4 # move mask back - lgfr %r3,%r3 # int - lgr %r4,%r3 # move history1 parameter - lgfr %r2,%r2 # int - lgr %r3,%r2 # move history0 parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - la %r14,6(%r14) # skip store of return value - jg sys32_sigsuspend # branch to sys32_sigsuspend -#endif - -sys_rt_sigsuspend_glue: - lgr %r4,%r3 # move sigsetsize parameter - lgr %r3,%r2 # move unewset parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - la %r14,6(%r14) # skip store of return value - jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend - -#ifdef CONFIG_COMPAT -sys32_rt_sigsuspend_glue: - llgfr %r3,%r3 # size_t - lgr %r4,%r3 # move sigsetsize parameter - llgtr %r2,%r2 # sigset_emu31_t * - lgr %r3,%r2 # move unewset parameter - la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - la %r14,6(%r14) # skip store of return value - jg sys32_rt_sigsuspend # branch to sys32_rt_sigsuspend -#endif - sys_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigaltstack # branch to sys_sigreturn @@ -646,15 +599,16 @@ io_work: lgr %r15,%r1 # # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING +# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED +# and _TIF_MCCK_PENDING # io_work_loop: tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo io_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo io_reschedule - tm __TI_flags+7(%r9),_TIF_SIGPENDING - jo io_sigpending + tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + jnz io_sigpending j io_leave # @@ -676,12 +630,11 @@ io_reschedule: j io_work_loop # -# _TIF_SIGPENDING is set, call do_signal +# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # io_sigpending: stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs - slgr %r3,%r3 # clear *oldset brasl %r14,do_signal # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts j io_work_loop diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index f0ed5c642c74..bad81b5832db 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -12,15 +12,16 @@ * on the S390 architecture. */ -#include <asm/cio.h> -#include <asm/setup.h> #include <linux/device.h> #include <linux/mm.h> #include <linux/kexec.h> #include <linux/delay.h> +#include <asm/cio.h> +#include <asm/setup.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/system.h> +#include <asm/smp.h> static void kexec_halt_all_cpus(void *); diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6ae4a77270b5..ae1927e48cfb 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -1,8 +1,7 @@ /* * arch/s390/kernel/signal.c * - * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 1999,2006 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * * Based on Intel version @@ -51,60 +50,24 @@ typedef struct struct ucontext uc; } rt_sigframe; -int do_signal(struct pt_regs *regs, sigset_t *oldset); - /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int -sys_sigsuspend(struct pt_regs * regs, int history0, int history1, - old_sigset_t mask) +sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->gprs[2] = -EINTR; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - -asmlinkage long -sys_rt_sigsuspend(struct pt_regs *regs, sigset_t __user *unewset, - size_t sigsetsize) -{ - sigset_t saveset, newset; - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->gprs[2] = -EINTR; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } + return -ERESTARTNOHAND; } asmlinkage long @@ -306,8 +269,8 @@ static inline int map_signal(int sig) return sig; } -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs * regs) +static int setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs * regs) { sigframe __user *frame; @@ -355,13 +318,14 @@ static void setup_frame(int sig, struct k_sigaction *ka, /* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) goto give_sigsegv; - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { int err = 0; @@ -409,32 +373,39 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->gprs[2] = map_signal(sig); regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[4] = (unsigned long) &frame->uc; - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { + int ret; + /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); else - setup_frame(sig, ka, oldset, regs); + ret = setup_frame(sig, ka, oldset, regs); + + if (ret == 0) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + return ret; } /* @@ -446,12 +417,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +void do_signal(struct pt_regs *regs) { unsigned long retval = 0, continue_addr = 0, restart_addr = 0; siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -460,9 +432,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) * if so. */ if (!user_mode(regs)) - return 1; + return; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; /* Are we from a system call? */ @@ -473,12 +447,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Prepare for system call restart. We do this here so that a debugger will see the already changed PSW. */ - if (retval == -ERESTARTNOHAND || - retval == -ERESTARTSYS || - retval == -ERESTARTNOINTR) { + switch (retval) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: regs->gprs[2] = regs->orig_gpr2; regs->psw.addr = restart_addr; - } else if (retval == -ERESTART_RESTARTBLOCK) { + break; + case -ERESTART_RESTARTBLOCK: regs->gprs[2] = -EINTR; } } @@ -503,17 +479,38 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Whee! Actually deliver the signal. */ #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_31BIT)) { - extern void handle_signal32(unsigned long sig, - struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, - struct pt_regs *regs); - handle_signal32(signr, &ka, &info, oldset, regs); - return 1; + extern int handle_signal32(unsigned long sig, + struct k_sigaction *ka, + siginfo_t *info, + sigset_t *oldset, + struct pt_regs *regs); + if (handle_signal32( + signr, &ka, &info, oldset, regs) == 0) { + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; } #endif - handle_signal(signr, &ka, &info, oldset, regs); - return 1; + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; + } + + /* + * If there's no signal to deliver, we just put the saved sigmask back. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } /* Restart a different system call. */ @@ -522,5 +519,4 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) regs->gprs[2] = __NR_restart_syscall; set_thread_flag(TIF_RESTART_SVC); } - return 0; } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index cbfcfd02a43a..0d1ad5dbe2b1 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -52,7 +52,7 @@ extern volatile int __cpu_logical_map[]; struct _lowcore *lowcore_ptr[NR_CPUS]; cpumask_t cpu_online_map; -cpumask_t cpu_possible_map; +cpumask_t cpu_possible_map = CPU_MASK_ALL; static struct task_struct *current_set[NR_CPUS]; @@ -514,9 +514,6 @@ __init smp_check_cpus(unsigned int max_cpus) num_cpus++; } - for (cpu = 1; cpu < max_cpus; cpu++) - cpu_set(cpu, cpu_possible_map); - printk("Detected %d CPU's\n",(int) num_cpus); printk("Boot cpu address %2X\n", boot_cpu_addr); } @@ -810,7 +807,6 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(0, cpu_online_map); cpu_set(0, cpu_present_map); - cpu_set(0, cpu_possible_map); S390_lowcore.percpu_offset = __per_cpu_offset[0]; current_set[0] = current; } diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 6a63553493c5..e351780bb660 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -122,8 +122,8 @@ out: #ifndef CONFIG_64BIT struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp, *outp, *exp; + struct timeval __user *tvp; }; asmlinkage long old_select(struct sel_arg_struct __user *arg) diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 426d7cafdab3..84921fe8d266 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -80,7 +80,7 @@ NI_SYSCALL /* old sgetmask syscall*/ NI_SYSCALL /* old ssetmask syscall*/ SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper) /* old setreuid16 syscall */ SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper) /* old setregid16 syscall */ -SYSCALL(sys_sigsuspend_glue,sys_sigsuspend_glue,sys32_sigsuspend_glue) +SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper) SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper) SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper) SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */ @@ -187,7 +187,7 @@ SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 1 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait_wrapper) SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper) -SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue) +SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend_wrapper) SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper) /* 180 */ SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper) SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper) /* old chown16 syscall */ @@ -293,5 +293,22 @@ SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper) SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper) SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper) SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init) -SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper) +SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper) /* 285 */ SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper) +NI_SYSCALL /* 287 sys_migrate_pages */ +SYSCALL(sys_openat,sys_openat,compat_sys_openat_wrapper) +SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper) +SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper) /* 290 */ +SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper) +SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper) +SYSCALL(sys_fstatat64,sys_newfstatat,sys32_fstatat_wrapper) +SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper) +SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper) /* 295 */ +SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper) +SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper) +SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper) +SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper) +SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper) /* 300 */ +SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper) +SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper) +SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 7c0fe152a111..fea043b69b91 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -61,9 +61,18 @@ extern unsigned long wall_jiffies; */ unsigned long long sched_clock(void) { - return ((get_clock() - jiffies_timer_cc) * 1000) >> 12; + return ((get_clock() - jiffies_timer_cc) * 125) >> 9; } +/* + * Monotonic_clock - returns # of nanoseconds passed since time_init() + */ +unsigned long long monotonic_clock(void) +{ + return sched_clock(); +} +EXPORT_SYMBOL(monotonic_clock); + void tod_to_timeval(__u64 todval, struct timespec *xtime) { unsigned long long sec; diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5d21e9e6e7b4..a46793beeddd 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -486,7 +486,7 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) info.si_signo = signal; info.si_errno = 0; info.si_code = ILL_ILLOPC; - info.si_addr = (void *) location; + info.si_addr = (void __user *) location; do_trap(interruption_code, signal, "illegal operation", regs, &info); } diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index f20b51ff1d86..e05d087a6eae 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -6,4 +6,4 @@ EXTRA_AFLAGS := -traditional lib-y += delay.o string.o lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) -lib-$(CONFIG_SMP) += spinlock.o
\ No newline at end of file +lib-$(CONFIG_SMP) += spinlock.o diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 2d5cb1385753..b075ab499d05 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -42,8 +42,8 @@ static volatile long cmm_timed_pages_target = 0; static long cmm_timeout_pages = 0; static long cmm_timeout_seconds = 0; -static struct cmm_page_array *cmm_page_list = 0; -static struct cmm_page_array *cmm_timed_page_list = 0; +static struct cmm_page_array *cmm_page_list = NULL; +static struct cmm_page_array *cmm_timed_page_list = NULL; static unsigned long cmm_thread_active = 0; static struct work_struct cmm_thread_starter; @@ -259,7 +259,7 @@ static struct ctl_table cmm_table[]; static int cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { char buf[16], *p; long pages; @@ -300,7 +300,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, static int cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { char buf[64], *p; long pages, seconds; @@ -419,7 +419,7 @@ cmm_init (void) #ifdef CONFIG_CMM_IUCV smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); #endif - INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, 0); + INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL); init_waitqueue_head(&cmm_thread_wait); init_timer(&cmm_timer); return 0; diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 01bc7d589afe..504d56f8ca7f 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -396,14 +396,8 @@ source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" source "arch/sh/boards/renesas/rts7751r2d/Kconfig" -config SH_PCLK_FREQ_BOOL - bool "Set default pclk frequency" - default y if !SH_RTC - default n - config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" - depends on SH_PCLK_FREQ_BOOL default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 default "60000000" if CPU_SUBTYPE_SH7751 default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760 diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c index c46f9154cfd5..123abbbc91e0 100644 --- a/arch/sh/boards/renesas/rts7751r2d/io.c +++ b/arch/sh/boards/renesas/rts7751r2d/io.c @@ -216,24 +216,26 @@ void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count) { volatile __u8 *bp; volatile __u16 *p; + unsigned char *s = addr; if (CHECK_AX88796L_PORT(port)) { p = (volatile unsigned short *)port88796l(port, 0); - while (count--) *((unsigned char *) addr)++ = *p & 0xff; + while (count--) *s++ = *p & 0xff; } else if (PXSEG(port)) - while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port; + while (count--) *s++ = *(volatile unsigned char *)port; else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { bp = (__u8 *)PCI_IOMAP(port); - while (count--) *((volatile unsigned char *) addr)++ = *bp; + while (count--) *s++ = *bp; } else { p = (volatile unsigned short *)port2adr(port); - while (count--) *((unsigned char *) addr)++ = *p & 0xff; + while (count--) *s++ = *p & 0xff; } } void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count) { volatile __u16 *p; + __u16 *s = addr; if (CHECK_AX88796L_PORT(port)) p = (volatile unsigned short *)port88796l(port, 1); @@ -243,7 +245,7 @@ void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count) p = (volatile unsigned short *)PCI_IOMAP(port); else p = (volatile unsigned short *)port2adr(port); - while (count--) *((__u16 *) addr)++ = *p; + while (count--) *s++ = *p; } void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count) @@ -252,8 +254,9 @@ void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count) maybebadio(insl, port); else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { volatile __u32 *p = (__u32 *)PCI_IOMAP(port); + __u32 *s = addr; - while (count--) *((__u32 *) addr)++ = *p; + while (count--) *s++ = *p; } else maybebadio(insl, port); } @@ -262,24 +265,26 @@ void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count) { volatile __u8 *bp; volatile __u16 *p; + const __u8 *s = addr; if (CHECK_AX88796L_PORT(port)) { p = (volatile unsigned short *)port88796l(port, 0); - while (count--) *p = *((unsigned char *) addr)++; + while (count--) *p = *s++; } else if (PXSEG(port)) - while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++; + while (count--) *(volatile unsigned char *)port = *s++; else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { bp = (__u8 *)PCI_IOMAP(port); - while (count--) *bp = *((volatile unsigned char *) addr)++; + while (count--) *bp = *s++; } else { p = (volatile unsigned short *)port2adr(port); - while (count--) *p = *((unsigned char *) addr)++; + while (count--) *p = *s++; } } void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count) { volatile __u16 *p; + const __u16 *s = addr; if (CHECK_AX88796L_PORT(port)) p = (volatile unsigned short *)port88796l(port, 1); @@ -289,7 +294,7 @@ void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count) p = (volatile unsigned short *)PCI_IOMAP(port); else p = (volatile unsigned short *)port2adr(port); - while (count--) *p = *((__u16 *) addr)++; + while (count--) *p = *s++; } void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count) @@ -298,8 +303,9 @@ void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count) maybebadio(outsl, port); else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { volatile __u32 *p = (__u32 *)PCI_IOMAP(port); + const __u32 *s = addr; - while (count--) *p = *((__u32 *) addr)++; + while (count--) *p = *s++; } else maybebadio(outsl, port); } diff --git a/arch/sh/boards/superh/microdev/io.c b/arch/sh/boards/superh/microdev/io.c index fe83b2c03076..1ed7f880b8c7 100644 --- a/arch/sh/boards/superh/microdev/io.c +++ b/arch/sh/boards/superh/microdev/io.c @@ -16,7 +16,7 @@ #include <linux/pci.h> #include <linux/wait.h> #include <asm/io.h> -#include <asm/mach/io.h> +#include <asm/microdev.h> /* * we need to have a 'safe' address to re-direct all I/O requests @@ -52,8 +52,90 @@ #define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */ #define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */ -#define PORT2ADDR(x) (microdev_isa_port2addr(x)) +/* + * map I/O ports to memory-mapped addresses + */ +static unsigned long microdev_isa_port2addr(unsigned long offset) +{ + unsigned long result; + + if ((offset >= IO_LAN91C111_BASE) && + (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { + /* + * SMSC LAN91C111 Ethernet chip + */ + result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE; + } else if ((offset >= IO_SUPERIO_BASE) && + (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * Configuration Registers + */ + result = IO_SUPERIO_PHYS + (offset << 1); +#if 0 + } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG || + offset == KBD_STATUS_REG) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * PS/2 Keyboard + Mouse (ports 0x60 and 0x64). + */ + result = IO_SUPERIO_PHYS + (offset << 1); +#endif + } else if (((offset >= IO_IDE1_BASE) && + (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) || + (offset == IO_IDE1_MISC)) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * IDE #1 + */ + result = IO_SUPERIO_PHYS + (offset << 1); + } else if (((offset >= IO_IDE2_BASE) && + (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) || + (offset == IO_IDE2_MISC)) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * IDE #2 + */ + result = IO_SUPERIO_PHYS + (offset << 1); + } else if ((offset >= IO_SERIAL1_BASE) && + (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * Serial #1 + */ + result = IO_SUPERIO_PHYS + (offset << 1); + } else if ((offset >= IO_SERIAL2_BASE) && + (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) { + /* + * SMSC FDC37C93xAPM SuperIO chip + * + * Serial #2 + */ + result = IO_SUPERIO_PHYS + (offset << 1); + } else if ((offset >= IO_ISP1161_BASE) && + (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) { + /* + * Philips USB ISP1161x chip + */ + result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE; + } else { + /* + * safe default. + */ + printk("Warning: unexpected port in %s( offset = 0x%lx )\n", + __FUNCTION__, offset); + result = PVR; + } + + return result; +} +#define PORT2ADDR(x) (microdev_isa_port2addr(x)) static inline void delay(void) { @@ -94,6 +176,17 @@ unsigned int microdev_inl(unsigned long port) return *(volatile unsigned int*)PORT2ADDR(port); } +void microdev_outw(unsigned short b, unsigned long port) +{ +#ifdef CONFIG_PCI + if (port >= PCIBIOS_MIN_IO) { + microdev_pci_outw(b, port); + return; + } +#endif + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + void microdev_outb(unsigned char b, unsigned long port) { #ifdef CONFIG_PCI @@ -158,17 +251,6 @@ void microdev_outb(unsigned char b, unsigned long port) } } -void microdev_outw(unsigned short b, unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) { - microdev_pci_outw(b, port); - return; - } -#endif - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - void microdev_outl(unsigned int b, unsigned long port) { #ifdef CONFIG_PCI @@ -284,87 +366,3 @@ void microdev_outsl(unsigned long port, const void *buffer, unsigned long count) while (count--) *port_addr = *buf++; } - -/* - * map I/O ports to memory-mapped addresses - */ -unsigned long microdev_isa_port2addr(unsigned long offset) -{ - unsigned long result; - - if ((offset >= IO_LAN91C111_BASE) && - (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { - /* - * SMSC LAN91C111 Ethernet chip - */ - result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE; - } else if ((offset >= IO_SUPERIO_BASE) && - (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * Configuration Registers - */ - result = IO_SUPERIO_PHYS + (offset << 1); -#if 0 - } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG || - offset == KBD_STATUS_REG) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * PS/2 Keyboard + Mouse (ports 0x60 and 0x64). - */ - result = IO_SUPERIO_PHYS + (offset << 1); -#endif - } else if (((offset >= IO_IDE1_BASE) && - (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) || - (offset == IO_IDE1_MISC)) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * IDE #1 - */ - result = IO_SUPERIO_PHYS + (offset << 1); - } else if (((offset >= IO_IDE2_BASE) && - (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) || - (offset == IO_IDE2_MISC)) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * IDE #2 - */ - result = IO_SUPERIO_PHYS + (offset << 1); - } else if ((offset >= IO_SERIAL1_BASE) && - (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * Serial #1 - */ - result = IO_SUPERIO_PHYS + (offset << 1); - } else if ((offset >= IO_SERIAL2_BASE) && - (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * Serial #2 - */ - result = IO_SUPERIO_PHYS + (offset << 1); - } else if ((offset >= IO_ISP1161_BASE) && - (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) { - /* - * Philips USB ISP1161x chip - */ - result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE; - } else { - /* - * safe default. - */ - printk("Warning: unexpected port in %s( offset = 0x%lx )\n", - __FUNCTION__, offset); - result = PVR; - } - - return result; -} - diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c index 1395c1e65da4..efcbd86b7cd2 100644 --- a/arch/sh/boards/superh/microdev/irq.c +++ b/arch/sh/boards/superh/microdev/irq.c @@ -15,7 +15,7 @@ #include <asm/system.h> #include <asm/io.h> -#include <asm/mach/irq.h> +#include <asm/microdev.h> #define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */ diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c index 1c1d65fb12df..892b14d31405 100644 --- a/arch/sh/boards/superh/microdev/setup.c +++ b/arch/sh/boards/superh/microdev/setup.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) * Copyright (C) 2003, 2004 SuperH, Inc. - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004, 2005 Paul Mundt * * SuperH SH4-202 MicroDev board support. * @@ -15,11 +15,10 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/ioport.h> +#include <video/s1d13xxxfb.h> +#include <asm/microdev.h> #include <asm/io.h> -#include <asm/mach/irq.h> -#include <asm/mach/io.h> #include <asm/machvec.h> -#include <asm/machvec_init.h> extern void microdev_heartbeat(void); @@ -51,8 +50,6 @@ struct sh_machine_vector mv_sh4202_microdev __initmv = { .mv_outsw = microdev_outsw, .mv_outsl = microdev_outsl, - .mv_isa_port2addr = microdev_isa_port2addr, - .mv_init_irq = init_microdev_irq, #ifdef CONFIG_HEARTBEAT @@ -142,16 +139,161 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -static int __init smc91x_setup(void) +#ifdef CONFIG_FB_S1D13XXX +static struct s1d13xxxfb_regval s1d13806_initregs[] = { + { S1DREG_MISC, 0x00 }, + { S1DREG_COM_DISP_MODE, 0x00 }, + { S1DREG_GPIO_CNF0, 0x00 }, + { S1DREG_GPIO_CNF1, 0x00 }, + { S1DREG_GPIO_CTL0, 0x00 }, + { S1DREG_GPIO_CTL1, 0x00 }, + { S1DREG_CLK_CNF, 0x02 }, + { S1DREG_LCD_CLK_CNF, 0x01 }, + { S1DREG_CRT_CLK_CNF, 0x03 }, + { S1DREG_MPLUG_CLK_CNF, 0x03 }, + { S1DREG_CPU2MEM_WST_SEL, 0x02 }, + { S1DREG_SDRAM_REF_RATE, 0x03 }, + { S1DREG_SDRAM_TC0, 0x00 }, + { S1DREG_SDRAM_TC1, 0x01 }, + { S1DREG_MEM_CNF, 0x80 }, + { S1DREG_PANEL_TYPE, 0x25 }, + { S1DREG_MOD_RATE, 0x00 }, + { S1DREG_LCD_DISP_HWIDTH, 0x63 }, + { S1DREG_LCD_NDISP_HPER, 0x1e }, + { S1DREG_TFT_FPLINE_START, 0x06 }, + { S1DREG_TFT_FPLINE_PWIDTH, 0x03 }, + { S1DREG_LCD_DISP_VHEIGHT0, 0x57 }, + { S1DREG_LCD_DISP_VHEIGHT1, 0x02 }, + { S1DREG_LCD_NDISP_VPER, 0x00 }, + { S1DREG_TFT_FPFRAME_START, 0x0a }, + { S1DREG_TFT_FPFRAME_PWIDTH, 0x81 }, + { S1DREG_LCD_DISP_MODE, 0x03 }, + { S1DREG_LCD_MISC, 0x00 }, + { S1DREG_LCD_DISP_START0, 0x00 }, + { S1DREG_LCD_DISP_START1, 0x00 }, + { S1DREG_LCD_DISP_START2, 0x00 }, + { S1DREG_LCD_MEM_OFF0, 0x90 }, + { S1DREG_LCD_MEM_OFF1, 0x01 }, + { S1DREG_LCD_PIX_PAN, 0x00 }, + { S1DREG_LCD_DISP_FIFO_HTC, 0x00 }, + { S1DREG_LCD_DISP_FIFO_LTC, 0x00 }, + { S1DREG_CRT_DISP_HWIDTH, 0x63 }, + { S1DREG_CRT_NDISP_HPER, 0x1f }, + { S1DREG_CRT_HRTC_START, 0x04 }, + { S1DREG_CRT_HRTC_PWIDTH, 0x8f }, + { S1DREG_CRT_DISP_VHEIGHT0, 0x57 }, + { S1DREG_CRT_DISP_VHEIGHT1, 0x02 }, + { S1DREG_CRT_NDISP_VPER, 0x1b }, + { S1DREG_CRT_VRTC_START, 0x00 }, + { S1DREG_CRT_VRTC_PWIDTH, 0x83 }, + { S1DREG_TV_OUT_CTL, 0x10 }, + { S1DREG_CRT_DISP_MODE, 0x05 }, + { S1DREG_CRT_DISP_START0, 0x00 }, + { S1DREG_CRT_DISP_START1, 0x00 }, + { S1DREG_CRT_DISP_START2, 0x00 }, + { S1DREG_CRT_MEM_OFF0, 0x20 }, + { S1DREG_CRT_MEM_OFF1, 0x03 }, + { S1DREG_CRT_PIX_PAN, 0x00 }, + { S1DREG_CRT_DISP_FIFO_HTC, 0x00 }, + { S1DREG_CRT_DISP_FIFO_LTC, 0x00 }, + { S1DREG_LCD_CUR_CTL, 0x00 }, + { S1DREG_LCD_CUR_START, 0x01 }, + { S1DREG_LCD_CUR_XPOS0, 0x00 }, + { S1DREG_LCD_CUR_XPOS1, 0x00 }, + { S1DREG_LCD_CUR_YPOS0, 0x00 }, + { S1DREG_LCD_CUR_YPOS1, 0x00 }, + { S1DREG_LCD_CUR_BCTL0, 0x00 }, + { S1DREG_LCD_CUR_GCTL0, 0x00 }, + { S1DREG_LCD_CUR_RCTL0, 0x00 }, + { S1DREG_LCD_CUR_BCTL1, 0x1f }, + { S1DREG_LCD_CUR_GCTL1, 0x3f }, + { S1DREG_LCD_CUR_RCTL1, 0x1f }, + { S1DREG_LCD_CUR_FIFO_HTC, 0x00 }, + { S1DREG_CRT_CUR_CTL, 0x00 }, + { S1DREG_CRT_CUR_START, 0x01 }, + { S1DREG_CRT_CUR_XPOS0, 0x00 }, + { S1DREG_CRT_CUR_XPOS1, 0x00 }, + { S1DREG_CRT_CUR_YPOS0, 0x00 }, + { S1DREG_CRT_CUR_YPOS1, 0x00 }, + { S1DREG_CRT_CUR_BCTL0, 0x00 }, + { S1DREG_CRT_CUR_GCTL0, 0x00 }, + { S1DREG_CRT_CUR_RCTL0, 0x00 }, + { S1DREG_CRT_CUR_BCTL1, 0x1f }, + { S1DREG_CRT_CUR_GCTL1, 0x3f }, + { S1DREG_CRT_CUR_RCTL1, 0x1f }, + { S1DREG_CRT_CUR_FIFO_HTC, 0x00 }, + { S1DREG_BBLT_CTL0, 0x00 }, + { S1DREG_BBLT_CTL1, 0x00 }, + { S1DREG_BBLT_CC_EXP, 0x00 }, + { S1DREG_BBLT_OP, 0x00 }, + { S1DREG_BBLT_SRC_START0, 0x00 }, + { S1DREG_BBLT_SRC_START1, 0x00 }, + { S1DREG_BBLT_SRC_START2, 0x00 }, + { S1DREG_BBLT_DST_START0, 0x00 }, + { S1DREG_BBLT_DST_START1, 0x00 }, + { S1DREG_BBLT_DST_START2, 0x00 }, + { S1DREG_BBLT_MEM_OFF0, 0x00 }, + { S1DREG_BBLT_MEM_OFF1, 0x00 }, + { S1DREG_BBLT_WIDTH0, 0x00 }, + { S1DREG_BBLT_WIDTH1, 0x00 }, + { S1DREG_BBLT_HEIGHT0, 0x00 }, + { S1DREG_BBLT_HEIGHT1, 0x00 }, + { S1DREG_BBLT_BGC0, 0x00 }, + { S1DREG_BBLT_BGC1, 0x00 }, + { S1DREG_BBLT_FGC0, 0x00 }, + { S1DREG_BBLT_FGC1, 0x00 }, + { S1DREG_LKUP_MODE, 0x00 }, + { S1DREG_LKUP_ADDR, 0x00 }, + { S1DREG_PS_CNF, 0x10 }, + { S1DREG_PS_STATUS, 0x00 }, + { S1DREG_CPU2MEM_WDOGT, 0x00 }, + { S1DREG_COM_DISP_MODE, 0x02 }, +}; + +static struct s1d13xxxfb_pdata s1d13806_platform_data = { + .initregs = s1d13806_initregs, + .initregssize = ARRAY_SIZE(s1d13806_initregs), +}; + +static struct resource s1d13806_resources[] = { + [0] = { + .start = 0x07200000, + .end = 0x07200000 + 0x00200000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0x07000000, + .end = 0x07000000 + 0x00200000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device s1d13806_device = { + .name = "s1d13806fb", + .id = -1, + .num_resources = ARRAY_SIZE(s1d13806_resources), + .resource = s1d13806_resources, + + .dev = { + .platform_data = &s1d13806_platform_data, + }, +}; +#endif + +static struct platform_device *microdev_devices[] __initdata = { + &smc91x_device, +#ifdef CONFIG_FB_S1D13XXX + &s1d13806_device, +#endif +}; + +static int __init microdev_devices_setup(void) { - return platform_device_register(&smc91x_device); + return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices)); } -__initcall(smc91x_setup); +__initcall(microdev_devices_setup); - /* - * Initialize the board - */ void __init platform_setup(void) { int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul); diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile index cffc21031e71..7d18f408b0c5 100644 --- a/arch/sh/boards/unknown/Makefile +++ b/arch/sh/boards/unknown/Makefile @@ -2,5 +2,5 @@ # Makefile for unknown SH boards # -obj-y := mach.o io.o setup.o +obj-y := setup.o diff --git a/arch/sh/boards/unknown/io.c b/arch/sh/boards/unknown/io.c deleted file mode 100644 index 8f3f17267bd9..000000000000 --- a/arch/sh/boards/unknown/io.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * linux/arch/sh/kernel/io_unknown.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * I/O routine for unknown hardware. - */ - -static unsigned int unknown_handler(void) -{ - return 0; -} - -#define UNKNOWN_ALIAS(fn) \ - void unknown_##fn(void) __attribute__ ((alias ("unknown_handler"))); - -UNKNOWN_ALIAS(inb) -UNKNOWN_ALIAS(inw) -UNKNOWN_ALIAS(inl) -UNKNOWN_ALIAS(outb) -UNKNOWN_ALIAS(outw) -UNKNOWN_ALIAS(outl) -UNKNOWN_ALIAS(inb_p) -UNKNOWN_ALIAS(inw_p) -UNKNOWN_ALIAS(inl_p) -UNKNOWN_ALIAS(outb_p) -UNKNOWN_ALIAS(outw_p) -UNKNOWN_ALIAS(outl_p) -UNKNOWN_ALIAS(insb) -UNKNOWN_ALIAS(insw) -UNKNOWN_ALIAS(insl) -UNKNOWN_ALIAS(outsb) -UNKNOWN_ALIAS(outsw) -UNKNOWN_ALIAS(outsl) -UNKNOWN_ALIAS(readb) -UNKNOWN_ALIAS(readw) -UNKNOWN_ALIAS(readl) -UNKNOWN_ALIAS(writeb) -UNKNOWN_ALIAS(writew) -UNKNOWN_ALIAS(writel) -UNKNOWN_ALIAS(isa_port2addr) -UNKNOWN_ALIAS(ioremap) -UNKNOWN_ALIAS(iounmap) diff --git a/arch/sh/boards/unknown/mach.c b/arch/sh/boards/unknown/mach.c deleted file mode 100644 index ad0bcc60a640..000000000000 --- a/arch/sh/boards/unknown/mach.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_unknown.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine specific code for an unknown machine (internal peripherials only) - */ - -#include <linux/config.h> -#include <linux/init.h> - -#include <asm/machvec.h> -#include <asm/machvec_init.h> - -#include <asm/io_unknown.h> - -#include <asm/rtc.h> -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_unknown __initmv = { -#if defined(CONFIG_CPU_SH4) - .mv_nr_irqs = 48, -#elif defined(CONFIG_CPU_SUBTYPE_SH7708) - .mv_nr_irqs = 32, -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) - .mv_nr_irqs = 61, -#endif - - .mv_inb = unknown_inb, - .mv_inw = unknown_inw, - .mv_inl = unknown_inl, - .mv_outb = unknown_outb, - .mv_outw = unknown_outw, - .mv_outl = unknown_outl, - - .mv_inb_p = unknown_inb_p, - .mv_inw_p = unknown_inw_p, - .mv_inl_p = unknown_inl_p, - .mv_outb_p = unknown_outb_p, - .mv_outw_p = unknown_outw_p, - .mv_outl_p = unknown_outl_p, - - .mv_insb = unknown_insb, - .mv_insw = unknown_insw, - .mv_insl = unknown_insl, - .mv_outsb = unknown_outsb, - .mv_outsw = unknown_outsw, - .mv_outsl = unknown_outsl, - - .mv_readb = unknown_readb, - .mv_readw = unknown_readw, - .mv_readl = unknown_readl, - .mv_writeb = unknown_writeb, - .mv_writew = unknown_writew, - .mv_writel = unknown_writel, - - .mv_ioremap = unknown_ioremap, - .mv_iounmap = unknown_iounmap, - - .mv_isa_port2addr = unknown_isa_port2addr, -}; -ALIAS_MV(unknown) diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c index 7d772a6f8865..02e84f03f45c 100644 --- a/arch/sh/boards/unknown/setup.c +++ b/arch/sh/boards/unknown/setup.c @@ -7,10 +7,20 @@ * License. See linux/COPYING for more information. * * Setup code for an unknown machine (internal peripherials only) + * + * This is the simplest of all boards, and serves only as a quick and dirty + * method to start debugging a new board during bring-up until proper board + * setup code is written. */ - #include <linux/config.h> #include <linux/init.h> +#include <asm/machvec.h> +#include <asm/irq.h> + +struct sh_machine_vector mv_unknown __initmv = { + .mv_nr_irqs = NR_IRQS, +}; +ALIAS_MV(unknown) const char *get_system_type(void) { diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c index 3d9a02c093a3..07e8b9c5a531 100644 --- a/arch/sh/cchips/voyagergx/consistent.c +++ b/arch/sh/cchips/voyagergx/consistent.c @@ -15,7 +15,7 @@ #include <linux/module.h> #include <linux/device.h> #include <asm/io.h> -#include <asm/bus-sh.h> + struct voya_alloc_entry { struct list_head list; @@ -30,12 +30,13 @@ static LIST_HEAD(voya_alloc_list); #define OHCI_HCCA_SIZE 0x100 #define OHCI_SRAM_SIZE 0x10000 +#define VOYAGER_OHCI_NAME "voyager-ohci" + void *voyagergx_consistent_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t flag) { struct list_head *list = &voya_alloc_list; struct voya_alloc_entry *entry; - struct sh_dev *shdev = to_sh_dev(dev); unsigned long start, end; unsigned long flags; @@ -46,9 +47,7 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size, * * Everything else goes through consistent_alloc(). */ - if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || - (dev->bus == &sh_bus_types[SH_BUS_VIRT] && - shdev->dev_id != SH_DEV_ID_USB_OHCI)) + if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME)) return NULL; start = OHCI_SRAM_START + OHCI_HCCA_SIZE; @@ -98,12 +97,9 @@ int voyagergx_consistent_free(struct device *dev, size_t size, void *vaddr, dma_addr_t handle) { struct voya_alloc_entry *entry; - struct sh_dev *shdev = to_sh_dev(dev); unsigned long flags; - if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || - (dev->bus == &sh_bus_types[SH_BUS_VIRT] && - shdev->dev_id != SH_DEV_ID_USB_OHCI)) + if (!dev || strcmp(dev->driver->name, VOYAGER_OHCI_NAME)) return -EINVAL; spin_lock_irqsave(&voya_list_lock, flags); @@ -123,4 +119,3 @@ int voyagergx_consistent_free(struct device *dev, size_t size, EXPORT_SYMBOL(voyagergx_consistent_alloc); EXPORT_SYMBOL(voyagergx_consistent_free); - diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c index 1b6ac523b458..2ee330b3c38f 100644 --- a/arch/sh/cchips/voyagergx/irq.c +++ b/arch/sh/cchips/voyagergx/irq.c @@ -163,7 +163,12 @@ int voyagergx_irq_demux(int irq) return irq; } -static struct irqaction irq0 = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL}; +static struct irqaction irq0 = { + .name = "voyagergx", + .handler = voyagergx_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, +}; void __init setup_voyagergx_irq(void) { diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig index a3bd280b53d6..ab3db76d1e51 100644 --- a/arch/sh/configs/microdev_defconfig +++ b/arch/sh/configs/microdev_defconfig @@ -1,10 +1,9 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-sh -# Wed Mar 2 15:09:41 2005 +# Linux kernel version: 2.6.16-rc1 +# Fri Jan 27 19:43:20 2006 # CONFIG_SUPERH=y -CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y @@ -17,11 +16,13 @@ CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_POSIX_MQUEUE is not set @@ -29,22 +30,29 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -52,6 +60,24 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_MODULES is not set # +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# # System type # # CONFIG_SH_SOLUTION_ENGINE is not set @@ -61,9 +87,7 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_STB1_HARP is not set # CONFIG_SH_STB1_OVERDRIVE is not set -# CONFIG_SH_HP620 is not set -# CONFIG_SH_HP680 is not set -# CONFIG_SH_HP690 is not set +# CONFIG_SH_HP6XX is not set # CONFIG_SH_CQREEK is not set # CONFIG_SH_DMIDA is not set # CONFIG_SH_EC3104 is not set @@ -78,45 +102,94 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_SH_SECUREEDGE5410 is not set # CONFIG_SH_HS7751RVOIP is not set # CONFIG_SH_RTS7751R2D is not set +# CONFIG_SH_R7780RP is not set # CONFIG_SH_EDOSK7705 is not set CONFIG_SH_SH4202_MICRODEV=y +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set # CONFIG_SH_UNKNOWN is not set -# CONFIG_CPU_SH2 is not set -# CONFIG_CPU_SH3 is not set + +# +# Processor selection +# CONFIG_CPU_SH4=y + +# +# SH-2 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7604 is not set + +# +# SH-3 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set # CONFIG_CPU_SUBTYPE_SH7709 is not set + +# +# SH-4 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set # CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH73180 is not set +CONFIG_CPU_SUBTYPE_SH4_202=y + +# +# ST40 Processor Support +# # CONFIG_CPU_SUBTYPE_ST40STB1 is not set # CONFIG_CPU_SUBTYPE_ST40GX1 is not set -CONFIG_CPU_SUBTYPE_SH4_202=y + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# Memory management options +# CONFIG_MMU=y -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttySC0,115200" +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x04000000 -CONFIG_MEMORY_SET=y -# CONFIG_MEMORY_OVERRIDE is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_RTC=y CONFIG_SH_FPU=y -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_PREEMPT=y -# CONFIG_UBC_WAKEUP is not set -# CONFIG_SH_WRITETHROUGH is not set -# CONFIG_SH_OCRAM is not set # CONFIG_SH_STORE_QUEUES is not set -# CONFIG_SMP is not set -CONFIG_SH_PCLK_CALC=y -CONFIG_SH_PCLK_FREQ=65986048 +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y + +# +# Timer support +# +CONFIG_SH_TMU=y +CONFIG_SH_PCLK_FREQ=66000000 # # CPU Frequency scaling @@ -137,20 +210,31 @@ CONFIG_NR_ONCHIP_DMA_CHANNELS=4 CONFIG_HEARTBEAT=y # -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# Kernel features # -CONFIG_ISA=y -# CONFIG_PCI is not set +# CONFIG_KEXEC is not set +CONFIG_PREEMPT=y +# CONFIG_SMP is not set # -# PCCARD (PCMCIA/CardBus) support +# Boot options # -# CONFIG_PCCARD is not set +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC0,115200" # -# PC-card bridges +# Bus options # -CONFIG_PCMCIA_PROBE=y +# CONFIG_SUPERHYWAY is not set +# CONFIG_PCI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set # # PCI Hotplug Support @@ -164,9 +248,79 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # -# SH initrd options +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_EMBEDDED_RAMDISK is not set +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -180,6 +334,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -192,13 +351,10 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices # -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set @@ -206,17 +362,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set # @@ -241,9 +387,7 @@ CONFIG_BLK_DEV_IDECD=y # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y -CONFIG_IDE_SH=y # CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -251,14 +395,10 @@ CONFIG_IDE_SH=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -266,6 +406,7 @@ CONFIG_IDE_SH=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -276,69 +417,8 @@ CONFIG_IDE_SH=y # # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -# CONFIG_UNIX is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -346,9 +426,9 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # -# ARCnet devices +# PHY device support # -# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) @@ -356,17 +436,7 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_STNIC is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set CONFIG_SMC91X=y -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) @@ -379,7 +449,6 @@ CONFIG_SMC91X=y # # Token Ring devices # -# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -394,6 +463,8 @@ CONFIG_SMC91X=y # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -411,20 +482,10 @@ CONFIG_SMC91X=y # CONFIG_INPUT is not set # -# Userland interfaces -# - -# -# Input I/O drivers +# Hardware I/O ports # -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - -# -# Input Device Drivers -# +# CONFIG_GAMEPORT is not set # # Character devices @@ -464,24 +525,46 @@ CONFIG_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# # I2C support # # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set # +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -508,7 +591,7 @@ CONFIG_RTC=y # CONFIG_USB_ARCH_HAS_OHCI is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -524,13 +607,21 @@ CONFIG_RTC=y # # InfiniBand support # -# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# EDAC - error detection and reporting (RAS) +# # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set @@ -540,17 +631,17 @@ CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -574,16 +665,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -607,12 +694,14 @@ CONFIG_RAMFS=y # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y @@ -622,6 +711,7 @@ CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -681,8 +771,10 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_DEBUG_PREEMPT=y +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FRAME_POINTER is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set @@ -706,6 +798,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set @@ -730,5 +823,6 @@ CONFIG_CRYPTO_DES=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 7a86eeb22655..f05cd96f8867 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ io.o io_generic.o sh_ksyms.o -obj-y += cpu/ +obj-y += cpu/ timers/ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_CF_ENABLER) += cf-enabler.o diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index 5bfc33bec5d0..59d5b748752f 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y += irq/ init.o bus.o clock.o +obj-y += irq/ init.o clock.o obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) += sh3/ diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c deleted file mode 100644 index fc6c4bd40c65..000000000000 --- a/arch/sh/kernel/cpu/bus.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * arch/sh/kernel/cpu/bus.c - * - * Virtual bus for SuperH. - * - * Copyright (C) 2004 Paul Mundt - * - * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written - * by: - * - * Copyright (C) 2003 - 2004 Nokia Corporation - * Written by Tony Lindgren <tony@atomide.com> - * Portions of code based on sa1111.c. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/module.h> -#include <asm/bus-sh.h> - -static int sh_bus_match(struct device *dev, struct device_driver *drv) -{ - struct sh_driver *shdrv = to_sh_driver(drv); - struct sh_dev *shdev = to_sh_dev(dev); - - return shdev->dev_id == shdrv->dev_id; -} - -static int sh_bus_suspend(struct device *dev, pm_message_t state) -{ - struct sh_dev *shdev = to_sh_dev(dev); - struct sh_driver *shdrv = to_sh_driver(dev->driver); - - if (shdrv && shdrv->suspend) - return shdrv->suspend(shdev, state); - - return 0; -} - -static int sh_bus_resume(struct device *dev) -{ - struct sh_dev *shdev = to_sh_dev(dev); - struct sh_driver *shdrv = to_sh_driver(dev->driver); - - if (shdrv && shdrv->resume) - return shdrv->resume(shdev); - - return 0; -} - -static int sh_device_probe(struct device *dev) -{ - struct sh_dev *shdev = to_sh_dev(dev); - struct sh_driver *shdrv = to_sh_driver(dev->driver); - - if (shdrv && shdrv->probe) - return shdrv->probe(shdev); - - return -ENODEV; -} - -static int sh_device_remove(struct device *dev) -{ - struct sh_dev *shdev = to_sh_dev(dev); - struct sh_driver *shdrv = to_sh_driver(dev->driver); - - if (shdrv && shdrv->remove) - return shdrv->remove(shdev); - - return 0; -} - -static struct device sh_bus_devices[SH_NR_BUSES] = { - { - .bus_id = SH_BUS_NAME_VIRT, - }, -}; - -struct bus_type sh_bus_types[SH_NR_BUSES] = { - { - .name = SH_BUS_NAME_VIRT, - .match = sh_bus_match, - .probe = sh_bus_probe, - .remove = sh_bus_remove, - .suspend = sh_bus_suspend, - .resume = sh_bus_resume, - }, -}; - -int sh_device_register(struct sh_dev *dev) -{ - if (!dev) - return -EINVAL; - - if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) { - printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n", - __FUNCTION__, dev->name, dev->bus_id); - return -EINVAL; - } - - dev->dev.parent = &sh_bus_devices[dev->bus_id]; - dev->dev.bus = &sh_bus_types[dev->bus_id]; - - /* This is needed for USB OHCI to work */ - if (dev->dma_mask) - dev->dev.dma_mask = dev->dma_mask; - if (dev->coherent_dma_mask) - dev->dev.coherent_dma_mask = dev->coherent_dma_mask; - - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u", - dev->name, dev->dev_id); - - printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n", - dev->dev.bus_id, dev->dev.parent->bus_id); - - return device_register(&dev->dev); -} - -void sh_device_unregister(struct sh_dev *dev) -{ - device_unregister(&dev->dev); -} - -int sh_driver_register(struct sh_driver *drv) -{ - if (!drv) - return -EINVAL; - - if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) { - printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n", - __FUNCTION__, drv->bus_id, drv->dev_id); - return -EINVAL; - } - - drv->drv.bus = &sh_bus_types[drv->bus_id]; - - return driver_register(&drv->drv); -} - -void sh_driver_unregister(struct sh_driver *drv) -{ - driver_unregister(&drv->drv); -} - -static int __init sh_bus_init(void) -{ - int i, ret = 0; - - for (i = 0; i < SH_NR_BUSES; i++) { - ret = device_register(&sh_bus_devices[i]); - if (ret != 0) { - printk(KERN_ERR "Unable to register bus device %s\n", - sh_bus_devices[i].bus_id); - continue; - } - - ret = bus_register(&sh_bus_types[i]); - if (ret != 0) { - printk(KERN_ERR "Unable to register bus %s\n", - sh_bus_types[i].name); - device_unregister(&sh_bus_devices[i]); - } - } - - printk(KERN_INFO "SH Virtual Bus initialized\n"); - - return ret; -} - -static void __exit sh_bus_exit(void) -{ - int i; - - for (i = 0; i < SH_NR_BUSES; i++) { - bus_unregister(&sh_bus_types[i]); - device_unregister(&sh_bus_devices[i]); - } -} - -module_init(sh_bus_init); -module_exit(sh_bus_exit); - -MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); -MODULE_DESCRIPTION("SH Virtual Bus"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(sh_bus_types); -EXPORT_SYMBOL(sh_device_register); -EXPORT_SYMBOL(sh_device_unregister); -EXPORT_SYMBOL(sh_driver_register); -EXPORT_SYMBOL(sh_driver_unregister); - diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 989e7fdd524d..97fa37f42b84 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -38,9 +38,7 @@ static DECLARE_MUTEX(clock_list_sem); static struct clk master_clk = { .name = "master_clk", .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, -#ifdef CONFIG_SH_PCLK_FREQ_BOOL .rate = CONFIG_SH_PCLK_FREQ, -#endif }; static struct clk module_clk = { @@ -227,16 +225,7 @@ int __init clk_init(void) { int i, ret = 0; - if (unlikely(!master_clk.rate)) - /* - * NOTE: This will break if the default divisor has been - * changed. - * - * No one should be changing the default on us however, - * expect that a sane value for CONFIG_SH_PCLK_FREQ will - * be defined in the event of a different divisor. - */ - master_clk.rate = get_timer_frequency() * 4; + BUG_ON(unlikely(!master_clk.rate)); for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) { struct clk *clk = onchip_clocks[i]; diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index fdbd718ae5c6..e55150ed0856 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -108,8 +108,7 @@ static void end_ipr_irq(unsigned int irq) enable_ipr_irq(irq); } -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, - int priority, int maskpos) +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) { disable_irq_nosync(irq); ipr_data[irq].addr = addr; @@ -123,44 +122,44 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, void __init init_IRQ(void) { #ifndef CONFIG_CPU_SUBTYPE_SH7780 - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0); - make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0); + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); + make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); #if defined(CONFIG_SH_RTC) - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); #endif #ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); #endif #ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0); + make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY); + make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); + make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); + make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); #endif #ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); #endif #ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ @@ -175,12 +174,12 @@ void __init init_IRQ(void) * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0); + make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); + make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); + make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); + make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); + make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); + make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); #endif #endif diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index fb6368159dd0..a440d36ee618 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -16,6 +16,7 @@ #include <linux/config.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> +#include <asm/cpu/mmu_context.h> #include <asm/unistd.h> #if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE) @@ -75,23 +76,6 @@ ENOSYS = 38 EINVAL = 22 -#if defined(CONFIG_CPU_SH3) -TRA = 0xffffffd0 -EXPEVT = 0xffffffd4 -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) -INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000) -#else -INTEVT = 0xffffffd8 -#endif -MMU_TEA = 0xfffffffc ! TLB Exception Address Register -#elif defined(CONFIG_CPU_SH4) -TRA = 0xff000020 -EXPEVT = 0xff000024 -INTEVT = 0xff000028 -MMU_TEA = 0xff00000c ! TLB Exception Address Register -#endif - #if defined(CONFIG_KGDB_NMI) NMI_VEC = 0x1c0 ! Must catch early for debounce #endif diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index a4dc2b532e10..9fd1723e6219 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -15,21 +15,18 @@ #include <linux/unistd.h> #include <linux/mm.h> #include <linux/elfcore.h> -#include <linux/slab.h> #include <linux/a.out.h> +#include <linux/slab.h> +#include <linux/pm.h> #include <linux/ptrace.h> #include <linux/platform.h> #include <linux/kallsyms.h> +#include <linux/kexec.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> #include <asm/elf.h> -#if defined(CONFIG_SH_HS7751RVOIP) -#include <asm/hs7751rvoip/hs7751rvoip.h> -#elif defined(CONFIG_SH_RTS7751R2D) -#include <asm/rts7751r2d/rts7751r2d.h> -#endif static int hlt_counter=0; @@ -37,6 +34,11 @@ int ubc_usercnt = 0; #define HARD_IDLE_TIMEOUT (HZ / 3) +void (*pm_idle)(void); + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + void disable_hlt(void) { hlt_counter++; @@ -51,17 +53,25 @@ void enable_hlt(void) EXPORT_SYMBOL(enable_hlt); +void default_idle(void) +{ + if (!hlt_counter) + cpu_sleep(); + else + cpu_relax(); +} + void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - if (hlt_counter) { - while (!need_resched()) - cpu_relax(); - } else { - while (!need_resched()) - cpu_sleep(); - } + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + while (!need_resched()) + idle(); preempt_enable_no_resched(); schedule(); @@ -88,28 +98,16 @@ void machine_restart(char * __unused) void machine_halt(void) { -#if defined(CONFIG_SH_HS7751RVOIP) - unsigned short value; + local_irq_disable(); - value = ctrl_inw(PA_OUTPORTR); - ctrl_outw((value & 0xffdf), PA_OUTPORTR); -#elif defined(CONFIG_SH_RTS7751R2D) - ctrl_outw(0x0001, PA_POWOFF); -#endif while (1) cpu_sleep(); } void machine_power_off(void) { -#if defined(CONFIG_SH_HS7751RVOIP) - unsigned short value; - - value = ctrl_inw(PA_OUTPORTR); - ctrl_outw((value & 0xffdf), PA_OUTPORTR); -#elif defined(CONFIG_SH_RTS7751R2D) - ctrl_outw(0x0001, PA_POWOFF); -#endif + if (pm_power_off) + pm_power_off(); } void show_regs(struct pt_regs * regs) diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 036050b377cd..a067a34e0b64 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -22,10 +22,10 @@ #include <linux/cpu.h> #include <asm/uaccess.h> #include <asm/io.h> -#include <asm/io_generic.h> #include <asm/sections.h> #include <asm/irq.h> #include <asm/setup.h> +#include <asm/clock.h> #ifdef CONFIG_SH_KGDB #include <asm/kgdb.h> @@ -41,7 +41,7 @@ extern void * __rd_start, * __rd_end; * This value will be used at the very early stage of serial setup. * The bigger value means no problem. */ -struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, }; +struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; struct screen_info screen_info; #if defined(CONFIG_SH_UNKNOWN) @@ -186,7 +186,7 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], static int __init sh_mv_setup(char **cmdline_p) { -#if defined(CONFIG_SH_UNKNOWN) +#ifdef CONFIG_SH_UNKNOWN extern struct sh_machine_vector mv_unknown; #endif struct sh_machine_vector *mv = NULL; @@ -196,7 +196,7 @@ static int __init sh_mv_setup(char **cmdline_p) parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); -#ifdef CONFIG_SH_GENERIC +#ifdef CONFIG_SH_UNKNOWN if (mv == NULL) { mv = &mv_unknown; if (*mv_name != '\0') { @@ -206,9 +206,6 @@ static int __init sh_mv_setup(char **cmdline_p) } sh_mv = *mv; #endif -#ifdef CONFIG_SH_UNKNOWN - sh_mv = mv_unknown; -#endif /* * Manually walk the vec, fill in anything that the board hasn't yet @@ -231,10 +228,8 @@ static int __init sh_mv_setup(char **cmdline_p) mv_set(readb); mv_set(readw); mv_set(readl); mv_set(writeb); mv_set(writew); mv_set(writel); - mv_set(ioremap); - mv_set(iounmap); - - mv_set(isa_port2addr); + mv_set(ioport_map); + mv_set(ioport_unmap); mv_set(irq_demux); #ifdef CONFIG_SH_UNKNOWN @@ -273,10 +268,10 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long) _edata; init_mm.brk = (unsigned long) _end; - code_resource.start = virt_to_bus(_text); - code_resource.end = virt_to_bus(_etext)-1; - data_resource.start = virt_to_bus(_etext); - data_resource.end = virt_to_bus(_edata)-1; + code_resource.start = (unsigned long)virt_to_phys(_text); + code_resource.end = (unsigned long)virt_to_phys(_etext)-1; + data_resource.start = (unsigned long)virt_to_phys(_etext); + data_resource.end = (unsigned long)virt_to_phys(_edata)-1; sh_mv_setup(cmdline_p); @@ -435,6 +430,9 @@ static const char *cpu_name[] = { [CPU_ST40GX1] = "ST40GX1", [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", + [CPU_SH7770] = "SH7770", + [CPU_SH7780] = "SH7780", + [CPU_SH7781] = "SH7781", [CPU_SH_NONE] = "Unknown" }; @@ -445,7 +443,7 @@ const char *get_cpu_subtype(void) #ifdef CONFIG_PROC_FS static const char *cpu_flags[] = { - "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", + "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL }; static void show_cpuflags(struct seq_file *m) @@ -459,7 +457,7 @@ static void show_cpuflags(struct seq_file *m) return; } - for (i = 0; i < cpu_data->flags; i++) + for (i = 0; cpu_flags[i]; i++) if ((cpu_data->flags & (1 << i))) seq_printf(m, " %s", cpu_flags[i+1]); @@ -472,7 +470,8 @@ static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_in cache_size = info.ways * info.sets * info.linesz; - seq_printf(m, "%s size\t: %dKiB\n", type, cache_size >> 10); + seq_printf(m, "%s size\t: %2dKiB (%d-way)\n", + type, cache_size >> 10, info.ways); } /* @@ -511,21 +510,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) boot_cpu_data.loops_per_jiffy/(500000/HZ), (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100); -#define PRINT_CLOCK(name, value) \ - seq_printf(m, name " clock\t: %d.%02dMHz\n", \ - ((value) / 1000000), ((value) % 1000000)/10000) - - PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock); - PRINT_CLOCK("bus", boot_cpu_data.bus_clock); -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - PRINT_CLOCK("memory", boot_cpu_data.memory_clock); -#endif - PRINT_CLOCK("module", boot_cpu_data.module_clock); - - return 0; + return show_clocks(m); } - static void *c_start(struct seq_file *m, loff_t *pos) { return *pos < NR_CPUS ? cpu_data + *pos : NULL; @@ -596,7 +583,7 @@ static int __init kgdb_parse_options(char *options) options += map->namelen + 1; options = (*options == ',') ? options+1 : options; - + /* Read optional parameters (baud/parity/bits) */ baud = simple_strtoul(options, &options, 10); if (baud != 0) { diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c index 472b450e61be..de29c45f23a7 100644 --- a/arch/sh64/kernel/sh_ksyms.c +++ b/arch/sh64/kernel/sh_ksyms.c @@ -31,14 +31,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); -#if 0 -/* Not yet - there's no declaration of drive_info anywhere. */ -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) -extern struct drive_info_struct drive_info; -EXPORT_SYMBOL(drive_info); -#endif -#endif - /* platform dependent support */ EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(iounmap); diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c index 1195af37ee5a..0773c9f389f3 100644 --- a/arch/sh64/kernel/time.c +++ b/arch/sh64/kernel/time.c @@ -29,6 +29,7 @@ #include <linux/init.h> #include <linux/profile.h> #include <linux/smp.h> +#include <linux/module.h> #include <asm/registers.h> /* required by inline __asm__ stmt. */ diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 03ecb4e4614e..887f6a160c58 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -38,7 +38,7 @@ #define curptr g6 -#define NR_SYSCALLS 284 /* Each OS is different... */ +#define NR_SYSCALLS 300 /* Each OS is different... */ /* These are just handy. */ #define _SV save %sp, -STACKFRAME_SZ, %sp @@ -1277,62 +1277,6 @@ sys_sigstack: mov %l5, %o7 .align 4 - .globl sys_sigpause -sys_sigpause: - /* Note: %o0 already has correct value... */ - call do_sigpause - add %sp, STACKFRAME_SZ, %o1 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 - .globl sys_sigsuspend -sys_sigsuspend: - call do_sigsuspend - add %sp, STACKFRAME_SZ, %o0 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 - .globl sys_rt_sigsuspend -sys_rt_sigsuspend: - /* Note: %o0, %o1 already have correct value... */ - call do_rt_sigsuspend - add %sp, STACKFRAME_SZ, %o2 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 .globl sys_sigreturn sys_sigreturn: call do_sigreturn diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index fbb05a452e51..118cac84a0f5 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -54,7 +54,7 @@ void (*pm_idle)(void); * This is done via auxio, but could be used as a fallback * handler when auxio is not present-- unused for now... */ -void (*pm_power_off)(void); +void (*pm_power_off)(void) = machine_power_off; /* * sysctl - toggle power-off restriction for serial console diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index f7460d897e79..77ca6fd81253 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S @@ -68,15 +68,14 @@ ret_trap_lockless_ipi: ld [%curptr + TI_FLAGS], %g2 signal_p: - andcc %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0 + andcc %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0 bz,a ret_trap_continue ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr - clr %o0 - mov %l5, %o2 - mov %l6, %o3 + mov %l5, %o1 + mov %l6, %o2 call do_signal - add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr + add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr /* Fall through. */ ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 5f34d7dc2b89..0748d8147bbf 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_o0, int restart_syscall); - /* Signal frames: the original one (compatible with SunOS): * * Set up a signal frame... Make the stack look the way SunOS @@ -95,98 +92,30 @@ struct rt_signal_frame { #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) +static int _sigpause_common(old_sigset_t set) { - sigset_t saveset; - set &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, set); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->pc = regs->npc; - regs->npc += 4; - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&saveset, regs, 0, 0)) - return; - } -} + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); -asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) -{ - _sigpause_common(set, regs); + return -ERESTARTNOHAND; } -asmlinkage void do_sigsuspend (struct pt_regs *regs) +asmlinkage int sys_sigpause(unsigned int set) { - _sigpause_common(regs->u_regs[UREG_I0], regs); + return _sigpause_common(set); } -asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, - struct pt_regs *regs) +asmlinkage int sys_sigsuspend(old_sigset_t set) { - sigset_t oldset, set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) { - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINVAL; - return; - } - - if (copy_from_user(&set, uset, sizeof(set))) { - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EFAULT; - return; - } - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->pc = regs->npc; - regs->npc += 4; - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&oldset, regs, 0, 0)) - return; - } + return _sigpause_common(set); } static inline int @@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct sparc_deliver_cookie cookie; struct k_sigaction ka; int signr; + sigset_t *oldset; /* * XXX Disable svr4 signal handling until solaris emulation works. @@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, &cookie); @@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, syscall_restart(cookie.orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs, svr4_signal); - return 1; + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, regs->pc -= 4; regs->npc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } asmlinkage int diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 0b0d492c953b..19b25399d7e4 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -66,7 +66,6 @@ struct poll { extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); -void _sigpause_common (unsigned int set, struct pt_regs *); extern void (*__copy_1page)(void *, const void *); extern void __memmove(void *, const void *, __kernel_size_t); extern void (*bzero_1page)(void *); @@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic); /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(svr4_setcontext); EXPORT_SYMBOL(svr4_getcontext); -EXPORT_SYMBOL(_sigpause_common); EXPORT_SYMBOL(dump_thread); diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index e457a40838fc..768de64b371f 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -75,7 +75,10 @@ sys_call_table: /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat +/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 +/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -181,6 +184,12 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys /*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys +/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys #endif diff --git a/arch/sparc/math-emu/math.c b/arch/sparc/math-emu/math.c index be2c80932e26..8613b3eb877c 100644 --- a/arch/sparc/math-emu/math.c +++ b/arch/sparc/math-emu/math.c @@ -323,11 +323,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) case FMOVS: case FABSS: case FNEGS: TYPE(2,1,0,1,0,0,0); break; - default: -#ifdef DEBUG_MATHEMU - printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff); -#endif - break; } } else if ((insn & 0xc1f80000) == 0x81a80000) /* FPOP2 */ { switch ((insn >> 5) & 0x1ff) { @@ -337,11 +332,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) case FCMPED: TYPE(3,0,0,2,1,2,1); break; case FCMPQ: TYPE(3,0,0,3,1,3,1); break; case FCMPEQ: TYPE(3,0,0,3,1,3,1); break; - default: -#ifdef DEBUG_MATHEMU - printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff); -#endif - break; } } diff --git a/arch/sparc64/boot/.gitignore b/arch/sparc64/boot/.gitignore new file mode 100644 index 000000000000..36356f9d498e --- /dev/null +++ b/arch/sparc64/boot/.gitignore @@ -0,0 +1,4 @@ +image +tftpboot.img +vmlinux.aout +piggyback diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index a3fb3376ffa0..069d49777b2a 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15 -# Mon Jan 9 14:36:29 2006 +# Linux kernel version: 2.6.16-rc2 +# Tue Feb 7 17:47:18 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -23,7 +23,6 @@ CONFIG_HZ=250 # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -31,7 +30,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -155,6 +154,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -224,6 +224,11 @@ CONFIG_IP_DCCP_TFRC_LIB=m # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set CONFIG_VLAN_8021Q=m @@ -420,8 +425,7 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLOGICPTI is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -529,6 +533,7 @@ CONFIG_NET_PCI=y # CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -738,6 +743,12 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_DEBUG_CHIP is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -755,6 +766,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set @@ -1014,6 +1026,7 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set @@ -1107,6 +1120,10 @@ CONFIG_USB_HIDDEV=y # # +# EDAC - error detection and reporting (RAS) +# + +# # Misc Linux/SPARC drivers # CONFIG_SUN_OPENPROMIO=m @@ -1268,12 +1285,13 @@ CONFIG_KPROBES=y # Kernel hacking # CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1281,6 +1299,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_DCFLUSH is not set diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 710002991888..a73553ae7e53 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -25,7 +25,7 @@ #define curptr g6 -#define NR_SYSCALLS 284 /* Each OS is different... */ +#define NR_SYSCALLS 300 /* Each OS is different... */ .text .align 32 @@ -1416,7 +1416,6 @@ execve_merge: add %sp, PTREGS_OFF, %o0 .globl sys_pipe, sys_sigpause, sys_nis_syscall - .globl sys_sigsuspend, sys_rt_sigsuspend .globl sys_rt_sigreturn .globl sys_ptrace .globl sys_sigaltstack @@ -1440,28 +1439,6 @@ sys32_sigaltstack: mov %i6, %o2 #endif .align 32 -sys_sigsuspend: add %sp, PTREGS_OFF, %o0 - call do_sigsuspend - add %o7, 1f-.-4, %o7 - nop -sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ - add %sp, PTREGS_OFF, %o2 - call do_rt_sigsuspend - add %o7, 1f-.-4, %o7 - nop -#ifdef CONFIG_COMPAT - .globl sys32_rt_sigsuspend -sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ - srl %o0, 0, %o0 - add %sp, PTREGS_OFF, %o2 - call do_rt_sigsuspend32 - add %o7, 1f-.-4, %o7 -#endif - /* NOTE: %o0 has a correct value already */ -sys_sigpause: add %sp, PTREGS_OFF, %o1 - call do_sigpause - add %o7, 1f-.-4, %o7 - nop #ifdef CONFIG_COMPAT .globl sys32_sigreturn sys32_sigreturn: diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 1dc3650c5cae..059b0d025224 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -164,6 +164,7 @@ void machine_restart(char * cmd) panic("Reboot failed!"); } +#ifdef CONFIG_COMPAT static void show_regwindow32(struct pt_regs *regs) { struct reg_window32 __user *rw; @@ -189,6 +190,9 @@ static void show_regwindow32(struct pt_regs *regs) r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3], r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]); } +#else +#define show_regwindow32(regs) do { } while (0) +#endif static void show_regwindow(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 090dcca00d2a..b80eba0081ca 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -53,14 +53,13 @@ __handle_user_windows: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 +1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 be,pt %xcc, __handle_user_windows_continue nop - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate @@ -96,15 +95,14 @@ __handle_perfctrs: wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 +1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 be,pt %xcc, __handle_perfctrs_continue sethi %hi(TSTATE_PEF), %o0 - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate @@ -129,11 +127,10 @@ __handle_userfpu: ba,a,pt %xcc, __handle_userfpu_continue __handle_signal: - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate @@ -200,7 +197,7 @@ __handle_preemption_continue: andcc %l1, %o0, %g0 andcc %l0, _TIF_NEED_RESCHED, %g0 bne,pn %xcc, __handle_preemption - andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 + andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 bne,pn %xcc, __handle_signal __handle_signal_continue: ldub [%g6 + TI_WSAVED], %o2 diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 250745896aee..054461e6946d 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -561,6 +561,8 @@ static int __init set_preferred_console(void) serial_console = 1; } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { serial_console = 2; + } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { + serial_console = 3; } else { prom_printf("Inconsistent console: " "input %d, output %d\n", diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 60f5dfabb1e1..ca11a4c457d4 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -36,9 +36,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -static int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_o0, int ret_from_syscall); - /* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) { @@ -242,114 +239,29 @@ struct rt_signal_frame { /* Align macros */ #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) +static long _sigpause_common(old_sigset_t set) { - sigset_t saveset; - -#ifdef CONFIG_SPARC32_COMPAT - if (test_thread_flag(TIF_32BIT)) { - extern asmlinkage void _sigpause32_common(compat_old_sigset_t, - struct pt_regs *); - _sigpause32_common(set, regs); - return; - } -#endif set &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, set); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc = (regs->tnpc & 0xffffffff); - regs->tnpc = (regs->tnpc + 4) & 0xffffffff; - } else { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&saveset, regs, 0, 0)) - return; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } -asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) +asmlinkage long sys_sigpause(unsigned int set) { - _sigpause_common(set, regs); + return _sigpause_common(set); } -asmlinkage void do_sigsuspend(struct pt_regs *regs) +asmlinkage long sys_sigsuspend(old_sigset_t set) { - _sigpause_common(regs->u_regs[UREG_I0], regs); -} - -asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs) -{ - sigset_t oldset, set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) { - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINVAL; - return; - } - if (copy_from_user(&set, uset, sizeof(set))) { - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EFAULT; - return; - } - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc = (regs->tnpc & 0xffffffff); - regs->tnpc = (regs->tnpc + 4) & 0xffffffff; - } else { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&oldset, regs, 0, 0)) - return; - } + return _sigpause_common(set); } static inline int @@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct signal_deliver_cookie cookie; struct k_sigaction ka; int signr; + sigset_t *oldset; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; #ifdef CONFIG_SPARC32_COMPAT if (test_thread_flag(TIF_32BIT)) { - extern int do_signal32(sigset_t *, struct pt_regs *, - unsigned long, int); - return do_signal32(oldset, regs, orig_i0, - cookie.restart_syscall); + extern void do_signal32(sigset_t *, struct pt_regs *, + unsigned long, int); + do_signal32(oldset, regs, orig_i0, + cookie.restart_syscall); + return; } #endif @@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, if (cookie.restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); - return 1; + + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, regs->tpc -= 4; regs->tnpc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } -void do_notify_resume(sigset_t *oldset, struct pt_regs *regs, - unsigned long orig_i0, int restart_syscall, +void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall, unsigned long thread_info_flags) { - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(oldset, regs, orig_i0, restart_syscall); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs, orig_i0, restart_syscall); } void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 009a86e5ded4..708ba9b42cda 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -32,9 +32,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -int do_signal32(sigset_t *oldset, struct pt_regs *regs, - unsigned long orig_o0, int ret_from_syscall); - /* Signal frames: the original one (compatible with SunOS): * * Set up a signal frame... Make the stack look the way SunOS @@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) return 0; } -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs) -{ - sigset_t saveset; - - set &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, set); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal32(&saveset, regs, 0, 0)) - return; - } -} - -asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs) -{ - sigset_t oldset, set; - compat_sigset_t set32; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) { - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINVAL; - return; - } - if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) { - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EFAULT; - return; - } - switch (_NSIG_WORDS) { - case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32); - case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32); - case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32); - case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal32(&oldset, regs, 0, 0)) - return; - } -} - static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) { unsigned long *fpregs = current_thread_info()->fpregs; @@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal32(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +void do_signal32(sigset_t *oldset, struct pt_regs * regs, + unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct signal_deliver_cookie cookie; @@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, syscall_restart32(orig_i0, regs, &ka.sa); handle_signal32(signr, &ka, &info, oldset, regs, svr4_signal); - return 1; + + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, regs->tpc -= 4; regs->tnpc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } struct sigstack32 { diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index d177d7e5c9d3..3c06bfb92a8c 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -69,7 +69,6 @@ struct poll { extern void die_if_kernel(char *str, struct pt_regs *regs); extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -void _sigpause_common (unsigned int set, struct pt_regs *); extern void *__bzero(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); @@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported); /* I/O device mmaping on Sparc64. */ EXPORT_SYMBOL(io_remap_pfn_range); +#ifdef CONFIG_COMPAT /* Solaris/SunOS binary compatibility */ -EXPORT_SYMBOL(_sigpause_common); EXPORT_SYMBOL(verify_compat_iovec); +#endif EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(pte_alloc_one_kernel); diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 9cd272ac3ac1..60b59375aa78 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -84,7 +84,6 @@ SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) SIGN1(sys32_mlockall, sys_mlockall, %o0) SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0) -SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1) SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index d4b7a100cb8a..417727bd87ba 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -428,6 +428,27 @@ asmlinkage long compat_sys_fstat64(unsigned int fd, return error; } +asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename, + struct compat_stat64 __user * statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_compat_stat64(&stat, statbuf); + +out: + return error; +} + asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) { return sys_sysfs(option, arg1, arg2); @@ -821,7 +842,7 @@ asmlinkage long sys32_utimes(char __user *filename, return -EFAULT; } - return do_utimes(filename, (tvs ? &ktvs[0] : NULL)); + return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL)); } /* These are here just in case some old sparc32 binary calls it. */ @@ -1003,7 +1024,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp) asmlinkage long sparc32_open(const char __user *filename, int flags, int mode) { - return do_sys_open(filename, flags, mode); + return do_sys_open(AT_FDCWD, filename, flags, mode); } extern unsigned long do_mremap(unsigned long addr, diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 98d24bc00044..c3adb7ac167d 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -41,7 +41,7 @@ sys_call_table32: /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending - .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid + .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod @@ -71,12 +71,15 @@ sys_call_table32: /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep /*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl - .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep + .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid -/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat + .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 +/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat + .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare #endif /* CONFIG_COMPAT */ @@ -142,7 +145,10 @@ sys_call_table: .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat + .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 +/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat + .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -239,12 +245,20 @@ sunos_sys_table: /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c index eae5db8dda56..ac6d035dd150 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc64/prom/console.c @@ -99,8 +99,12 @@ prom_query_input_device(void) if (!strncmp(propb, "keyboard", 8)) return PROMDEV_ITTYA; + if (!strncmp (propb, "rsc", 3)) + return PROMDEV_IRSC; + if (strncmp (propb, "tty", 3) || !propb[3]) return PROMDEV_I_UNK; + switch (propb[3]) { case 'a': return PROMDEV_ITTYA; case 'b': return PROMDEV_ITTYB; @@ -136,8 +140,12 @@ prom_query_output_device(void) if (!strncmp(propb, "screen", 6)) return PROMDEV_OTTYA; + if (!strncmp (propb, "rsc", 3)) + return PROMDEV_ORSC; + if (strncmp (propb, "tty", 3) || !propb[3]) return PROMDEV_O_UNK; + switch (propb[3]) { case 'a': return PROMDEV_OTTYA; case 'b': return PROMDEV_OTTYB; diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index 4b6ae583c0a3..eb314ed23cdb 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S @@ -180,6 +180,8 @@ solaris_sigsuspend: nop call sys_sigsuspend stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] + b,pt %xcc, ret_from_solaris + nop .globl solaris_getpid solaris_getpid: diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S index d25667eeae10..7043ca18caf9 100644 --- a/arch/sparc64/solaris/systbl.S +++ b/arch/sparc64/solaris/systbl.S @@ -283,32 +283,3 @@ solaris_sys_table: .word solaris_unimplemented /* 253 */ .word solaris_unimplemented /* 254 */ .word solaris_unimplemented /* 255 */ - .word solaris_unimplemented /* 256 */ - .word solaris_unimplemented /* 257 */ - .word solaris_unimplemented /* 258 */ - .word solaris_unimplemented /* 259 */ - .word solaris_unimplemented /* 260 */ - .word solaris_unimplemented /* 261 */ - .word solaris_unimplemented /* 262 */ - .word solaris_unimplemented /* 263 */ - .word solaris_unimplemented /* 264 */ - .word solaris_unimplemented /* 265 */ - .word solaris_unimplemented /* 266 */ - .word solaris_unimplemented /* 267 */ - .word solaris_unimplemented /* 268 */ - .word solaris_unimplemented /* 269 */ - .word solaris_unimplemented /* 270 */ - .word solaris_unimplemented /* 271 */ - .word solaris_unimplemented /* 272 */ - .word solaris_unimplemented /* 273 */ - .word solaris_unimplemented /* 274 */ - .word solaris_unimplemented /* 275 */ - .word solaris_unimplemented /* 276 */ - .word solaris_unimplemented /* 277 */ - .word solaris_unimplemented /* 278 */ - .word solaris_unimplemented /* 279 */ - .word solaris_unimplemented /* 280 */ - .word solaris_unimplemented /* 281 */ - .word solaris_unimplemented /* 282 */ - .word solaris_unimplemented /* 283 */ - diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 8ff3bcbce5fc..5982fe2753e0 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -143,6 +143,7 @@ config HOSTFS config HPPFS tristate "HoneyPot ProcFS (EXPERIMENTAL)" + depends on EXPERIMENTAL help hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc entries to be overridden, removed, or fabricated from the host. @@ -155,10 +156,6 @@ config HPPFS You only need this if you are setting up a UML honeypot. Otherwise, it is safe to say 'N' here. - If you are actively using it, please report any problems, since it's - getting fixed. In this moment, it is experimental on 2.6 (it works on - 2.4). - config MCONSOLE bool "Management console" default y @@ -243,8 +240,16 @@ config NEST_LEVEL Only change this if you are running nested UMLs. config HIGHMEM - bool "Highmem support" - depends on !64BIT + bool "Highmem support (EXPERIMENTAL)" + depends on !64BIT && EXPERIMENTAL + default n + help + This was used to allow UML to run with big amounts of memory. + Currently it is unstable, so if unsure say N. + + To use big amounts of memory, it is recommended to disable TT mode (i.e. + CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) - + this should allow the guest to use up to 2.75G of memory. config KERNEL_STACK_ORDER int "Kernel stack size order" @@ -269,17 +274,13 @@ endmenu source "init/Kconfig" -source "net/Kconfig" - -source "drivers/base/Kconfig" +source "drivers/block/Kconfig" source "arch/um/Kconfig.char" -source "drivers/block/Kconfig" +source "drivers/base/Kconfig" -config NETDEVICES - bool - default NET +source "net/Kconfig" source "arch/um/Kconfig.net" diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index c71b39a677aa..ef79ed25aecd 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -22,13 +22,17 @@ config TOP_ADDR default 0x80000000 if HOST_2G_2G config 3_LEVEL_PGTABLES - bool "Three-level pagetables" + bool "Three-level pagetables (EXPERIMENTAL)" default n + depends on EXPERIMENTAL help Three-level pagetables will let UML have more than 4G of physical memory. All the memory that can't be mapped directly will be treated as high memory. + However, this it experimental on 32-bit architectures, so if unsure say + N (on x86-64 it's automatically enabled, instead, as it's safe there). + config STUB_CODE hex default 0xbfffe000 diff --git a/arch/um/Makefile b/arch/um/Makefile index 45435ff589c1..c58b657f0097 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt um-modes-$(CONFIG_MODE_SKAS) += skas MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ - -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include) + -I$(srctree)/$(ARCH_DIR)/include/$(mode)) MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) @@ -47,13 +47,16 @@ ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include endif SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) -# -Dvmap=kernel_vmap affects everything, and prevents anything from -# referencing the libpcap.o symbol so named. +# -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so +# named - it's a common symbol in libpcap, so we get a binary which crashes. # -# Same things for in6addr_loopback - found in libc. +# Same things for in6addr_loopback and mktime - found in libc. For these two we +# only get link-time error, luckily. +# +# These apply to USER_CFLAGS to. -CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ - $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ +CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ + $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ -Din6addr_loopback=kernel_in6addr_loopback AFLAGS += $(ARCH_INCLUDE) @@ -66,6 +69,7 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ # kernel_errno to separate them from the libc errno. This allows -fno-common # in CFLAGS. Otherwise, it would cause ld to complain about the two different # errnos. +# These apply to kernelspace only. CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ -Dmktime=kernel_mktime @@ -168,10 +172,13 @@ else $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch endif -$(ARCH_DIR)/include/sysdep: +$(objtree)/$(ARCH_DIR)/include: + @echo ' MKDIR $@' + $(Q)mkdir -p $@ + +$(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include @echo ' SYMLINK $@' ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p $(ARCH_DIR)/include $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep else $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep @@ -214,7 +221,7 @@ $(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s CLEAN_FILES += $(ARCH_DIR)/user-offsets.s -$(ARCH_DIR)/include/kern_constants.h: +$(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include @echo ' SYMLINK $@' $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@ diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index ab0d0b170816..7218c754505b 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -403,7 +403,7 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, return 0; } -void free_one_chan(struct chan *chan, int delay_free_irq) +static void free_one_chan(struct chan *chan, int delay_free_irq) { list_del(&chan->list); @@ -416,7 +416,7 @@ void free_one_chan(struct chan *chan, int delay_free_irq) kfree(chan); } -void free_chan(struct list_head *chans, int delay_free_irq) +static void free_chan(struct list_head *chans, int delay_free_irq) { struct list_head *ele, *next; struct chan *chan; @@ -497,7 +497,7 @@ struct chan_type { struct chan_ops *ops; }; -struct chan_type chan_table[] = { +static struct chan_type chan_table[] = { { "fd", &fd_ops }, #ifdef CONFIG_NULL_CHAN diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 5d50d4a44abf..2f880cb167a5 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -9,6 +9,7 @@ #include <termios.h> #include <string.h> #include <signal.h> +#include <sched.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -73,7 +74,6 @@ static void winch_handler(int sig) struct winch_data { int pty_fd; int pipe_fd; - int close_me; }; static int winch_thread(void *arg) @@ -84,7 +84,6 @@ static int winch_thread(void *arg) int count, err; char c = 1; - os_close_file(data->close_me); pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; count = os_write_file(pipe_fd, &c, sizeof(c)); @@ -153,15 +152,16 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) } data = ((struct winch_data) { .pty_fd = fd, - .pipe_fd = fds[1], - .close_me = fds[0] } ); - err = run_helper_thread(winch_thread, &data, 0, &stack, 0); + .pipe_fd = fds[1] } ); + /* CLONE_FILES so this thread doesn't hold open files which are open + * now, but later closed. This is a problem with /dev/net/tun. + */ + err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); if(err < 0){ printk("fork of winch_thread failed - errno = %d\n", errno); goto out_close; } - os_close_file(fds[1]); *fd_out = fds[0]; n = os_read_file(fds[0], &c, sizeof(c)); if(n != sizeof(c)){ @@ -169,13 +169,12 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) printk("read failed, err = %d\n", -n); printk("fd %d will not support SIGWINCH\n", fd); err = -EINVAL; - goto out_close1; + goto out_close; } return err ; out_close: os_close_file(fds[1]); - out_close1: os_close_file(fds[0]); out: return err; diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 30d285b266af..a61b7b46bc02 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c @@ -18,7 +18,7 @@ struct daemon_init { char *ctl_sock; }; -void daemon_init(struct net_device *dev, void *data) +static void daemon_init(struct net_device *dev, void *data) { struct uml_net_private *pri; struct daemon_data *dpri; @@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data) dpri->fd = -1; dpri->control = -1; dpri->dev = dev; + /* We will free this pointer. If it contains crap we're burned. */ + dpri->ctl_addr = NULL; + dpri->data_addr = NULL; + dpri->local_addr = NULL; printk("daemon backend (uml_switch version %d) - %s:%s", SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); @@ -60,7 +64,7 @@ static struct net_kern_info daemon_kern_info = { .write = daemon_write, }; -int daemon_setup(char *str, char **mac_out, void *data) +static int daemon_setup(char *str, char **mac_out, void *data) { struct daemon_init *init = data; char *remain; diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 1bb085b2824d..c944265955e2 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -158,10 +158,16 @@ static void daemon_remove(void *data) struct daemon_data *pri = data; os_close_file(pri->fd); + pri->fd = -1; os_close_file(pri->control); + pri->control = -1; + kfree(pri->data_addr); + pri->data_addr = NULL; kfree(pri->ctl_addr); + pri->ctl_addr = NULL; kfree(pri->local_addr); + pri->local_addr = NULL; } int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 3296e86a03a5..c41f75e4acb5 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -11,6 +11,7 @@ #include "user.h" #include "user_util.h" #include "chan_user.h" +#include "os.h" struct fd_chan { int fd; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 46ceb25a9959..6c2d4ccaf20f 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -714,7 +714,7 @@ struct winch { struct tty_struct *tty; }; -irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) { struct winch *winch = data; struct tty_struct *tty; diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index 217438cdef33..c9b078fba03e 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c @@ -26,7 +26,7 @@ struct mcast_init { int ttl; }; -void mcast_init(struct net_device *dev, void *data) +static void mcast_init(struct net_device *dev, void *data) { struct uml_net_private *pri; struct mcast_data *dpri; @@ -40,7 +40,7 @@ void mcast_init(struct net_device *dev, void *data) dpri->dev = dev; printk("mcast backend "); - printk("multicast adddress: %s:%u, TTL:%u ", + printk("multicast address: %s:%u, TTL:%u ", dpri->addr, dpri->port, dpri->ttl); printk("\n"); diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index e3d576567172..54388d10bcf9 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -273,7 +273,7 @@ void mconsole_proc(struct mc_request *req) config <dev> - Query the configuration of a device \n\ remove <dev> - Remove a device from UML \n\ sysrq <letter> - Performs the SysRq action controlled by the letter \n\ - cad - invoke the Ctl-Alt-Del handler \n\ + cad - invoke the Ctrl-Alt-Del handler \n\ stop - pause the UML; it will do nothing until it receives a 'go' \n\ go - continue the UML after a 'stop' \n\ log <string> - make UML enter <string> into the kernel log\n\ @@ -327,7 +327,7 @@ void mconsole_stop(struct mc_request *req) /* This list is populated by __initcall routines. */ -LIST_HEAD(mconsole_devices); +static LIST_HEAD(mconsole_devices); void mconsole_register_dev(struct mc_device *new) { @@ -561,6 +561,8 @@ void mconsole_sysrq(struct mc_request *req) } #endif +#ifdef CONFIG_MODE_SKAS + static void stack_proc(void *arg) { struct task_struct *from = current, *to = arg; @@ -574,7 +576,7 @@ static void stack_proc(void *arg) * Dumps a stacks registers to the linux console. * Usage stack <pid>. */ -void do_stack(struct mc_request *req) +static void do_stack_trace(struct mc_request *req) { char *ptr = req->request.data; int pid_requested= -1; @@ -605,6 +607,7 @@ void do_stack(struct mc_request *req) } with_console(req, stack_proc, to); } +#endif /* CONFIG_MODE_SKAS */ void mconsole_stack(struct mc_request *req) { @@ -613,7 +616,7 @@ void mconsole_stack(struct mc_request *req) */ CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", 1, 0), - do_stack(req)); + do_stack_trace(req)); } /* Changed by mconsole_setup, which is __setup, and called before SMP is diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index fb1f9fb9b871..8c7279bb353b 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev) return pkt_len; } +static void uml_dev_close(void* dev) +{ + dev_close( (struct net_device *) dev); +} + irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; @@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; if(err < 0) { + DECLARE_WORK(close_work, uml_dev_close, dev); printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); - dev_close(dev); + /* dev_close can't be called in interrupt context, and takes + * again lp->lock. + * And dev_close() can be safely called multiple times on the + * same device, since it tests for (dev->flags & IFF_UP). So + * there's no harm in delaying the device shutdown. */ + schedule_work(&close_work); goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); - out: +out: spin_unlock(&lp->lock); return(IRQ_HANDLED); } @@ -120,9 +131,8 @@ static int uml_net_open(struct net_device *dev) SA_INTERRUPT | SA_SHIRQ, dev->name, dev); if(err != 0){ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); - if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); - lp->fd = -1; err = -ENETUNREACH; + goto out_close; } lp->tl.data = (unsigned long) &lp->user; @@ -134,9 +144,19 @@ static int uml_net_open(struct net_device *dev) */ while((err = uml_net_rx(dev)) > 0) ; - out: spin_unlock(&lp->lock); - return(err); + + spin_lock(&opened_lock); + list_add(&lp->list, &opened); + spin_unlock(&opened_lock); + + return 0; +out_close: + if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); + lp->fd = -1; +out: + spin_unlock(&lp->lock); + return err; } static int uml_net_close(struct net_device *dev) @@ -150,9 +170,13 @@ static int uml_net_close(struct net_device *dev) if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; - list_del(&lp->list); spin_unlock(&lp->lock); + + spin_lock(&opened_lock); + list_del(&lp->list); + spin_unlock(&opened_lock); + return 0; } @@ -317,6 +341,11 @@ static int eth_configure(int n, void *init, char *mac, return 1; } + lp = dev->priv; + /* This points to the transport private data. It's still clear, but we + * must memset it to 0 *now*. Let's help the drivers. */ + memset(lp, 0, size); + /* sysfs register */ if (!driver_registered) { platform_driver_register(¨_net_driver); @@ -358,7 +387,6 @@ static int eth_configure(int n, void *init, char *mac, free_netdev(dev); return 1; } - lp = dev->priv; /* lp.user is the first four bytes of the transport data, which * has already been initialized. This structure assignment will @@ -395,11 +423,7 @@ static int eth_configure(int n, void *init, char *mac, if (device->have_mac) set_ether_mac(dev, device->mac); - spin_lock(&opened_lock); - list_add(&lp->list, &opened); - spin_unlock(&opened_lock); - - return(0); + return 0; } static struct uml_net *find_device(int n) diff --git a/arch/um/drivers/slip_common.h b/arch/um/drivers/slip_common.h index 2ae76d8f1be1..d574e0a9dc13 100644 --- a/arch/um/drivers/slip_common.h +++ b/arch/um/drivers/slip_common.h @@ -88,12 +88,13 @@ struct slip_proto { int esc; }; -#define SLIP_PROTO_INIT { \ - .ibuf = { '\0' }, \ - .obuf = { '\0' }, \ - .more = 0, \ - .pos = 0, \ - .esc = 0 \ +static inline void slip_proto_init(struct slip_proto * slip) +{ + memset(slip->ibuf, 0, sizeof(slip->ibuf)); + memset(slip->obuf, 0, sizeof(slip->obuf)); + slip->more = 0; + slip->pos = 0; + slip->esc = 0; } extern int slip_proto_read(int fd, void *buf, int len, diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 9a6f5c85f902..a62f5ef445cf 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c @@ -21,13 +21,14 @@ void slip_init(struct net_device *dev, void *data) private = dev->priv; spri = (struct slip_data *) private->user; - *spri = ((struct slip_data) - { .name = { '\0' }, - .addr = NULL, - .gate_addr = init->gate_addr, - .slave = -1, - .slip = SLIP_PROTO_INIT, - .dev = dev }); + + memset(spri->name, 0, sizeof(spri->name)); + spri->addr = NULL; + spri->gate_addr = init->gate_addr; + spri->slave = -1; + spri->dev = dev; + + slip_proto_init(&spri->slip); dev->init = NULL; dev->header_cache_update = NULL; diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 9864d27afdbe..33d7982be5d3 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -21,12 +21,13 @@ void slirp_init(struct net_device *dev, void *data) private = dev->priv; spri = (struct slirp_data *) private->user; - *spri = ((struct slirp_data) - { .argw = init->argw, - .pid = -1, - .slave = -1, - .slip = SLIP_PROTO_INIT, - .dev = dev }); + + spri->argw = init->argw; + spri->pid = -1; + spri->slave = -1; + spri->dev = dev; + + slip_proto_init(&spri->slip); dev->init = NULL; dev->hard_header_len = 0; diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index a32ef55cb244..a4d6415bc8c4 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -33,7 +33,7 @@ static struct tty_driver *ssl_driver; #define NR_PORTS 64 -void ssl_announce(char *dev_name, int dev) +static void ssl_announce(char *dev_name, int dev) { printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, dev_name); @@ -98,7 +98,7 @@ static int ssl_remove(int n) return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); } -int ssl_open(struct tty_struct *tty, struct file *filp) +static int ssl_open(struct tty_struct *tty, struct file *filp) { return line_open(serial_lines, tty); } @@ -182,7 +182,7 @@ static struct console ssl_cons = { .index = -1, }; -int ssl_init(void) +static int ssl_init(void) { char *new_title; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 7696f8d2d89c..101efd26d467 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1103,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file, return(-EINVAL); } -static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) +static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) { struct uml_stat buf1, buf2; int err; - if(from_cmdline == NULL) return(1); - if(!strcmp(from_cmdline, from_cow)) return(1); + if(from_cmdline == NULL) + return 0; + if(!strcmp(from_cmdline, from_cow)) + return 0; err = os_stat_file(from_cmdline, &buf1); if(err < 0){ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); - return(1); + return 0; } err = os_stat_file(from_cow, &buf2); if(err < 0){ printk("Couldn't stat '%s', err = %d\n", from_cow, -err); - return(1); + return 1; } if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) - return(1); + return 0; printk("Backing file mismatch - \"%s\" requested,\n" "\"%s\" specified in COW header of \"%s\"\n", from_cmdline, from_cow, cow); - return(0); + return 1; } static int backing_file_mismatch(char *file, __u64 size, time_t mtime) @@ -1189,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags, unsigned long long size; __u32 version, align; char *backing_file; - int fd, err, sectorsize, same, mode = 0644; + int fd, err, sectorsize, asked_switch, mode = 0644; fd = os_open_file(file, *openflags, mode); - if(fd < 0){ - if((fd == -ENOENT) && (create_cow_out != NULL)) + if (fd < 0) { + if ((fd == -ENOENT) && (create_cow_out != NULL)) *create_cow_out = 1; - if(!openflags->w || - ((fd != -EROFS) && (fd != -EACCES))) return(fd); + if (!openflags->w || + ((fd != -EROFS) && (fd != -EACCES))) + return fd; openflags->w = 0; fd = os_open_file(file, *openflags, mode); - if(fd < 0) - return(fd); + if (fd < 0) + return fd; } err = os_lock_file(fd, openflags->w); @@ -1209,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags, goto out_close; } - if(backing_file_out == NULL) return(fd); + /* Succesful return case! */ + if(backing_file_out == NULL) + return(fd); err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, &size, §orsize, &align, bitmap_offset_out); @@ -1218,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags, "errno = %d\n", file, -err); goto out_close; } - if(err) return(fd); - - if(backing_file_out == NULL) return(fd); + if(err) + return(fd); - same = same_backing_files(*backing_file_out, backing_file, file); + asked_switch = path_requires_switch(*backing_file_out, backing_file, file); - if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ + /* Allow switching only if no mismatch. */ + if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) { printk("Switching backing file to '%s'\n", *backing_file_out); err = write_cow_header(file, fd, *backing_file_out, sectorsize, align, &size); - if(err){ + if (err) { printk("Switch failed, errno = %d\n", -err); - return(err); + goto out_close; } - } - else { + } else { *backing_file_out = backing_file; err = backing_file_mismatch(*backing_file_out, size, mtime); - if(err) goto out_close; + if (err) + goto out_close; } cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, bitmap_len_out, data_offset_out); - return(fd); + return fd; out_close: os_close_file(fd); - return(err); + return err; } int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 8f4e46d677ab..07176d92e1c9 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -31,8 +31,6 @@ extern int timer_irq_inited; extern int jail; extern int nsyscalls; -extern struct task_struct *idle_threads[NR_CPUS]; - #define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) #define UML_ROUND_UP(addr) \ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) @@ -120,8 +118,10 @@ extern void machine_halt(void); extern int is_syscall(unsigned long addr); extern void arch_switch(void); extern void free_irq(unsigned int, void *); -extern int um_in_interrupt(void); extern int cpu(void); + +/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ +extern int __cant_sleep(void); extern void segv_handler(int sig, union uml_pt_regs *regs); extern void sigio_handler(int sig, union uml_pt_regs *regs); diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h new file mode 100644 index 000000000000..018b3819ab0b --- /dev/null +++ b/arch/um/include/longjmp.h @@ -0,0 +1,19 @@ +#ifndef __UML_LONGJMP_H +#define __UML_LONGJMP_H + +#include <setjmp.h> +#include "os.h" + +#define UML_SIGLONGJMP(buf, val) do { \ + longjmp(*buf, val); \ +} while(0) + +#define UML_SIGSETJMP(buf, enable) ({ \ + int n; \ + enable = get_signals(); \ + n = setjmp(*buf); \ + if(n != 0) \ + set_signals(enable); \ + n; }) + +#endif diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h index 2d88afd0cf16..e7539a8451ef 100644 --- a/arch/um/include/mode_kern.h +++ b/arch/um/include/mode_kern.h @@ -9,22 +9,11 @@ #include "linux/config.h" #ifdef CONFIG_MODE_TT -#include "mode_kern-tt.h" +#include "mode_kern_tt.h" #endif #ifdef CONFIG_MODE_SKAS -#include "mode_kern-skas.h" +#include "mode_kern_skas.h" #endif #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/arch/um/include/os.h b/arch/um/include/os.h index dd72d66cf0ed..eb1710b81255 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -11,6 +11,7 @@ #include "../os/include/file.h" #include "sysdep/ptrace.h" #include "kern_util.h" +#include "skas/mm_id.h" #define OS_TYPE_FILE 1 #define OS_TYPE_DIR 2 @@ -190,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len, int r, int w, int x); extern int os_unmap_memory(void *addr, int len); extern void os_flush_stdout(void); -extern unsigned long long os_usecs(void); /* tt.c * for tt mode only (will be deleted in future...) */ +extern void stop(void); +extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern void forward_pending_sigio(int target); @@ -230,9 +232,63 @@ extern void block_signals(void); extern void unblock_signals(void); extern int get_signals(void); extern int set_signals(int enable); +extern void os_usr1_signal(int on); /* trap.c */ extern void os_fill_handlinfo(struct kern_handlers h); extern void do_longjmp(void *p, int val); +/* util.c */ +extern void stack_protections(unsigned long address); +extern void task_protections(unsigned long address); +extern int raw(int fd); +extern void setup_machinename(char *machine_out); +extern void setup_hostinfo(void); +extern int setjmp_wrapper(void (*proc)(void *, void *), ...); + +/* time.c */ +#define BILLION (1000 * 1000 * 1000) + +extern void switch_timers(int to_real); +extern void idle_sleep(int secs); +extern void enable_timer(void); +extern void disable_timer(void); +extern void user_time_init(void); +extern void uml_idle_timer(void); +extern unsigned long long os_nsecs(void); + +/* skas/mem.c */ +extern long run_syscall_stub(struct mm_id * mm_idp, + int syscall, unsigned long *args, long expected, + void **addr, int done); +extern long syscall_stub_data(struct mm_id * mm_idp, + unsigned long *data, int data_count, + void **addr, void **stub_addr); +extern int map(struct mm_id * mm_idp, unsigned long virt, + unsigned long len, int r, int w, int x, int phys_fd, + unsigned long long offset, int done, void **data); +extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, + int done, void **data); +extern int protect(struct mm_id * mm_idp, unsigned long addr, + unsigned long len, int r, int w, int x, int done, + void **data); + +/* skas/process.c */ +extern int is_skas_winch(int pid, int fd, void *data); +extern int start_userspace(unsigned long stub_stack); +extern int copy_context_skas0(unsigned long stack, int pid); +extern void userspace(union uml_pt_regs *regs); +extern void map_stub_pages(int fd, unsigned long code, + unsigned long data, unsigned long stack); +extern void new_thread(void *stack, void **switch_buf_ptr, + void **fork_buf_ptr, void (*handler)(int)); +extern void thread_wait(void *sw, void *fb); +extern void switch_threads(void *me, void *next); +extern int start_idle_thread(void *stack, void *switch_buf_ptr, + void **fork_buf_ptr); +extern void initial_thread_cb_skas(void (*proc)(void *), + void *arg); +extern void halt_skas(void); +extern void reboot_skas(void); + #endif diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 4892e5fcef07..83b688ca198f 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -14,7 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs); extern void save_registers(int pid, union uml_pt_regs *regs); extern void restore_registers(int pid, union uml_pt_regs *regs); extern void init_registers(int pid); -extern void get_safe_registers(unsigned long * regs); +extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer); #endif diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/include/skas/mm_id.h index 48dd0989ddaa..48dd0989ddaa 100644 --- a/arch/um/kernel/skas/include/mm_id.h +++ b/arch/um/include/skas/mm_id.h diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h new file mode 100644 index 000000000000..d8869a6ef1b4 --- /dev/null +++ b/arch/um/include/skas/mmu-skas.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_MMU_H +#define __SKAS_MMU_H + +#include "linux/config.h" +#include "mm_id.h" +#include "asm/ldt.h" + +struct mmu_context_skas { + struct mm_id id; + unsigned long last_page_table; +#ifdef CONFIG_3_LEVEL_PGTABLES + unsigned long last_pmd; +#endif + uml_ldt_t ldt; +}; + +extern void switch_mm_skas(struct mm_id * mm_idp); + +#endif diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h new file mode 100644 index 000000000000..260065cfeef1 --- /dev/null +++ b/arch/um/include/skas/mode-skas.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_SKAS_H__ +#define __MODE_SKAS_H__ + +#include <sysdep/ptrace.h> + +extern unsigned long exec_regs[]; +extern unsigned long exec_fp_regs[]; +extern unsigned long exec_fpx_regs[]; +extern int have_fpx_regs; + +extern void sig_handler_common_skas(int sig, void *sc_ptr); +extern void kill_off_processes_skas(void); + +#endif diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h index c97a80dfe370..63c58739bde0 100644 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ b/arch/um/include/skas/mode_kern_skas.h @@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct *p, struct pt_regs *regs); extern void release_thread_skas(struct task_struct *task); -extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); extern void init_idle_skas(void); extern void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end); @@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task); #define kmem_end_skas (host_task_size - 1024 * 1024) #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/arch/um/kernel/skas/include/proc_mm.h b/arch/um/include/skas/proc_mm.h index cce61a679052..902809209603 100644 --- a/arch/um/kernel/skas/include/proc_mm.h +++ b/arch/um/include/skas/proc_mm.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -22,13 +22,13 @@ struct mm_mmap { struct mm_munmap { unsigned long addr; - unsigned long len; + unsigned long len; }; struct mm_mprotect { unsigned long addr; unsigned long len; - unsigned int prot; + unsigned int prot; }; struct proc_mm_op { @@ -42,14 +42,3 @@ struct proc_mm_op { }; #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/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h new file mode 100644 index 000000000000..86357282d681 --- /dev/null +++ b/arch/um/include/skas/skas.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_H +#define __SKAS_H + +#include "mm_id.h" +#include "sysdep/ptrace.h" + +extern int userspace_pid[]; +extern int proc_mm, ptrace_faultinfo, ptrace_ldt; +extern int skas_needs_stub; + +extern int user_thread(unsigned long stack, int flags); +extern void new_thread_proc(void *stack, void (*handler)(int sig)); +extern void new_thread_handler(int sig); +extern void handle_syscall(union uml_pt_regs *regs); +extern void user_signal(int sig, union uml_pt_regs *regs, int pid); +extern int new_mm(unsigned long stack); +extern void get_skas_faultinfo(int pid, struct faultinfo * fi); +extern long execute_syscall_skas(void *r); +extern unsigned long current_stub_stack(void); + +#endif diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h index f6ed92c3727d..f6ed92c3727d 100644 --- a/arch/um/kernel/skas/include/stub-data.h +++ b/arch/um/include/skas/stub-data.h diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h index 64516c556cdf..224a75f4c025 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/include/skas/uaccess-skas.h @@ -19,14 +19,3 @@ extern int clear_user_skas(void __user *mem, int len); extern int strnlen_user_skas(const void __user *str, int len); #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/arch/um/include/time_user.h b/arch/um/include/time_user.h deleted file mode 100644 index 17d7ef2141f4..000000000000 --- a/arch/um/include/time_user.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TIME_USER_H__ -#define __TIME_USER_H__ - -extern void timer(void); -extern void switch_timers(int to_real); -extern void idle_sleep(int secs); -extern void enable_timer(void); -extern void prepare_timer(void * ptr); -extern void disable_timer(void); -extern unsigned long time_lock(void); -extern void time_unlock(unsigned long); -extern void user_time_init(void); - -#endif diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h index 738435461e13..9778fa838296 100644 --- a/arch/um/kernel/tt/include/debug.h +++ b/arch/um/include/tt/debug.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and * Lars Brinkhoff. * Licensed under the GPL diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h new file mode 100644 index 000000000000..572a78b22587 --- /dev/null +++ b/arch/um/include/tt/mmu-tt.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_MMU_H +#define __TT_MMU_H + +struct mmu_context_tt { +}; + +#endif diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h new file mode 100644 index 000000000000..2823cd56eea2 --- /dev/null +++ b/arch/um/include/tt/mode-tt.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_TT_H__ +#define __MODE_TT_H__ + +#include "sysdep/ptrace.h" + +enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + +extern int tracing_pid; + +extern int tracer(int (*init_proc)(void *), void *sp); +extern void sig_handler_common_tt(int sig, void *sc); +extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); +extern void reboot_tt(void); +extern void halt_tt(void); +extern int is_tracer_winch(int pid, int fd, void *data); +extern void kill_off_processes_tt(void); + +#endif diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h new file mode 100644 index 000000000000..efa0012550d0 --- /dev/null +++ b/arch/um/include/tt/mode_kern_tt.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_MODE_KERN_H__ +#define __TT_MODE_KERN_H__ + +#include "linux/sched.h" +#include "asm/page.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" + +extern void switch_to_tt(void *prev, void *next); +extern void flush_thread_tt(void); +extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, + unsigned long esp); +extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct *p, + struct pt_regs *regs); +extern void release_thread_tt(struct task_struct *task); +extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); +extern void init_idle_tt(void); +extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); +extern void flush_tlb_kernel_vm_tt(void); +extern void __flush_tlb_one_tt(unsigned long addr); +extern void flush_tlb_range_tt(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +extern void flush_tlb_mm_tt(struct mm_struct *mm); +extern void force_flush_all_tt(void); +extern long execute_syscall_tt(void *r); +extern void before_mem_tt(unsigned long brk_start); +extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, + unsigned long *task_size_out); +extern int start_uml_tt(void); +extern int external_pid_tt(struct task_struct *task); +extern int thread_pid_tt(struct task_struct *task); + +#define kmem_end_tt (host_task_size - ABOVE_KMEM) + +#endif diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h index c667b67af405..808521980186 100644 --- a/arch/um/kernel/tt/include/tt.h +++ b/arch/um/include/tt/tt.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r); #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/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h index b9bfe9c481c4..b19645f32f24 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/include/tt/uaccess-tt.h @@ -46,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len); extern int strnlen_user_tt(const void __user *str, int len); #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/arch/um/include/user.h b/arch/um/include/user.h index 0f865ef46918..91b0ac4ad88c 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -18,6 +18,7 @@ extern int open_gdb_chan(void); extern unsigned long strlcpy(char *, const char *, unsigned long); extern unsigned long strlcat(char *, const char *, unsigned long); extern void *um_vmalloc(int size); +extern void *um_vmalloc_atomic(int size); extern void vfree(void *ptr); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index c1dbd77b073f..a6f1f176cf84 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -44,10 +44,6 @@ extern unsigned long brk_start; extern int pty_output_sigio; extern int pty_close_sigio; -extern void stop(void); -extern void stack_protections(unsigned long address); -extern void task_protections(unsigned long address); -extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern void *add_signal_handler(int sig, void (*handler)(int)); extern int linux_main(int argc, char **argv); extern void set_cmdline(char *cmd); @@ -55,8 +51,6 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len); extern int get_pty(void); extern void *um_kmalloc(int size); extern int switcheroo(int fd, int prot, void *from, void *to, int size); -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 int detach(int pid, int sig); @@ -70,18 +64,6 @@ extern int cpu_feature(char *what, char *buf, int len); extern int arch_handle_signal(int sig, union uml_pt_regs *regs); extern int arch_fixup(unsigned long address, void *sc_ptr); extern void arch_init_thread(void); -extern int setjmp_wrapper(void (*proc)(void *, void *), ...); extern int raw(int fd); #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/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 193cc2b7448d..693018ba80f1 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -9,9 +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 \ - user_util.o + signal_kern.o smp.o syscall_kern.o sysrq.o \ + time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o +USER_OBJS := $(user-objs-y) config.o tty_log.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index efd222ffe20e..c264e1c05ab3 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -17,7 +17,6 @@ #include "irq_user.h" #include "tlb.h" #include "os.h" -#include "time_user.h" #include "choose-mode.h" #include "mode_kern.h" @@ -34,7 +33,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) extern void log_exec(char **argv, void *tty); static long execve1(char *file, char __user * __user *argv, - char *__user __user *env) + char __user *__user *env) { long error; diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f3b583a878a6..544665e04513 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -265,7 +265,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) highmem_len = highmem_pages * sizeof(struct page); total_pages = phys_pages + iomem_pages + highmem_pages; - total_len = phys_len + iomem_pages + highmem_len; + total_len = phys_len + iomem_len + highmem_len; if(kmalloc_ok){ map = kmalloc(total_len, GFP_KERNEL); diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 7f13b85d2656..3113cab8675e 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -39,7 +39,6 @@ #include "init.h" #include "irq_user.h" #include "mem_user.h" -#include "time_user.h" #include "tlb.h" #include "frame_kern.h" #include "sigcontext.h" @@ -288,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt); void *um_kmalloc(int size) { - return(kmalloc(size, GFP_KERNEL)); + return kmalloc(size, GFP_KERNEL); } void *um_kmalloc_atomic(int size) { - return(kmalloc(size, GFP_ATOMIC)); + return kmalloc(size, GFP_ATOMIC); } void *um_vmalloc(int size) { - return(vmalloc(size)); + return vmalloc(size); +} + +void *um_vmalloc_atomic(int size) +{ + return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); +} + +int __cant_sleep(void) { + return in_atomic() || irqs_disabled() || in_interrupt(); + /* Is in_interrupt() really needed? */ } unsigned long get_fault_addr(void) @@ -370,11 +379,6 @@ int smp_sigio_handler(void) return(0); } -int um_in_interrupt(void) -{ - return(in_interrupt()); -} - int cpu(void) { return(current_thread->cpu); diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 6f1a3a288117..3ef73bf2e781 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -5,6 +5,7 @@ #include "linux/module.h" #include "linux/sched.h" +#include "asm/smp.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 62e5cfdf2188..f7b18e157d35 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -337,70 +337,103 @@ int ignore_sigio_fd(int fd) return(err); } -static int setup_initial_poll(int fd) +static struct pollfd* setup_initial_poll(int fd) { struct pollfd *p; - p = um_kmalloc_atomic(sizeof(struct pollfd)); - if(p == NULL){ + p = um_kmalloc(sizeof(struct pollfd)); + if (p == NULL) { printk("setup_initial_poll : failed to allocate poll\n"); - return(-1); + return NULL; } *p = ((struct pollfd) { .fd = fd, .events = POLLIN, .revents = 0 }); - current_poll = ((struct pollfds) { .poll = p, - .used = 1, - .size = 1 }); - return(0); + return p; } void write_sigio_workaround(void) { unsigned long stack; + struct pollfd *p; int err; + int l_write_sigio_fds[2]; + int l_sigio_private[2]; + int l_write_sigio_pid; + /* We call this *tons* of times - and most ones we must just fail. */ sigio_lock(); - if(write_sigio_pid != -1) - goto out; + l_write_sigio_pid = write_sigio_pid; + sigio_unlock(); - err = os_pipe(write_sigio_fds, 1, 1); + if (l_write_sigio_pid != -1) + return; + + err = os_pipe(l_write_sigio_fds, 1, 1); if(err < 0){ printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); - goto out; + return; } - err = os_pipe(sigio_private, 1, 1); + err = os_pipe(l_sigio_private, 1, 1); if(err < 0){ - printk("write_sigio_workaround - os_pipe 2 failed, " + printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); goto out_close1; } - if(setup_initial_poll(sigio_private[1])) + + p = setup_initial_poll(l_sigio_private[1]); + if(!p) goto out_close2; - write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, + sigio_lock(); + + /* Did we race? Don't try to optimize this, please, it's not so likely + * to happen, and no more than once at the boot. */ + if(write_sigio_pid != -1) + goto out_unlock; + + write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, CLONE_FILES | CLONE_VM, &stack, 0); - if(write_sigio_pid < 0) goto out_close2; + if (write_sigio_pid < 0) + goto out_clear; - if(write_sigio_irq(write_sigio_fds[0])) + if (write_sigio_irq(l_write_sigio_fds[0])) goto out_kill; - out: + /* Success, finally. */ + memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); + memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); + + current_poll = ((struct pollfds) { .poll = p, + .used = 1, + .size = 1 }); + sigio_unlock(); return; out_kill: - os_kill_process(write_sigio_pid, 1); + l_write_sigio_pid = write_sigio_pid; write_sigio_pid = -1; + sigio_unlock(); + /* Going to call waitpid, avoid holding the lock. */ + os_kill_process(l_write_sigio_pid, 1); + goto out_free; + + out_clear: + write_sigio_pid = -1; + out_unlock: + sigio_unlock(); + out_free: + kfree(p); out_close2: - os_close_file(sigio_private[0]); - os_close_file(sigio_private[1]); + os_close_file(l_sigio_private[0]); + os_close_file(l_sigio_private[1]); out_close1: - os_close_file(write_sigio_fds[0]); - os_close_file(write_sigio_fds[1]); - sigio_unlock(); + os_close_file(l_write_sigio_fds[0]); + os_close_file(l_write_sigio_fds[1]); + return; } int read_sigio_fd(int fd) diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 7b0e0e81c161..da17b7541e08 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, return err; } -static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) +static int kern_do_signal(struct pt_regs *regs) { struct k_sigaction ka_copy; siginfo_t info; + sigset_t *oldset; int sig, handled_sig = 0; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ handled_sig = 1; /* Whee! Actually deliver the signal. */ - if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); break; + } } /* Did we come from a system call? */ if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ /* Restart the system call - no handlers present */ - if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); PT_REGS_RESTART_SYSCALL(regs); - } - else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ + break; + case -ERESTART_RESTARTBLOCK: PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); + break; } } @@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) if(current->ptrace & PT_DTRACE) current->thread.singlestep_syscall = is_syscall(PT_REGS_IP(¤t->thread.regs)); + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return(handled_sig); } int do_signal(void) { - return(kern_do_signal(¤t->thread.regs, ¤t->blocked)); + return(kern_do_signal(¤t->thread.regs)); } /* @@ -150,63 +172,20 @@ int do_signal(void) */ long sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if(kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } -} - -long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } - -/* - * 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/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 7a9fc16d71d4..57181a920d48 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -1,12 +1,12 @@ -# +# # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # -obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ +obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ syscall.o tlb.o uaccess.o -USER_OBJS := process.o clone.o +USER_OBJS := clone.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h deleted file mode 100644 index 44110c521e49..000000000000 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MMU_H -#define __SKAS_MMU_H - -#include "linux/config.h" -#include "mm_id.h" -#include "asm/ldt.h" - -struct mmu_context_skas { - struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; -#endif - uml_ldt_t ldt; -}; - -extern void switch_mm_skas(struct mm_id * mm_idp); - -#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/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h deleted file mode 100644 index bcd26a6a3888..000000000000 --- a/arch/um/kernel/skas/include/mode-skas.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_SKAS_H__ -#define __MODE_SKAS_H__ - -#include <sysdep/ptrace.h> - -extern unsigned long exec_regs[]; -extern unsigned long exec_fp_regs[]; -extern unsigned long exec_fpx_regs[]; -extern int have_fpx_regs; - -extern void sig_handler_common_skas(int sig, void *sc_ptr); -extern void halt_skas(void); -extern void reboot_skas(void); -extern void kill_off_processes_skas(void); -extern int is_skas_winch(int pid, int fd, void *data); - -#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/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h deleted file mode 100644 index 01d489de3986..000000000000 --- a/arch/um/kernel/skas/include/skas.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_H -#define __SKAS_H - -#include "mm_id.h" -#include "sysdep/ptrace.h" - -extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo, ptrace_ldt; -extern int skas_needs_stub; - -extern void switch_threads(void *me, void *next); -extern void thread_wait(void *sw, void *fb); -extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, - void (*handler)(int)); -extern int start_idle_thread(void *stack, void *switch_buf_ptr, - void **fork_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 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, - unsigned long len, int r, int w, int x, int phys_fd, - unsigned long long offset, int done, void **data); -extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, - int done, void **data); -extern int protect(struct mm_id * mm_idp, unsigned long addr, - unsigned long len, int r, int w, int x, int done, - void **data); -extern void user_signal(int sig, union uml_pt_regs *regs, int pid); -extern int new_mm(int from, unsigned long stack); -extern int start_userspace(unsigned long stub_stack); -extern int copy_context_skas0(unsigned long stack, int pid); -extern void get_skas_faultinfo(int pid, struct faultinfo * fi); -extern long execute_syscall_skas(void *r); -extern unsigned long current_stub_stack(void); -extern long run_syscall_stub(struct mm_id * mm_idp, - int syscall, unsigned long *args, long expected, - void **addr, int done); -extern long syscall_stub_data(struct mm_id * mm_idp, - unsigned long *data, int data_count, - void **addr, void **stub_addr); - -#endif diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 677871f1b37c..c5c9885a8297 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) struct mmu_context_skas *from_mm = NULL; struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from_fd, ret = -ENOMEM; + int ret = -ENOMEM; if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); @@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) from_mm = ¤t->mm->context.skas; if(proc_mm){ - if(from_mm) - from_fd = from_mm->id.u.mm_fd; - else from_fd = -1; - - ret = new_mm(from_fd, stack); + ret = new_mm(stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index dc41c6dc2f34..3f70a2e12f06 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,14 +13,12 @@ #include "asm/uaccess.h" #include "asm/atomic.h" #include "kern_util.h" -#include "time_user.h" #include "skas.h" #include "os.h" #include "user_util.h" #include "tlb.h" #include "kern.h" #include "mode.h" -#include "proc_mm.h" #include "registers.h" void switch_to_skas(void *prev, void *next) @@ -34,7 +32,7 @@ void switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - switch_threads(&from->thread.mode.skas.switch_buf, + switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); if(current->pid == 0) @@ -50,8 +48,8 @@ void new_thread_handler(int sig) fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); if(current->thread.prev_sched != NULL) @@ -82,8 +80,8 @@ void release_thread_skas(struct task_struct *task) void fork_handler(int sig) { - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); force_flush_all(); @@ -93,13 +91,13 @@ void fork_handler(int sig) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; - /* Handle any immediate reschedules or signals */ +/* Handle any immediate reschedules or signals */ interrupt_end(); userspace(¤t->thread.regs.regs); } int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, + unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { void (*handler)(int); @@ -123,27 +121,14 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, return(0); } -extern void map_stub_pages(int fd, unsigned long code, - unsigned long data, unsigned long stack); -int new_mm(int from, unsigned long stack) +int new_mm(unsigned long stack) { - struct proc_mm_op copy; - int n, fd; + int fd; fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); if(fd < 0) return(fd); - if(from != -1){ - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, - .u = - { .copy_segments = from } } ); - n = os_write_file(fd, ©, sizeof(copy)); - if(n != sizeof(copy)) - printk("new_mm : /proc/mm copy_segments failed, " - "err = %d\n", -n); - } - if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index a5a47528dec7..5992c3257167 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -13,7 +13,7 @@ #include "asm/pgtable.h" #include "asm/uaccess.h" #include "kern_util.h" -#include "user_util.h" +#include "os.h" extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 1429c131879d..1731d90e6850 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -25,12 +25,12 @@ int record_syscall_start(int syscall) syscall_record[index].syscall = syscall; syscall_record[index].pid = current_pid(); syscall_record[index].result = 0xdeadbeef; - syscall_record[index].start = os_usecs(); + syscall_record[index].start = os_nsecs(); return(index); } void record_syscall_end(int index, long result) { syscall_record[index].result = result; - syscall_record[index].end = os_usecs(); + syscall_record[index].end = os_nsecs(); } diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 020ca79b8d33..3c7626cdba4b 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,12 +13,12 @@ #include "linux/interrupt.h" #include "linux/init.h" #include "linux/delay.h" +#include "linux/hrtimer.h" #include "asm/irq.h" #include "asm/param.h" #include "asm/current.h" #include "kern_util.h" #include "user_util.h" -#include "time_user.h" #include "mode.h" #include "os.h" @@ -39,7 +39,7 @@ unsigned long long sched_clock(void) int timer_irq_inited = 0; static int first_tick; -static unsigned long long prev_usecs; +static unsigned long long prev_nsecs; #ifdef CONFIG_UML_REAL_TIME_CLOCK static long long delta; /* Deviation per interval */ #endif @@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs) if(first_tick){ #ifdef CONFIG_UML_REAL_TIME_CLOCK /* We've had 1 tick */ - unsigned long long usecs = os_usecs(); + unsigned long long nsecs = os_nsecs(); - delta += usecs - prev_usecs; - prev_usecs = usecs; + delta += nsecs - prev_nsecs; + prev_nsecs = nsecs; /* Protect against the host clock being set backwards */ if(delta < 0) delta = 0; - ticks += (delta * HZ) / MILLION; - delta -= (ticks * MILLION) / HZ; + ticks += (delta * HZ) / BILLION; + delta -= (ticks * BILLION) / HZ; #else ticks = 1; #endif } else { - prev_usecs = os_usecs(); + prev_nsecs = os_nsecs(); first_tick = 1; } @@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs) } } -void boot_timer_handler(int sig) +void do_boot_timer_handler(struct sigcontext * sc) { struct pt_regs regs; - CHOOSE_MODE((void) - (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), + CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), (void) (regs.regs.skas.is_user = 0)); do_timer(®s); } +static DEFINE_SPINLOCK(timer_spinlock); + +static unsigned long long local_offset = 0; + +static inline unsigned long long get_time(void) +{ + unsigned long long nsecs; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + nsecs = os_nsecs(); + nsecs += local_offset; + spin_unlock_irqrestore(&timer_spinlock, flags); + + return nsecs; +} + irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) { + unsigned long long nsecs; unsigned long flags; do_timer(regs); + write_seqlock_irqsave(&xtime_lock, flags); - timer(); + nsecs = get_time() + local_offset; + xtime.tv_sec = nsecs / NSEC_PER_SEC; + xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; write_sequnlock_irqrestore(&xtime_lock, flags); + return(IRQ_HANDLED); } long um_time(int __user *tloc) { - struct timeval now; + long ret = get_time() / NSEC_PER_SEC; - do_gettimeofday(&now); - if (tloc) { - if (put_user(now.tv_sec, tloc)) - now.tv_sec = -EFAULT; - } - return now.tv_sec; + if((tloc != NULL) && put_user(ret, tloc)) + return -EFAULT; + + return ret; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long long nsecs = get_time(); + + tv->tv_sec = nsecs / NSEC_PER_SEC; + /* Careful about calculations here - this was originally done as + * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC + * which gave bogus (> 1000000) values. Dunno why, suspect gcc + * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion + * problem that I missed. + */ + nsecs -= tv->tv_sec * NSEC_PER_SEC; + tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; +} + +static inline void set_time(unsigned long long nsecs) +{ + unsigned long long now; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + now = os_nsecs(); + local_offset = nsecs - now; + spin_unlock_irqrestore(&timer_spinlock, flags); + + clock_was_set(); } long um_stime(int __user *tptr) { int value; - struct timespec new; if (get_user(value, tptr)) return -EFAULT; - new.tv_sec = value; - new.tv_nsec = 0; - do_settimeofday(&new); + + set_time((unsigned long long) value * NSEC_PER_SEC); + + return 0; +} + +int do_settimeofday(struct timespec *tv) +{ + set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); + return 0; } @@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs) { local_irq_disable(); irq_enter(); - update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), - (regs)->skas.is_user)); + update_process_times(CHOOSE_MODE( + (UPT_SC(regs) && user_context(UPT_SP(regs))), + (regs)->skas.is_user)); irq_exit(); local_irq_enable(); if(current_thread->cpu == 0) timer_irq(regs); } -static DEFINE_SPINLOCK(timer_spinlock); - -unsigned long time_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&timer_spinlock, flags); - return(flags); -} - -void time_unlock(unsigned long flags) -{ - spin_unlock_irqrestore(&timer_spinlock, flags); -} - int __init timer_init(void) { int err; @@ -171,14 +210,3 @@ int __init timer_init(void) } __initcall(timer_init); - -/* - * 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/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 8f40e4838736..5c1e4cc1c049 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -13,7 +13,6 @@ #include "user_util.h" #include "kern_util.h" #include "irq_user.h" -#include "time_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 37e22d71a0d9..786e4edd86c5 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -20,6 +20,7 @@ #include "user_util.h" #include "tt.h" #include "sysdep/thread.h" +#include "os.h" extern int debugger_pid; extern int debugger_fd; diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h deleted file mode 100644 index 0440510ab3fe..000000000000 --- a/arch/um/kernel/tt/include/mmu-tt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MMU_H -#define __TT_MMU_H - -struct mmu_context_tt { -}; - -#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/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 62535303aa27..295c1ac817b3 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -18,7 +18,6 @@ #include "os.h" #include "kern.h" #include "sigcontext.h" -#include "time_user.h" #include "mem_user.h" #include "tlb.h" #include "mode.h" diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c index 528a5fc8d887..03774427d468 100644 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ b/arch/um/kernel/tt/ptproxy/ptrace.c @@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml #include "kern_util.h" #include "ptrace_user.h" #include "tt.h" +#include "os.h" long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, long arg3, long arg4, pid_t child, int *ret) diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index a5f0e01e214e..99f178319d03 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -15,6 +15,7 @@ terms and conditions. #include "ptrace_user.h" #include "user_util.h" #include "user.h" +#include "os.h" int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, long *arg5) diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 3d29c90514cc..3fda9a03c59a 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c @@ -23,16 +23,20 @@ void syscall_handler_tt(int sig, struct pt_regs *regs) int syscall; #ifdef CONFIG_SYSCALL_DEBUG int index; - index = record_syscall_start(syscall); #endif sc = UPT_SC(®s->regs); SC_START_SYSCALL(sc); + syscall = UPT_SYSCALL_NR(®s->regs); + +#ifdef CONFIG_SYSCALL_DEBUG + index = record_syscall_start(syscall); +#endif + syscall_trace(®s->regs, 0); current->thread.nsyscalls++; nsyscalls++; - syscall = UPT_SYSCALL_NR(®s->regs); if((syscall >= NR_syscalls) || (syscall < 0)) result = -ENOSYS; diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index a414c529fbcd..b5d9d64d91e4 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -18,7 +18,7 @@ void sig_handler_common_tt(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct tt_regs save_regs, *r; - int save_errno = errno, is_user; + int save_errno = errno, is_user = 0; void (*handler)(int, union uml_pt_regs *); /* This is done because to allow SIGSEGV to be delivered inside a SEGV @@ -35,7 +35,8 @@ void sig_handler_common_tt(int sig, void *sc_ptr) GET_FAULTINFO_FROM_SC(r->faultinfo, sc); } save_regs = *r; - is_user = user_context(SC_SP(sc)); + if (sc) + is_user = user_context(SC_SP(sc)); r->sc = sc; if(sig != SIGUSR2) r->syscall = -1; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index e2d3ca445ef5..27cdf9164422 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -193,6 +193,24 @@ __uml_setup("root=", uml_root_setup, " root=/dev/ubd5\n\n" ); +#ifndef CONFIG_MODE_TT + +static int __init no_skas_debug_setup(char *line, int *add) +{ + printf("'debug' is not necessary to gdb UML in skas mode - run \n"); + printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); + printf("doesn't work as expected\n"); + + return 0; +} + +__uml_setup("debug", no_skas_debug_setup, +"debug\n" +" this flag is not needed to run gdb on UML in skas mode\n\n" +); + +#endif + #ifdef CONFIG_SMP static int __init uml_ncpus_setup(char *line, int *add) { diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 40c7d6b1df68..08a4e628b24c 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -5,12 +5,12 @@ 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)/ + util.o drivers/ sys-$(SUBARCH)/ obj-$(CONFIG_MODE_SKAS) += skas/ 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 trap.o tt.o tty.o uaccess.o umid.o util.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 52945338b64d..87c3aa0252db 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -122,6 +122,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, return(-EINVAL); } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; + os_set_exec_close(*fd_out, 1); return(0); } @@ -137,7 +138,8 @@ static int tuntap_open(void *data) return(err); if(pri->fixed_config){ - pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); + pri->fd = os_open_file("/dev/net/tun", + of_cloexec(of_rdwr(OPENFLAGS())), 0); if(pri->fd < 0){ printk("Failed to open /dev/net/tun, err = %d\n", -pri->fd); diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 36cc8475bcda..6490a4ff40ac 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, if((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; - else stack = alloc_stack(0, um_in_interrupt()); + else stack = alloc_stack(0, __cant_sleep()); if(stack == 0) return(-ENOMEM); @@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long stack, sp; int pid, status, err; - stack = alloc_stack(stack_order, um_in_interrupt()); + stack = alloc_stack(stack_order, __cant_sleep()); if(stack == 0) return(-ENOMEM); sp = stack + (page_size() << stack_order) - sizeof(void *); diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 172c8474453c..2878e89a674f 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -16,7 +16,6 @@ #include "user_util.h" #include "kern_util.h" #include "mem_user.h" -#include "time_user.h" #include "irq_user.h" #include "user.h" #include "init.h" @@ -82,20 +81,8 @@ extern void scan_elf_aux( char **envp); int main(int argc, char **argv, char **envp) { char **new_argv; - sigset_t mask; int ret, i, err; - /* Enable all signals except SIGIO - in some environments, we can - * enter with some signals blocked - */ - - sigemptyset(&mask); - sigaddset(&mask, SIGIO); - if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ - perror("sigprocmask"); - exit(1); - } - #ifdef UML_CONFIG_CMDLINE_ON_HOST /* Allocate memory for thread command lines */ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 39815c6b5e45..7f5e2dac2a35 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -18,6 +18,7 @@ #include "process.h" #include "irq_user.h" #include "kern_util.h" +#include "longjmp.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -205,24 +206,13 @@ void init_new_thread_signals(int altstack) int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) { - sigjmp_buf buf; - int n; - - *jmp_ptr = &buf; - n = sigsetjmp(buf, 1); - if(n != 0) - return(n); - (*fn)(arg); - return(0); + sigjmp_buf buf; + int n, enable; + + *jmp_ptr = &buf; + n = UML_SIGSETJMP(&buf, enable); + if(n != 0) + return(n); + (*fn)(arg); + return(0); } - -/* - * 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/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index c1f46a0fef13..f11b3124a0c8 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -12,32 +12,66 @@ #include <string.h> #include <sys/mman.h> #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 "os.h" + +/* 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 SIGIO_MASK (1 << SIGIO_BIT) + +#define SIGVTALRM_BIT 1 +#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) + +#define SIGALRM_BIT 2 +#define SIGALRM_MASK (1 << SIGALRM_BIT) + +static int signals_enabled = 1; +static int pending = 0; void sig_handler(ARCH_SIGHDLR_PARAM) { struct sigcontext *sc; + int enabled; + + /* Must be the first thing that this handler does - x86_64 stores + * the sigcontext in %rdx, and we need to save it before it has a + * chance to get trashed. + */ ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!enabled && (sig == SIGIO)){ + pending |= SIGIO_MASK; + return; + } + + block_signals(); + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, sig, sc); + + set_signals(enabled); } extern int timer_irq_inited; -void alarm_handler(ARCH_SIGHDLR_PARAM) +static void real_alarm_handler(int sig, struct sigcontext *sc) { - struct sigcontext *sc; - - ARCH_GET_SIGCONTEXT(sc, sig); - if(!timer_irq_inited) return; + if(!timer_irq_inited){ + signals_enabled = 1; + return; + } if(sig == SIGALRM) switch_timers(0); @@ -47,6 +81,52 @@ void alarm_handler(ARCH_SIGHDLR_PARAM) if(sig == SIGALRM) switch_timers(1); + +} + +void alarm_handler(ARCH_SIGHDLR_PARAM) +{ + struct sigcontext *sc; + int enabled; + + ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!signals_enabled){ + if(sig == SIGVTALRM) + pending |= SIGVTALRM_MASK; + else pending |= SIGALRM_MASK; + + return; + } + + block_signals(); + + real_alarm_handler(sig, sc); + set_signals(enabled); +} + +extern void do_boot_timer_handler(struct sigcontext * sc); + +void boot_timer_handler(ARCH_SIGHDLR_PARAM) +{ + struct sigcontext *sc; + int enabled; + + ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!enabled){ + if(sig == SIGVTALRM) + pending |= SIGVTALRM_MASK; + else pending |= SIGALRM_MASK; + return; + } + + block_signals(); + + do_boot_timer_handler(sc); + set_signals(enabled); } void set_sigstack(void *sig_stack, int size) @@ -73,6 +153,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) { struct sigaction action; va_list ap; + sigset_t sig_mask; int mask; va_start(ap, flags); @@ -85,7 +166,12 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) action.sa_flags = flags; action.sa_restorer = NULL; if(sigaction(sig, &action, NULL) < 0) - panic("sigaction failed"); + panic("sigaction failed - errno = %d\n", errno); + + sigemptyset(&sig_mask); + sigaddset(&sig_mask, sig); + if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) + panic("sigprocmask failed - errno = %d\n", errno); } int change_sig(int signal, int on) @@ -98,89 +184,77 @@ int change_sig(int signal, int on) 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); + signals_enabled = 0; } void unblock_signals(void) { - change_signals(SIG_UNBLOCK); -} + int save_pending; -/* 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 + if(signals_enabled == 1) + return; -static int enable_mask(sigset_t *mask) -{ - int sigs; + /* We loop because the IRQ handler returns with interrupts off. So, + * interrupts may have arrived and we need to re-enable them and + * recheck pending. + */ + while(1){ + /* Save and reset save_pending after enabling signals. This + * way, pending won't be changed while we're reading it. + */ + signals_enabled = 1; + + save_pending = pending; + if(save_pending == 0) + return; + + pending = 0; + + /* We have pending interrupts, so disable signals, as the + * handlers expect them off when they are called. They will + * be enabled again above. + */ + + signals_enabled = 0; - 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); + /* Deal with SIGIO first because the alarm handler might + * schedule, leaving the pending SIGIO stranded until we come + * back here. + */ + if(save_pending & SIGIO_MASK) + CHOOSE_MODE_PROC(sig_handler_common_tt, + sig_handler_common_skas, SIGIO, NULL); + + if(save_pending & SIGALRM_MASK) + real_alarm_handler(SIGALRM, NULL); + + if(save_pending & SIGVTALRM_MASK) + real_alarm_handler(SIGVTALRM, NULL); + } } int get_signals(void) { - sigset_t mask; - - if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) - panic("Failed to get signal mask"); - return(enable_mask(&mask)); + return signals_enabled; } int set_signals(int enable) { - sigset_t mask; int ret; + if(signals_enabled == enable) + return enable; - sigemptyset(&mask); - if(enable & (1 << SIGIO_BIT)) - sigaddset(&mask, SIGIO); - if(enable & (1 << SIGVTALRM_BIT)){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } + ret = signals_enabled; + if(enable) + unblock_signals(); + else block_signals(); - /* 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; +} - return(ret); +void os_usr1_signal(int on) +{ + change_sig(SIGUSR1, on); } diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile index eab5386d60a7..5fd8d4dad66a 100644 --- a/arch/um/os-Linux/skas/Makefile +++ b/arch/um/os-Linux/skas/Makefile @@ -3,8 +3,8 @@ # Licensed under the GPL # -obj-y := trap.o +obj-y := mem.o process.o trap.o -USER_OBJS := trap.o +USER_OBJS := mem.o process.o trap.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c index 1d89640bd502..fbb080c2fc26 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/os-Linux/skas/mem.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname); static inline unsigned long *check_init_stack(struct mm_id * mm_idp, unsigned long *stack) { - if(stack == NULL){ + if(stack == NULL) { stack = (unsigned long *) mm_idp->stack + 2; *stack = 0; } @@ -45,13 +45,14 @@ int single_count = 0; int multi_count = 0; int multi_op_count = 0; -static long do_syscall_stub(struct mm_id *mm_idp, void **addr) +static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) { unsigned long regs[MAX_REG_NR]; - unsigned long *data; - unsigned long *syscall; + int n; long ret, offset; - int n, pid = mm_idp->u.pid; + unsigned long * data; + unsigned long * syscall; + int pid = mm_idp->u.pid; if(proc_mm) #warning Need to look up userspace_pid by cpu @@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) multi_count++; - get_safe_registers(regs); - regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + get_safe_registers(regs, NULL); + regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + ((unsigned long) &batch_syscall_stub - - (unsigned long) &__syscall_stub_start); + (unsigned long) &__syscall_stub_start); + n = ptrace_setregs(pid, regs); if(n < 0) panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", @@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) if (offset) { data = (unsigned long *)(mm_idp->stack + offset - UML_CONFIG_STUB_DATA); + printk("do_syscall_stub : ret = %d, offset = %d, " + "data = 0x%x\n", ret, offset, data); syscall = (unsigned long *)((unsigned long)data + data[0]); printk("do_syscall_stub: syscall %ld failed, return value = " "0x%lx, expected return value = 0x%lx\n", @@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) long run_syscall_stub(struct mm_id * mm_idp, int syscall, unsigned long *args, long expected, void **addr, - int done) + int done) { - unsigned long *stack = check_init_stack(mm_idp, *addr); + unsigned long *stack = check_init_stack(mm_idp, *addr); if(done && *addr == NULL) single_count++; - *stack += sizeof(long); + *stack += sizeof(long); stack += *stack / sizeof(long); - *stack++ = syscall; - *stack++ = args[0]; - *stack++ = args[1]; - *stack++ = args[2]; - *stack++ = args[3]; - *stack++ = args[4]; - *stack++ = args[5]; + *stack++ = syscall; + *stack++ = args[0]; + *stack++ = args[1]; + *stack++ = args[2]; + *stack++ = args[3]; + *stack++ = args[4]; + *stack++ = args[5]; *stack++ = expected; - *stack = 0; - multi_op_count++; + *stack = 0; + multi_op_count++; - if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < + if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < PAGE_SIZE - 10 * sizeof(long))){ *addr = stack; - return 0; - } + return 0; + } return do_syscall_stub(mm_idp, addr); } @@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp, if((((unsigned long) *addr) & ~PAGE_MASK) >= PAGE_SIZE - (10 + data_count) * sizeof(long)) { ret = do_syscall_stub(mm_idp, addr); - /* in case of error, don't overwrite data on stack */ + /* in case of error, don't overwrite data on stack */ if(ret) return ret; } @@ -172,39 +176,39 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int r, int w, int x, int phys_fd, unsigned long long offset, int done, void **data) { - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - struct proc_mm_op map; - int fd = mm_idp->u.mm_fd; - - map = ((struct proc_mm_op) { .op = MM_MMAP, - .u = - { .mmap = - { .addr = virt, - .len = len, - .prot = prot, - .flags = MAP_SHARED | - MAP_FIXED, - .fd = phys_fd, - .offset= offset - } } } ); + int prot, ret; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + + if(proc_mm){ + struct proc_mm_op map; + int fd = mm_idp->u.mm_fd; + + map = ((struct proc_mm_op) { .op = MM_MMAP, + .u = + { .mmap = + { .addr = virt, + .len = len, + .prot = prot, + .flags = MAP_SHARED | + MAP_FIXED, + .fd = phys_fd, + .offset= offset + } } } ); ret = os_write_file(fd, &map, sizeof(map)); if(ret != sizeof(map)) printk("map : /proc/mm map failed, err = %d\n", -ret); else ret = 0; - } - else { - unsigned long args[] = { virt, len, prot, - MAP_SHARED | MAP_FIXED, phys_fd, - MMAP_OFFSET(offset) }; + } + else { + unsigned long args[] = { virt, len, prot, + MAP_SHARED | MAP_FIXED, phys_fd, + MMAP_OFFSET(offset) }; ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, data, done); - } + } return ret; } @@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, void **data) { - int ret; - - if(proc_mm){ - struct proc_mm_op unmap; - int fd = mm_idp->u.mm_fd; - - unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, - .u = - { .munmap = - { .addr = - (unsigned long) addr, - .len = len } } } ); + int ret; + + if(proc_mm){ + struct proc_mm_op unmap; + int fd = mm_idp->u.mm_fd; + + unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, + .u = + { .munmap = + { .addr = + (unsigned long) addr, + .len = len } } } ); ret = os_write_file(fd, &unmap, sizeof(unmap)); if(ret != sizeof(unmap)) printk("unmap - proc_mm write returned %d\n", ret); else ret = 0; - } - else { - unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, - 0 }; + } + else { + unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, + 0 }; ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, data, done); - if(ret < 0) - printk("munmap stub failed, errno = %d\n", ret); - } + } - return ret; + return ret; } int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, int r, int w, int x, int done, void **data) { - struct proc_mm_op protect; - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - int fd = mm_idp->u.mm_fd; - protect = ((struct proc_mm_op) { .op = MM_MPROTECT, - .u = - { .mprotect = - { .addr = - (unsigned long) addr, - .len = len, - .prot = prot } } } ); - - ret = os_write_file(fd, &protect, sizeof(protect)); - if(ret != sizeof(protect)) - printk("protect failed, err = %d", -ret); - else ret = 0; - } - else { - unsigned long args[] = { addr, len, prot, 0, 0, 0 }; - - ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, - data, done); - } - - return ret; + struct proc_mm_op protect; + int prot, ret; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + if(proc_mm){ + int fd = mm_idp->u.mm_fd; + + protect = ((struct proc_mm_op) { .op = MM_MPROTECT, + .u = + { .mprotect = + { .addr = + (unsigned long) addr, + .len = len, + .prot = prot } } } ); + + ret = os_write_file(fd, &protect, sizeof(protect)); + if(ret != sizeof(protect)) + printk("protect failed, err = %d", -ret); + else ret = 0; + } + else { + unsigned long args[] = { addr, len, prot, 0, 0, 0 }; + + ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, + data, done); + } + + return ret; } void before_mem_skas(unsigned long unused) diff --git a/arch/um/kernel/skas/process.c b/arch/um/os-Linux/skas/process.c index 3b3955d84407..bbf34cb91ce1 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -10,6 +10,7 @@ #include <signal.h> #include <setjmp.h> #include <sched.h> +#include "ptrace_user.h" #include <sys/wait.h> #include <sys/mman.h> #include <sys/user.h> @@ -17,8 +18,6 @@ #include <asm/unistd.h> #include <asm/types.h> #include "user.h" -#include "ptrace_user.h" -#include "time_user.h" #include "sysdep/ptrace.h" #include "user_util.h" #include "kern_util.h" @@ -35,10 +34,11 @@ #include "mem.h" #include "uml-config.h" #include "process.h" +#include "longjmp.h" int is_skas_winch(int pid, int fd, void *data) { - if(pid != os_getpgrp()) + if(pid != os_getpgrp()) return(0); register_winch_irq(-1, fd, -1, data); @@ -47,28 +47,29 @@ int is_skas_winch(int pid, int fd, void *data) void wait_stub_done(int pid, int sig, char * fname) { - int n, status, err; - - do { - if ( sig != -1 ) { - err = ptrace(PTRACE_CONT, pid, 0, sig); - if(err) - panic("%s : continue failed, errno = %d\n", - fname, errno); - } - sig = 0; - - CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - } while((n >= 0) && WIFSTOPPED(status) && - ((WSTOPSIG(status) == SIGVTALRM) || + int n, status, err; + + do { + if ( sig != -1 ) { + err = ptrace(PTRACE_CONT, pid, 0, sig); + if(err) + panic("%s : continue failed, errno = %d\n", + fname, errno); + } + sig = 0; + + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + } while((n >= 0) && WIFSTOPPED(status) && + ((WSTOPSIG(status) == SIGVTALRM) || /* running UML inside a detached screen can cause * SIGWINCHes */ (WSTOPSIG(status) == SIGWINCH))); - if((n < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ + if((n < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ unsigned long regs[HOST_FRAME_SIZE]; + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) printk("Failed to get registers from stub, " "errno = %d\n", errno); @@ -79,42 +80,44 @@ void wait_stub_done(int pid, int sig, char * fname) for(i = 0; i < HOST_FRAME_SIZE; i++) printk("\t%d - %lx\n", i, regs[i]); } - panic("%s : failed to wait for SIGUSR1/SIGTRAP, " - "pid = %d, n = %d, errno = %d, status = 0x%x\n", - fname, pid, n, errno, status); - } + panic("%s : failed to wait for SIGUSR1/SIGTRAP, " + "pid = %d, n = %d, errno = %d, status = 0x%x\n", + fname, pid, n, errno, status); + } } +extern unsigned long current_stub_stack(void); + void get_skas_faultinfo(int pid, struct faultinfo * fi) { - int err; - - if(ptrace_faultinfo){ - err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if(err) - panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " - "errno = %d\n", errno); - - /* Special handling for i386, which has different structs */ - if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) - memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, - sizeof(struct faultinfo) - - sizeof(struct ptrace_faultinfo)); - } - else { - wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); - - /* faultinfo is prepared by the stub-segv-handler at start of - * the stub stack page. We just have to copy it. - */ - memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); - } + int err; + + if(ptrace_faultinfo){ + err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); + if(err) + panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " + "errno = %d\n", errno); + + /* Special handling for i386, which has different structs */ + if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) + memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, + sizeof(struct faultinfo) - + sizeof(struct ptrace_faultinfo)); + } + else { + wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); + + /* faultinfo is prepared by the stub-segv-handler at start of + * the stub stack page. We just have to copy it. + */ + memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); + } } static void handle_segv(int pid, union uml_pt_regs * regs) { - get_skas_faultinfo(pid, ®s->skas.faultinfo); - segv(regs->skas.faultinfo, 0, 1, NULL); + get_skas_faultinfo(pid, ®s->skas.faultinfo); + segv(regs->skas.faultinfo, 0, 1, NULL); } /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ @@ -127,7 +130,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu if (!local_using_sysemu) { - err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); + err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, + __NR_getpid); if(err < 0) panic("handle_trap - nullifying syscall failed errno = %d\n", errno); @@ -148,8 +152,6 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu } extern int __syscall_stub_start; -int stub_code_fd = -1; -__u64 stub_code_offset; static int userspace_tramp(void *stack) { @@ -164,31 +166,30 @@ static int userspace_tramp(void *stack) /* This has a pte, but it can't be mapped in with the usual * tlb_flush mechanism because this is part of that mechanism */ + int fd; + __u64 offset; + fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), - PROT_EXEC, MAP_FIXED | MAP_PRIVATE, - stub_code_fd, stub_code_offset); + PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); if(addr == MAP_FAILED){ - printk("mapping stub code failed, errno = %d\n", + printk("mapping mmap stub failed, errno = %d\n", errno); exit(1); } if(stack != NULL){ - int fd; - __u64 offset; - fd = phys_mapping(to_phys(stack), &offset); addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); if(addr == MAP_FAILED){ - printk("mapping stub stack failed, " + printk("mapping segfault stack failed, " "errno = %d\n", errno); exit(1); } } } - if(!ptrace_faultinfo){ + if(!ptrace_faultinfo && (stack != NULL)){ unsigned long v = UML_CONFIG_STUB_CODE + (unsigned long) stub_segv_handler - (unsigned long) &__syscall_stub_start; @@ -214,10 +215,6 @@ int start_userspace(unsigned long stub_stack) unsigned long sp; int pid, status, n, flags; - if ( stub_code_fd == -1 ) - stub_code_fd = phys_mapping(to_phys(&__syscall_stub_start), - &stub_code_offset); - stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(stack == MAP_FAILED) @@ -233,7 +230,7 @@ int start_userspace(unsigned long stub_stack) do { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) - panic("start_userspace : wait failed, errno = %d", + panic("start_userspace : wait failed, errno = %d", errno); } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); @@ -242,7 +239,7 @@ int start_userspace(unsigned long stub_stack) status); if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n", + panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", errno); if(munmap(stack, PAGE_SIZE) < 0) @@ -272,7 +269,7 @@ void userspace(union uml_pt_regs *regs) CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) - panic("userspace - waitpid failed, errno = %d\n", + panic("userspace - waitpid failed, errno = %d\n", errno); regs->skas.is_user = 1; @@ -282,9 +279,9 @@ void userspace(union uml_pt_regs *regs) if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: - if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) - user_signal(SIGSEGV, regs, pid); - else handle_segv(pid, regs); + if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) + user_signal(SIGSEGV, regs, pid); + else handle_segv(pid, regs); break; case SIGTRAP + 0x80: handle_trap(pid, regs, local_using_sysemu); @@ -298,7 +295,7 @@ void userspace(union uml_pt_regs *regs) case SIGBUS: case SIGFPE: case SIGWINCH: - user_signal(WSTOPSIG(status), regs, pid); + user_signal(WSTOPSIG(status), regs, pid); break; default: printk("userspace - child stopped with signal " @@ -308,21 +305,17 @@ void userspace(union uml_pt_regs *regs) interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ - PT_SYSCALL_NR(regs->skas.regs) = -1; + if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) + PT_SYSCALL_NR(regs->skas.regs) = -1; } } } -#define INIT_JMP_NEW_THREAD 0 -#define INIT_JMP_REMOVE_SIGSTACK 1 -#define INIT_JMP_CALLBACK 2 -#define INIT_JMP_HALT 3 -#define INIT_JMP_REBOOT 4 - int copy_context_skas0(unsigned long new_stack, int pid) { int err; - unsigned long regs[MAX_REG_NR]; + unsigned long regs[HOST_FRAME_SIZE]; + unsigned long fp_regs[HOST_FP_SIZE]; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; struct stub_data *child_data = (struct stub_data *) new_stack; @@ -334,10 +327,10 @@ int copy_context_skas0(unsigned long new_stack, int pid) */ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), .fd = new_fd, - .timer = ((struct itimerval) - { { 0, 1000000 / hz() }, - { 0, 1000000 / hz() }})}); - get_safe_registers(regs); + .timer = ((struct itimerval) + { { 0, 1000000 / hz() }, + { 0, 1000000 / hz() }})}); + get_safe_registers(regs, fp_regs); /* Set parent's instruction pointer to start of clone-stub */ regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + @@ -345,11 +338,19 @@ int copy_context_skas0(unsigned long new_stack, int pid) (unsigned long) &__syscall_stub_start; regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - sizeof(void *); +#ifdef __SIGNAL_FRAMESIZE + regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; +#endif err = ptrace_setregs(pid, regs); if(err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, errno); + err = ptrace_setfpregs(pid, fp_regs); + if(err < 0) + panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " + "pid = %d, errno = %d\n", pid, errno); + /* set a well known return code for detection of child write failure */ child_data->err = 12345678; @@ -373,7 +374,7 @@ int copy_context_skas0(unsigned long new_stack, int pid) if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, " + panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " "errno = %d\n", errno); return pid; @@ -389,6 +390,9 @@ void map_stub_pages(int fd, unsigned long code, { struct proc_mm_op mmop; int n; + __u64 code_offset; + int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), + &code_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, .u = @@ -397,8 +401,8 @@ void map_stub_pages(int fd, unsigned long code, .len = PAGE_SIZE, .prot = PROT_EXEC, .flags = MAP_FIXED | MAP_PRIVATE, - .fd = stub_code_fd, - .offset = stub_code_offset + .fd = code_fd, + .offset = code_offset } } }); n = os_write_file(fd, &mmop, sizeof(mmop)); if(n != sizeof(mmop)) @@ -431,6 +435,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, { unsigned long flags; sigjmp_buf switch_buf, fork_buf; + int enable; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; @@ -445,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, */ flags = get_signals(); block_signals(); - if(sigsetjmp(fork_buf, 1) == 0) + if(UML_SIGSETJMP(&fork_buf, enable) == 0) new_thread_proc(stack, handler); remove_sigstack(); @@ -453,23 +458,31 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, set_signals(flags); } +#define INIT_JMP_NEW_THREAD 0 +#define INIT_JMP_REMOVE_SIGSTACK 1 +#define INIT_JMP_CALLBACK 2 +#define INIT_JMP_HALT 3 +#define INIT_JMP_REBOOT 4 + void thread_wait(void *sw, void *fb) { sigjmp_buf buf, **switch_buf = sw, *fork_buf; + int enable; *switch_buf = &buf; fork_buf = fb; - if(sigsetjmp(buf, 1) == 0) + if(UML_SIGSETJMP(&buf, enable) == 0) siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); } void switch_threads(void *me, void *next) { sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; - + int enable; + *me_ptr = &my_buf; - if(sigsetjmp(my_buf, 1) == 0) - siglongjmp(*next_buf, 1); + if(UML_SIGSETJMP(&my_buf, enable) == 0) + UML_SIGLONGJMP(next_buf, 1); } static sigjmp_buf initial_jmpbuf; @@ -482,48 +495,49 @@ static sigjmp_buf *cb_back; int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) { sigjmp_buf **switch_buf = switch_buf_ptr; - int n; + int n, enable; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, SIGVTALRM, -1); *fork_buf_ptr = &initial_jmpbuf; - n = sigsetjmp(initial_jmpbuf, 1); - switch(n){ - case INIT_JMP_NEW_THREAD: - new_thread_proc((void *) stack, new_thread_handler); - break; - case INIT_JMP_REMOVE_SIGSTACK: - remove_sigstack(); - break; - case INIT_JMP_CALLBACK: + n = UML_SIGSETJMP(&initial_jmpbuf, enable); + switch(n){ + case INIT_JMP_NEW_THREAD: + new_thread_proc((void *) stack, new_thread_handler); + break; + case INIT_JMP_REMOVE_SIGSTACK: + remove_sigstack(); + break; + case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); - siglongjmp(*cb_back, 1); - break; - case INIT_JMP_HALT: + UML_SIGLONGJMP(cb_back, 1); + break; + case INIT_JMP_HALT: kmalloc_ok = 0; return(0); - case INIT_JMP_REBOOT: + case INIT_JMP_REBOOT: kmalloc_ok = 0; return(1); - default: - panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); + default: + panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } - siglongjmp(**switch_buf, 1); + UML_SIGLONGJMP(*switch_buf, 1); } void initial_thread_cb_skas(void (*proc)(void *), void *arg) { sigjmp_buf here; + int enable; cb_proc = proc; cb_arg = arg; cb_back = &here; block_signals(); - if(sigsetjmp(here, 1) == 0) - siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); + if(UML_SIGSETJMP(&here, enable) == 0) + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); cb_proc = NULL; @@ -534,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) void halt_skas(void) { block_signals(); - siglongjmp(initial_jmpbuf, INIT_JMP_HALT); + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT); } void reboot_skas(void) { block_signals(); - siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); } void switch_mm_skas(struct mm_id *mm_idp) @@ -557,14 +571,3 @@ void switch_mm_skas(struct mm_id *mm_idp) } else userspace_pid[0] = mm_idp->u.pid; } - -/* - * 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/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b47e5e71d1a5..829d6b0d8b02 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -29,7 +29,6 @@ #include "irq_user.h" #include "ptrace_user.h" #include "mem_user.h" -#include "time_user.h" #include "init.h" #include "os.h" #include "uml-config.h" @@ -50,6 +49,7 @@ static int ptrace_child(void *arg) int pid = os_getpid(), ppid = getppid(); int sc_result; + change_sig(SIGWINCH, 0); if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ perror("ptrace"); os_kill_process(pid, 0); diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index aee4812333c6..7a6f6b99ceff 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -122,9 +122,12 @@ void init_registers(int pid) err); } -void get_safe_registers(unsigned long *regs) +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) { memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); } void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 4b638dfb52b0..001941fa1a1e 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -70,9 +70,12 @@ void init_registers(int pid) err); } -void get_safe_registers(unsigned long *regs) +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) { memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); + if(fp_regs != NULL) + memcpy(fp_regs, exec_fp_regs, + HOST_FP_SIZE * sizeof(unsigned long)); } void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index cf30a39bc484..6f7626775acb 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -1,21 +1,128 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <time.h> #include <sys/time.h> +#include <signal.h> +#include <errno.h> +#include "user_util.h" +#include "kern_util.h" +#include "user.h" +#include "process.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 <linux/time.h> + */ +extern struct timespec wall_to_monotonic; + +static void set_interval(int timer_type) +{ + int usec = 1000000/hz(); + struct itimerval interval = ((struct itimerval) { { 0, usec }, + { 0, usec } }); + + if(setitimer(timer_type, &interval, NULL) == -1) + panic("setitimer failed - errno = %d\n", errno); +} + +void enable_timer(void) +{ + set_interval(ITIMER_VIRTUAL); +} + +void disable_timer(void) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); + /* If there are signals already queued, after unblocking ignore them */ + set_handler(SIGALRM, SIG_IGN, 0, -1); + set_handler(SIGVTALRM, SIG_IGN, 0, -1); +} + +void switch_timers(int to_real) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, + { 0, 1000000/hz() }}); + int old, new; + + if(to_real){ + old = ITIMER_VIRTUAL; + new = ITIMER_REAL; + } + else { + old = ITIMER_REAL; + new = ITIMER_VIRTUAL; + } + + if((setitimer(old, &disable, NULL) < 0) || + (setitimer(new, &enable, NULL))) + printk("switch_timers - setitimer failed, errno = %d\n", + errno); +} -unsigned long long os_usecs(void) +void uml_idle_timer(void) +{ + if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) + panic("Couldn't unset SIGVTALRM handler"); + + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + set_interval(ITIMER_REAL); +} + +extern void ktime_get_ts(struct timespec *ts); +#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) + +void time_init(void) +{ + struct timespec now; + + if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) + panic("Couldn't set SIGVTALRM handler"); + set_interval(ITIMER_VIRTUAL); + + do_posix_clock_monotonic_gettime(&now); + wall_to_monotonic.tv_sec = -now.tv_sec; + wall_to_monotonic.tv_nsec = -now.tv_nsec; +} + +unsigned long long os_nsecs(void) { struct timeval tv; gettimeofday(&tv, NULL); - return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); + return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); } -/* - * 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: - */ +void idle_sleep(int secs) +{ + struct timespec ts; + + ts.tv_sec = secs; + ts.tv_nsec = 0; + nanosleep(&ts, NULL); +} + +/* XXX This partly duplicates init_irq_signals */ + +void user_time_init(void) +{ + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, + SIGALRM, SIGUSR2, -1); + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, + SIGVTALRM, SIGUSR2, -1); + set_interval(ITIMER_VIRTUAL); +} diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 321e1c8e227d..a9f6b26f9828 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c @@ -10,6 +10,7 @@ #include "user_util.h" #include "os.h" #include "mode.h" +#include "longjmp.h" void usr2_handler(int sig, union uml_pt_regs *regs) { @@ -36,5 +37,5 @@ void do_longjmp(void *b, int val) { sigjmp_buf *buf = b; - siglongjmp(*buf, val); + UML_SIGLONGJMP(buf, val); } diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index cb2648b79d0f..919d19f11537 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c @@ -27,7 +27,6 @@ #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" -#include "time_user.h" #include "init.h" #include "os.h" #include "uml-config.h" @@ -63,6 +62,54 @@ void kill_child_dead(int pid) } while(1); } +void stop(void) +{ + while(1) sleep(1000000); +} + +int wait_for_stop(int pid, int sig, int cont_type, void *relay) +{ + sigset_t *relay_signals = relay; + int status, ret; + + while(1){ + CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); + if((ret < 0) || + !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ + if(ret < 0){ + printk("wait failed, errno = %d\n", + errno); + } + else if(WIFEXITED(status)) + printk("process %d exited with status %d\n", + pid, WEXITSTATUS(status)); + else if(WIFSIGNALED(status)) + printk("process %d exited with signal %d\n", + pid, WTERMSIG(status)); + else if((WSTOPSIG(status) == SIGVTALRM) || + (WSTOPSIG(status) == SIGALRM) || + (WSTOPSIG(status) == SIGIO) || + (WSTOPSIG(status) == SIGPROF) || + (WSTOPSIG(status) == SIGCHLD) || + (WSTOPSIG(status) == SIGWINCH) || + (WSTOPSIG(status) == SIGINT)){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else if((relay_signals != NULL) && + sigismember(relay_signals, WSTOPSIG(status))){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else printk("process %d stopped with signal %d\n", + pid, WSTOPSIG(status)); + panic("wait_for_stop failed to wait for %d to stop " + "with %d\n", pid, sig); + } + return(status); + } +} + /* *------------------------- * only for tt mode (will be deleted in future...) diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index 38d710158c3d..166fb66995df 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c @@ -6,6 +6,7 @@ #include <setjmp.h> #include <string.h> +#include "longjmp.h" unsigned long __do_user_copy(void *to, const void *from, int n, void **fault_addr, void **fault_catcher, @@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n, int n), int *faulted_out) { unsigned long *faddrp = (unsigned long *) fault_addr, ret; + int enable; sigjmp_buf jbuf; *fault_catcher = &jbuf; - if(sigsetjmp(jbuf, 1) == 0){ + if(UML_SIGSETJMP(&jbuf, enable) == 0){ (*op)(to, from, n); ret = 0; *faulted_out = 0; diff --git a/arch/um/kernel/user_util.c b/arch/um/os-Linux/util.c index 4c231161f257..e32065e2fdc8 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/os-Linux/util.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -29,17 +29,14 @@ #include "init.h" #include "ptrace_user.h" #include "uml-config.h" - -void stop(void) -{ - while(1) sleep(1000000); -} +#include "os.h" +#include "longjmp.h" void stack_protections(unsigned long address) { int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - if(mprotect((void *) address, page_size(), prot) < 0) + if(mprotect((void *) address, page_size(), prot) < 0) panic("protecting stack failed, errno = %d", errno); } @@ -59,49 +56,6 @@ void task_protections(unsigned long address) panic("protecting stack failed, errno = %d", errno); } -int wait_for_stop(int pid, int sig, int cont_type, void *relay) -{ - sigset_t *relay_signals = relay; - int status, ret; - - while(1){ - CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); - if((ret < 0) || - !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ - if(ret < 0){ - printk("wait failed, errno = %d\n", - errno); - } - else if(WIFEXITED(status)) - printk("process %d exited with status %d\n", - pid, WEXITSTATUS(status)); - else if(WIFSIGNALED(status)) - printk("process %d exited with signal %d\n", - pid, WTERMSIG(status)); - else if((WSTOPSIG(status) == SIGVTALRM) || - (WSTOPSIG(status) == SIGALRM) || - (WSTOPSIG(status) == SIGIO) || - (WSTOPSIG(status) == SIGPROF) || - (WSTOPSIG(status) == SIGCHLD) || - (WSTOPSIG(status) == SIGWINCH) || - (WSTOPSIG(status) == SIGINT)){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else if((relay_signals != NULL) && - sigismember(relay_signals, WSTOPSIG(status))){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else printk("process %d stopped with signal %d\n", - pid, WSTOPSIG(status)); - panic("wait_for_stop failed to wait for %d to stop " - "with %d\n", pid, sig); - } - return(status); - } -} - int raw(int fd) { struct termios tt; @@ -113,7 +67,7 @@ int raw(int fd) cfmakeraw(&tt); - CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); + CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); if(err < 0) return -errno; @@ -149,7 +103,7 @@ void setup_hostinfo(void) int setjmp_wrapper(void (*proc)(void *, void *), ...) { - va_list args; + va_list args; sigjmp_buf buf; int n; @@ -161,14 +115,3 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) va_end(args); return(n); } - -/* - * 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/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 17746b4c08ff..1fa09a79a10b 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -16,6 +16,7 @@ #include "choose-mode.h" #include "kern.h" #include "mode_kern.h" +#include "os.h" extern int modify_ldt(int func, void *ptr, unsigned long bytecount); @@ -88,6 +89,7 @@ out: #include "skas.h" #include "skas_ptrace.h" #include "asm/mmu_context.h" +#include "proc_mm.h" long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, void **addr, int done) @@ -456,13 +458,14 @@ long init_new_ldt(struct mmu_context_skas * new_mm, int i; long page, err=0; void *addr = NULL; + struct proc_mm_op copy; - memset(&desc, 0, sizeof(desc)); if(!ptrace_ldt) init_MUTEX(&new_mm->ldt.semaphore); if(!from_mm){ + memset(&desc, 0, sizeof(desc)); /* * We have to initialize a clean ldt. */ @@ -494,8 +497,26 @@ long init_new_ldt(struct mmu_context_skas * new_mm, } } new_mm->ldt.entry_count = 0; + + goto out; } - else if (!ptrace_ldt) { + + if(proc_mm){ + /* We have a valid from_mm, so we now have to copy the LDT of + * from_mm to new_mm, because using proc_mm an new mm with + * an empty/default LDT was created in new_mm() + */ + copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, + .u = + { .copy_segments = + from_mm->id.u.mm_fd } } ); + i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); + if(i != sizeof(copy)) + printk("new_mm : /proc/mm copy_segments failed, " + "err = %d\n", -i); + } + + if(!ptrace_ldt) { /* Our local LDT is used to supply the data for * modify_ldt(READLDT), if PTRACE_LDT isn't available, * i.e., we have to use the stub for modify_ldt, which @@ -524,6 +545,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm, up(&from_mm->ldt.semaphore); } + out: return err; } diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c index 12e404c6fa46..b5f9c33e311e 100644 --- a/arch/um/sys-x86_64/ptrace_user.c +++ b/arch/um/sys-x86_64/ptrace_user.c @@ -24,6 +24,13 @@ int ptrace_setregs(long pid, unsigned long *regs) return(0); } +int ptrace_setfpregs(long pid, unsigned long *regs) +{ + if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) + return -errno; + return 0; +} + void ptrace_pokeuser(unsigned long addr, unsigned long data) { panic("ptrace_pokeuser"); diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 5a585bfbb8c2..7bd54a921cf7 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -57,7 +57,7 @@ void foo(void) #endif DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); - DEFINE(HOST_FP_SIZE, 0); + DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); DEFINE(HOST_XFP_SIZE, 0); DEFINE_LONGS(HOST_RBX, RBX); DEFINE_LONGS(HOST_RCX, RCX); diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c index 7f0efaa025c9..3975aa02cef8 100644 --- a/arch/v850/kernel/simcons.c +++ b/arch/v850/kernel/simcons.c @@ -117,6 +117,7 @@ late_initcall(simcons_tty_init); tty driver. */ void simcons_poll_tty (struct tty_struct *tty) { + char buf[32]; /* Not the nicest way to do it but I need it correct first */ int flip = 0, send_break = 0; struct pollfd pfd; pfd.fd = 0; @@ -124,21 +125,15 @@ void simcons_poll_tty (struct tty_struct *tty) if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) { if (pfd.revents & POLLIN) { - int left = TTY_FLIPBUF_SIZE - tty->flip.count; - - if (left > 0) { - unsigned char *buf = tty->flip.char_buf_ptr; - int rd = V850_SIM_SYSCALL (read, 0, buf, left); - - if (rd > 0) { - tty->flip.count += rd; - tty->flip.char_buf_ptr += rd; - memset (tty->flip.flag_buf_ptr, 0, rd); - tty->flip.flag_buf_ptr += rd; - flip = 1; - } else - send_break = 1; - } + /* Real block hardware knows the transfer size before + transfer so the new tty buffering doesn't try to handle + this rather weird simulator specific case well */ + int rd = V850_SIM_SYSCALL (read, 0, buf, 32); + if (rd > 0) { + tty_insert_flip_string(tty, buf, rd); + flip = 1; + } else + send_break = 1; } else if (pfd.revents & POLLERR) send_break = 1; } diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index fcb06a50fdd2..ea31b4c62105 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -2,13 +2,6 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config INIT_DEBUG - bool "Debug __init statements" - depends on DEBUG_KERNEL - help - Fill __init and __initdata at the end of boot. This helps debugging - illegal uses of __init and __initdata after initialization. - config DEBUG_RODATA bool "Write protect kernel read-only data structures" depends on DEBUG_KERNEL diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 5231fe83ea4b..56832929a543 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-git12 -# Mon Jan 16 13:09:08 2006 +# Linux kernel version: 2.6.16-rc1-git2 +# Thu Jan 19 10:05:21 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -310,6 +310,11 @@ CONFIG_IPV6=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -319,11 +324,6 @@ CONFIG_IPV6=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -646,6 +646,7 @@ CONFIG_8139TOO=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -1097,6 +1098,12 @@ CONFIG_USB_MON=y # # +# EDAC - error detection and reporting (RAS) +# +# CONFIG_EDAC is not set +# CONFIG_EDAC_POLL is not set + +# # Firmware Drivers # # CONFIG_EDD is not set @@ -1289,6 +1296,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set # CONFIG_FORCED_INLINING is not set +# CONFIG_UNWIND_INFO is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_INIT_DEBUG=y # CONFIG_DEBUG_RODATA is not set diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 58f5bfb52c63..00dee176c08e 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -672,6 +672,22 @@ ia32_sys_call_table: .quad sys_inotify_add_watch .quad sys_inotify_rm_watch .quad sys_migrate_pages + .quad compat_sys_openat /* 295 */ + .quad sys_mkdirat + .quad sys_mknodat + .quad sys_fchownat + .quad compat_sys_futimesat + .quad sys32_fstatat /* 300 */ + .quad sys_unlinkat + .quad sys_renameat + .quad sys_linkat + .quad sys_symlinkat + .quad sys_readlinkat /* 305 */ + .quad sys_fchmodat + .quad sys_faccessat + .quad sys_ni_syscall /* pselect6 for now */ + .quad sys_ni_syscall /* ppoll for now */ + .quad sys_unshare /* 310 */ ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 .quad ni_syscall diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 54481af5344a..2bc55af95419 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -180,6 +180,28 @@ sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) return ret; } +asmlinkage long +sys32_fstatat(unsigned int dfd, char __user *filename, + struct stat64 __user* statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_stat64(statbuf, &stat); + +out: + return error; +} + /* * Linux/i386 didn't use to be able to handle more than * 4 system call parameters, so these system calls used a memory diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile index 7da9ace890bd..4fe97071f297 100644 --- a/arch/x86_64/kernel/acpi/Makefile +++ b/arch/x86_64/kernel/acpi/Makefile @@ -1,3 +1,8 @@ obj-y := boot.o boot-y := ../../../i386/kernel/acpi/boot.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o + +ifneq ($(CONFIG_ACPI_PROCESSOR),) +obj-y += processor.o +endif + diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c new file mode 100644 index 000000000000..3bdc2baa5bb1 --- /dev/null +++ b/arch/x86_64/kernel/acpi/processor.c @@ -0,0 +1,72 @@ +/* + * arch/x86_64/kernel/acpi/processor.c + * + * Copyright (C) 2005 Intel Corporation + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + * - Added _PDC for platforms with Intel CPUs + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> + +#include <acpi/processor.h> +#include <asm/acpi.h> + +static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + return; +} + +/* Initialize _PDC data based on the CPU vendor */ +void arch_acpi_processor_init_pdc(struct acpi_processor *pr) +{ + unsigned int cpu = pr->id; + struct cpuinfo_x86 *c = cpu_data + cpu; + + pr->pdc = NULL; + if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST)) + init_intel_pdc(pr, c); + + return; +} + +EXPORT_SYMBOL(arch_acpi_processor_init_pdc); diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 5d3c5b07b8db..7a0a3e8d5d72 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -35,8 +35,12 @@ #include <asm/mach_apic.h> #include <asm/nmi.h> #include <asm/idle.h> +#include <asm/proto.h> +#include <asm/timex.h> int apic_verbosity; +int apic_runs_main_timer; +int apic_calibrate_pmtmr __initdata; int disable_apic_timer __initdata; @@ -68,6 +72,26 @@ int get_maxlvt(void) return maxlvt; } +/* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves. + */ +void ack_bad_irq(unsigned int irq) +{ + printk("unexpected IRQ trap at vector %02x\n", irq); + /* + * Currently unexpected vectors happen only on SMP and APIC. + * We _must_ ack these because every local APIC has only N + * irq slots per priority level, and a 'hanging, unacked' IRQ + * holds up an irq slot - in excessive cases (when multiple + * unexpected vectors occur) that might lock up the APIC + * completely. + * But don't ack when the APIC is disabled. -AK + */ + if (!disable_apic) + ack_APIC_irq(); +} + void clear_local_APIC(void) { int maxlvt; @@ -684,7 +708,7 @@ static void setup_APIC_timer(unsigned int clocks) local_irq_save(flags); /* wait for irq slice */ - if (vxtime.hpet_address) { + if (vxtime.hpet_address && hpet_use_timer) { int trigger = hpet_readl(HPET_T0_CMP); while (hpet_readl(HPET_COUNTER) >= trigger) /* do nothing */ ; @@ -702,9 +726,17 @@ static void setup_APIC_timer(unsigned int clocks) c2 |= inb_p(0x40) << 8; } while (c2 - c1 < 300); } - __setup_APIC_LVTT(clocks); - + /* Turn off PIT interrupt if we use APIC timer as main timer. + Only works with the PM timer right now + TBD fix it for HPET too. */ + if (vxtime.mode == VXTIME_PMTMR && + smp_processor_id() == boot_cpu_id && + apic_runs_main_timer == 1 && + !cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) { + stop_timer_interrupt(); + apic_runs_main_timer++; + } local_irq_restore(flags); } @@ -735,14 +767,27 @@ static int __init calibrate_APIC_clock(void) __setup_APIC_LVTT(1000000000); apic_start = apic_read(APIC_TMCCT); - rdtscl(tsc_start); - - do { +#ifdef CONFIG_X86_PM_TIMER + if (apic_calibrate_pmtmr && pmtmr_ioport) { + pmtimer_wait(5000); /* 5ms wait */ apic = apic_read(APIC_TMCCT); - rdtscl(tsc); - } while ((tsc - tsc_start) < TICK_COUNT && (apic - apic_start) < TICK_COUNT); + result = (apic_start - apic) * 1000L / 5; + } else +#endif + { + rdtscl(tsc_start); + + do { + apic = apic_read(APIC_TMCCT); + rdtscl(tsc); + } while ((tsc - tsc_start) < TICK_COUNT && + (apic - apic_start) < TICK_COUNT); + + result = (apic_start - apic) * 1000L * cpu_khz / + (tsc - tsc_start); + } + printk("result %d\n", result); - result = (apic_start - apic) * 1000L * cpu_khz / (tsc - tsc_start); printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", result / 1000 / 1000, result / 1000 % 1000); @@ -872,6 +917,8 @@ void smp_local_timer_interrupt(struct pt_regs *regs) #ifdef CONFIG_SMP update_process_times(user_mode(regs)); #endif + if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id) + main_timer_handler(regs); /* * We take the 'long' return path, and there every subsystem * grabs the appropriate locks (kernel lock/ irq lock). @@ -924,7 +971,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) * multi-chassis. Use available data to take a good guess. * If in doubt, go HPET. */ -__init int oem_force_hpet_timer(void) +__cpuinit int oem_force_hpet_timer(void) { int i, clusters, zeros; unsigned id; @@ -1081,10 +1128,34 @@ static __init int setup_nolapic(char *str) static __init int setup_noapictimer(char *str) { + if (str[0] != ' ' && str[0] != 0) + return -1; disable_apic_timer = 1; return 0; } +static __init int setup_apicmaintimer(char *str) +{ + apic_runs_main_timer = 1; + nohpet = 1; + return 0; +} +__setup("apicmaintimer", setup_apicmaintimer); + +static __init int setup_noapicmaintimer(char *str) +{ + apic_runs_main_timer = -1; + return 0; +} +__setup("noapicmaintimer", setup_noapicmaintimer); + +static __init int setup_apicpmtimer(char *s) +{ + apic_calibrate_pmtmr = 1; + return setup_apicmaintimer(NULL); +} +__setup("apicpmtimer", setup_apicpmtimer); + /* dummy parsing: see setup.c */ __setup("disableapic", setup_disableapic); diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index dbdba56e8faa..b150c87a08c6 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -499,7 +499,9 @@ ENTRY(stub_rt_sigreturn) movq %gs:pda_irqstackptr,%rax cmoveq %rax,%rsp /*todo This needs CFI annotation! */ pushq %rdi # save old stack +#ifndef CONFIG_DEBUG_INFO CFI_ADJUST_CFA_OFFSET 8 +#endif call \func .endm @@ -509,7 +511,9 @@ ENTRY(common_interrupt) /* 0(%rsp): oldrsp-ARGOFFSET */ ret_from_intr: popq %rdi +#ifndef CONFIG_DEBUG_INFO CFI_ADJUST_CFA_OFFSET -8 +#endif cli decl %gs:pda_irqcount #ifdef CONFIG_DEBUG_INFO @@ -922,7 +926,7 @@ KPROBE_ENTRY(debug) .previous .text /* runs on exception stack */ -ENTRY(nmi) +KPROBE_ENTRY(nmi) INTR_FRAME pushq $-1 CFI_ADJUST_CFA_OFFSET 8 @@ -969,6 +973,7 @@ paranoid_schedule: cli jmp paranoid_userspace CFI_ENDPROC + .previous .text KPROBE_ENTRY(int3) INTR_FRAME diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index e8cf44ef8778..4282d72b2a26 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -304,6 +304,14 @@ void __init check_ioapic(void) #endif /* RED-PEN skip them on mptables too? */ return; + case PCI_VENDOR_ID_ATI: + if (apic_runs_main_timer != 0) + break; + printk(KERN_INFO + "ATI board detected. Using APIC/PM timer.\n"); + apic_runs_main_timer = 1; + nohpet = 1; + return; } /* No multi-function device? */ @@ -2027,7 +2035,7 @@ int __init io_apic_get_redir_entries (int ioapic) } -int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low) +int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity) { struct IO_APIC_route_entry entry; unsigned long flags; @@ -2049,8 +2057,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a entry.delivery_mode = INT_DELIVERY_MODE; entry.dest_mode = INT_DEST_MODE; entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); - entry.trigger = edge_level; - entry.polarity = active_high_low; + entry.trigger = triggering; + entry.polarity = polarity; entry.mask = 1; /* Disabled (masked) */ irq = gsi_irq_sharing(irq); @@ -2065,9 +2073,9 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", ioapic, mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, - edge_level, active_high_low); + triggering, polarity); - ioapic_register_intr(irq, entry.vector, edge_level); + ioapic_register_intr(irq, entry.vector, triggering); if (!ioapic && (irq < 16)) disable_8259A_irq(irq); diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 13a2eada6c95..b8b9529fa89e 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -380,7 +380,7 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) */ void __cpuinit mcheck_init(struct cpuinfo_x86 *c) { - static cpumask_t mce_cpus __initdata = CPU_MASK_NONE; + static cpumask_t mce_cpus = CPU_MASK_NONE; mce_cpu_quirks(c); diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 1105250bf02c..dc49bfb6db0a 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -915,7 +915,7 @@ void __init mp_config_acpi_legacy_irqs (void) #define MAX_GSI_NUM 4096 -int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) +int mp_register_gsi(u32 gsi, int triggering, int polarity) { int ioapic = -1; int ioapic_pin = 0; @@ -964,7 +964,7 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit); - if (edge_level) { + if (triggering == ACPI_LEVEL_SENSITIVE) { /* * For PCI devices assign IRQs in order, avoiding gaps * due to unused I/O APIC pins. @@ -986,8 +986,8 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) } io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, - edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1, - active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1); + triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, + polarity == ACPI_ACTIVE_HIGH ? 0 : 1); return gsi; } diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 5fae6f0cd994..8be407a1f62d 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -24,6 +24,7 @@ #include <linux/sysdev.h> #include <linux/nmi.h> #include <linux/sysctl.h> +#include <linux/kprobes.h> #include <asm/smp.h> #include <asm/mtrr.h> @@ -468,7 +469,7 @@ void touch_nmi_watchdog (void) touch_softlockup_watchdog(); } -void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) +void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) { int sum; int touched = 0; @@ -512,14 +513,14 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) } } -static int dummy_nmi_callback(struct pt_regs * regs, int cpu) +static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu) { return 0; } static nmi_callback_t nmi_callback = dummy_nmi_callback; -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) { int cpu = safe_smp_processor_id(); diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index 2f5d8328e2b9..4ed391edd47a 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c @@ -107,6 +107,9 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, goto again; } + /* Let low level make its own zone decisions */ + gfp &= ~(GFP_DMA32|GFP_DMA); + if (dma_ops->alloc_coherent) return dma_ops->alloc_coherent(dev, size, dma_handle, gfp); diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index c37fc7726ba6..dd0718dc178b 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -310,7 +310,7 @@ void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int di for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; - if (!s->dma_length || !s->length) + if (!s->dma_length) break; dma_unmap_single(dev, s->dma_address, s->dma_length, dir); } @@ -364,7 +364,6 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, BUG_ON(i > start && s->offset); if (i == start) { - *sout = *s; sout->dma_address = iommu_bus_base; sout->dma_address += iommu_page*PAGE_SIZE + s->offset; sout->dma_length = s->length; @@ -379,7 +378,7 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, SET_LEAK(iommu_page); addr += PAGE_SIZE; iommu_page++; - } + } } BUG_ON(iommu_page - iommu_start != pages); return 0; @@ -391,7 +390,6 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, { if (!need) { BUG_ON(stopat - start != 1); - *sout = sg[start]; sout->dma_length = sg[start].length; return 0; } @@ -457,9 +455,12 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) error: flush_gart(NULL); gart_unmap_sg(dev, sg, nents, dir); - /* When it was forced try again unforced */ - if (force_iommu) - return dma_map_sg_nonforce(dev, sg, nents, dir); + /* When it was forced or merged try again in a dumb way */ + if (force_iommu || iommu_merge) { + out = dma_map_sg_nonforce(dev, sg, nents, dir); + if (out > 0) + return out; + } if (panic_on_overflow) panic("dma_map_sg: overflow on %lu pages\n", pages); iommu_full(dev, pages << PAGE_SHIFT, dir); @@ -642,9 +643,18 @@ static int __init pci_iommu_init(void) (no_agp && init_k8_gatt(&info) < 0)) { no_iommu = 1; no_iommu_init(); + printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); + if (end_pfn > MAX_DMA32_PFN) { + printk(KERN_ERR "WARNING more than 4GB of memory " + "but IOMMU not compiled in.\n" + KERN_ERR "WARNING 32bit PCI may malfunction.\n" + KERN_ERR "You might want to enable " + "CONFIG_GART_IOMMU\n"); + } return -1; } + printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); aper_size = info.aper_size * 1024 * 1024; iommu_size = check_iommu_size(info.aper_base, aper_size); iommu_pages = iommu_size >> PAGE_SHIFT; @@ -718,7 +728,6 @@ static int __init pci_iommu_init(void) flush_gart(NULL); - printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); dma_ops = &gart_dma_ops; return 0; diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index e41564975195..44adcc2d5e5b 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -88,12 +88,5 @@ void __init no_iommu_init(void) { if (dma_ops) return; - printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); dma_ops = &nommu_dma_ops; - if (end_pfn > MAX_DMA32_PFN) { - printk(KERN_ERR - "WARNING more than 4GB of memory but IOMMU not compiled in.\n" - KERN_ERR "WARNING 32bit PCI may malfunction.\n" - KERN_ERR "You might want to enable CONFIG_GART_IOMMU\n"); - } } diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c index 3569a25ad7fb..990ed67896f2 100644 --- a/arch/x86_64/kernel/pci-swiotlb.c +++ b/arch/x86_64/kernel/pci-swiotlb.c @@ -35,8 +35,8 @@ void pci_swiotlb_init(void) (end_pfn > MAX_DMA32_PFN || force_iommu)) swiotlb = 1; if (swiotlb) { - swiotlb_init(); printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); + swiotlb_init(); dma_ops = &swiotlb_dma_ops; } } diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index feb5f108dd26..5c51d10408a6 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -80,6 +80,31 @@ int pmtimer_mark_offset(void) return lost - 1; } +static unsigned pmtimer_wait_tick(void) +{ + u32 a, b; + for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK; + a == b; + b = inl(pmtmr_ioport) & ACPI_PM_MASK) + ; + return b; +} + +/* note: wait time is rounded up to one tick */ +void pmtimer_wait(unsigned us) +{ + u32 a, b; + a = pmtimer_wait_tick(); + do { + b = inl(pmtmr_ioport); + } while (cyc2us(b - a) < us); +} + +void pmtimer_resume(void) +{ + last_pmtmr_tick = inl(pmtmr_ioport); +} + unsigned int do_gettimeoffset_pm(void) { u32 now, offset, delta = 0; diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 8ded407e4a94..22a05dec81a2 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -516,8 +516,10 @@ out: * This could still be optimized: * - fold all the options into a flag word and test it with a single test. * - could test fs/gs bitsliced + * + * Kprobes not supported here. Set the probe on schedule instead. */ -struct task_struct * +__kprobes struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 28895c03cb11..9435ab7d6fb8 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -94,7 +94,6 @@ unsigned long saved_video_mode; /* * Setup options */ -struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info; struct sys_desc_table_struct { unsigned short length; @@ -572,7 +571,6 @@ void __init setup_arch(char **cmdline_p) unsigned long kernel_end; ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); - drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; edid_info = EDID_INFO; saved_video_mode = SAVED_VIDEO_MODE; @@ -741,7 +739,7 @@ void __init setup_arch(char **cmdline_p) e820_setup_gap(); #ifdef CONFIG_GART_IOMMU - iommu_hole_init(); + iommu_hole_init(); #endif #ifdef CONFIG_VT @@ -877,6 +875,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) static int __init init_amd(struct cpuinfo_x86 *c) { int r; + unsigned level; #ifdef CONFIG_SMP unsigned long value; @@ -899,6 +898,11 @@ static int __init init_amd(struct cpuinfo_x86 *c) 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); + /* On C+ stepping K8 rep microcode works well for copy/memset */ + level = cpuid_eax(1); + if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)) + set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability); + r = get_model_name(c); if (!r) { switch (c->x86) { diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 8ac4db09610a..70f1bb808a20 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -146,7 +146,7 @@ void pda_init(int cpu) pda->irqstackptr += IRQSTACKSIZE-64; } -char boot_exception_stacks[(N_EXCEPTION_STACKS - 2) * EXCEPTION_STKSZ + DEBUG_STKSZ] +char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ] __attribute__((section(".bss.page_aligned"))); /* May not be marked __init: used by software suspend */ diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index a28756ef7cef..67e4e28f4df8 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -59,6 +59,7 @@ #include <asm/nmi.h> #include <asm/irq.h> #include <asm/hw_irq.h> +#include <asm/numa.h> /* Number of siblings per CPU package */ int smp_num_siblings = 1; @@ -890,6 +891,7 @@ do_rest: if (boot_error) { cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */ + clear_node_cpumask(cpu); /* was set by numa_add_cpu */ cpu_clear(cpu, cpu_present_map); cpu_clear(cpu, cpu_possible_map); x86_cpu_to_apicid[cpu] = BAD_APICID; @@ -1187,6 +1189,7 @@ void remove_cpu_from_maps(void) cpu_clear(cpu, cpu_callout_map); cpu_clear(cpu, cpu_callin_map); clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */ + clear_node_cpumask(cpu); } int __cpu_disable(void) diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index f8c47c688443..3c58c30506a1 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -51,7 +51,7 @@ extern int using_apic_timer; DEFINE_SPINLOCK(rtc_lock); DEFINE_SPINLOCK(i8253_lock); -static int nohpet __initdata = 0; +int nohpet __initdata = 0; static int notsc __initdata = 0; #undef HPET_HACK_ENABLE_DANGEROUS @@ -59,7 +59,7 @@ static int notsc __initdata = 0; unsigned int cpu_khz; /* TSC clocks / usec, not used here */ static unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* HPET clocks / interrupt */ -static int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */ +int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */ unsigned long vxtime_hz = PIT_TICK_RATE; int report_lost_ticks; /* command line option */ unsigned long long monotonic_base; @@ -326,7 +326,10 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs) print_symbol("rip %s\n", regs->rip); if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) { printk(KERN_WARNING "Falling back to HPET\n"); - vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + if (hpet_use_timer) + vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + else + vxtime.last = hpet_readl(HPET_COUNTER); vxtime.mode = VXTIME_HPET; do_gettimeoffset = do_gettimeoffset_hpet; } @@ -345,7 +348,7 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs) #endif } -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +void main_timer_handler(struct pt_regs *regs) { static unsigned long rtc_update = 0; unsigned long tsc; @@ -458,12 +461,17 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) } write_sequnlock(&xtime_lock); +} +static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (apic_runs_main_timer > 1) + return IRQ_HANDLED; + main_timer_handler(regs); #ifdef CONFIG_X86_LOCAL_APIC if (using_apic_timer) smp_send_timer_broadcast_ipi(); #endif - return IRQ_HANDLED; } @@ -743,7 +751,7 @@ static __init int late_hpet_init(void) * Timer0 and Timer1 is used by platform. */ hd.hd_phys_address = vxtime.hpet_address; - hd.hd_address = (void *)fix_to_virt(FIX_HPET_BASE); + hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE); hd.hd_nirqs = ntimer; hd.hd_flags = HPET_DATA_PLATFORM; hpet_reserve_timer(&hd, 0); @@ -843,17 +851,43 @@ static int hpet_reenable(void) return hpet_timer_stop_set_go(hpet_tick); } -void __init pit_init(void) +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 + +static void __init __pit_init(int val, u8 mode) { unsigned long flags; spin_lock_irqsave(&i8253_lock, flags); - outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb_p(LATCH & 0xff, 0x40); /* LSB */ - outb_p(LATCH >> 8, 0x40); /* MSB */ + outb_p(mode, PIT_MODE); + outb_p(val & 0xff, PIT_CH0); /* LSB */ + outb_p(val >> 8, PIT_CH0); /* MSB */ spin_unlock_irqrestore(&i8253_lock, flags); } +void __init pit_init(void) +{ + __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ +} + +void __init pit_stop_interrupt(void) +{ + __pit_init(0, 0x30); /* mode 0 */ +} + +void __init stop_timer_interrupt(void) +{ + char *name; + if (vxtime.hpet_address) { + name = "HPET"; + hpet_timer_stop_set_go(0); + } else { + name = "PIT"; + pit_stop_interrupt(); + } + printk(KERN_INFO "timer: %s interrupt stopped.\n", name); +} + int __init time_setup(char *str) { report_lost_ticks = 1; @@ -932,7 +966,7 @@ void __init time_init(void) * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs. */ -__init int unsynchronized_tsc(void) +__cpuinit int unsynchronized_tsc(void) { #ifdef CONFIG_SMP if (oem_force_hpet_timer()) @@ -957,7 +991,10 @@ void __init time_init_gtod(void) notsc = 1; if (vxtime.hpet_address && notsc) { timetype = hpet_use_timer ? "HPET" : "PIT/HPET"; - vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + if (hpet_use_timer) + vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + else + vxtime.last = hpet_readl(HPET_COUNTER); vxtime.mode = VXTIME_HPET; do_gettimeoffset = do_gettimeoffset_hpet; #ifdef CONFIG_X86_PM_TIMER @@ -1016,9 +1053,21 @@ static int timer_resume(struct sys_device *dev) write_seqlock_irqsave(&xtime_lock,flags); xtime.tv_sec = sec; xtime.tv_nsec = 0; + if (vxtime.mode == VXTIME_HPET) { + if (hpet_use_timer) + vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + else + vxtime.last = hpet_readl(HPET_COUNTER); +#ifdef CONFIG_X86_PM_TIMER + } else if (vxtime.mode == VXTIME_PMTMR) { + pmtimer_resume(); +#endif + } else + vxtime.last_tsc = get_cycles_sync(); write_sequnlock_irqrestore(&xtime_lock,flags); jiffies += sleep_length; wall_jiffies += sleep_length; + monotonic_base += sleep_length * (NSEC_PER_SEC/HZ); touch_softlockup_watchdog(); return 0; } diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 8bb0aeda78b9..28d50dc540e8 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -90,6 +90,20 @@ static inline void conditional_sti(struct pt_regs *regs) local_irq_enable(); } +static inline void preempt_conditional_sti(struct pt_regs *regs) +{ + preempt_disable(); + if (regs->eflags & X86_EFLAGS_IF) + local_irq_enable(); +} + +static inline void preempt_conditional_cli(struct pt_regs *regs) +{ + if (regs->eflags & X86_EFLAGS_IF) + local_irq_disable(); + preempt_enable_no_resched(); +} + static int kstack_depth_to_print = 10; #ifdef CONFIG_KALLSYMS @@ -372,7 +386,7 @@ void out_of_line_bug(void) static DEFINE_SPINLOCK(die_lock); static int die_owner = -1; -unsigned long oops_begin(void) +unsigned __kprobes long oops_begin(void) { int cpu = safe_smp_processor_id(); unsigned long flags; @@ -391,7 +405,7 @@ unsigned long oops_begin(void) return flags; } -void oops_end(unsigned long flags) +void __kprobes oops_end(unsigned long flags) { die_owner = -1; bust_spinlocks(0); @@ -400,7 +414,7 @@ void oops_end(unsigned long flags) panic("Oops"); } -void __die(const char * str, struct pt_regs * regs, long err) +void __kprobes __die(const char * str, struct pt_regs * regs, long err) { static int die_counter; printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); @@ -432,7 +446,7 @@ void die(const char * str, struct pt_regs * regs, long err) do_exit(SIGSEGV); } -void die_nmi(char *str, struct pt_regs *regs) +void __kprobes die_nmi(char *str, struct pt_regs *regs) { unsigned long flags = oops_begin(); @@ -575,7 +589,8 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, } } -static void mem_parity_error(unsigned char reason, struct pt_regs * regs) +static __kprobes void +mem_parity_error(unsigned char reason, struct pt_regs * regs) { printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); printk("You probably have a hardware problem with your RAM chips\n"); @@ -585,7 +600,8 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) outb(reason, 0x61); } -static void io_check_error(unsigned char reason, struct pt_regs * regs) +static __kprobes void +io_check_error(unsigned char reason, struct pt_regs * regs) { printk("NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); @@ -598,7 +614,8 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) outb(reason, 0x61); } -static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) +static __kprobes void +unknown_nmi_error(unsigned char reason, struct pt_regs * regs) { printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); @@ -606,7 +623,7 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) /* Runs on IST stack. This code must keep interrupts off all the time. Nested NMIs are prevented by the CPU. */ -asmlinkage void default_do_nmi(struct pt_regs *regs) +asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs) { unsigned char reason = 0; int cpu; @@ -658,7 +675,7 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) /* Help handler running on IST stack to switch back to user stack for scheduling or signal handling. The actual stack switch is done in entry.S */ -asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs) +asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) { struct pt_regs *regs = eregs; /* Did already sync */ @@ -690,7 +707,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, SIGTRAP) == NOTIFY_STOP) return; - conditional_sti(regs); + preempt_conditional_sti(regs); /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { @@ -735,11 +752,13 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, clear_dr7: set_debugreg(0UL, 7); + preempt_conditional_cli(regs); return; clear_TF_reenable: set_tsk_thread_flag(tsk, TIF_SINGLESTEP); regs->eflags &= ~TF_MASK; + preempt_conditional_cli(regs); } static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index b0eed1faf740..74db0062d4a2 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -172,13 +172,15 @@ SECTIONS . = ALIGN(4096); __initramfs_start = .; .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) } - __initramfs_end = .; - . = ALIGN(32); + __initramfs_end = .; + /* temporary here to work around NR_CPUS. If you see this comment in 2.6.17+ + complain */ + . = ALIGN(4096); + __init_end = .; + . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); __per_cpu_start = .; .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } __per_cpu_end = .; - . = ALIGN(4096); - __init_end = .; . = ALIGN(4096); __nosave_begin = .; diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index b614d54d2ae4..3496abc8d372 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -39,11 +39,6 @@ extern void __write_lock_failed(rwlock_t *rw); extern void __read_lock_failed(rwlock_t *rw); #endif -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) -extern struct drive_info_struct drive_info; -EXPORT_SYMBOL(drive_info); -#endif - /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); //EXPORT_SYMBOL(dump_fpu); diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile index bba5db6cebd6..ccef6ae747a3 100644 --- a/arch/x86_64/lib/Makefile +++ b/arch/x86_64/lib/Makefile @@ -4,7 +4,7 @@ CFLAGS_csum-partial.o := -funroll-loops -obj-y := io.o +obj-y := io.o iomap_copy.o lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \ usercopy.o getuser.o putuser.o \ diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S index 43d9fa136180..1f81b79b796c 100644 --- a/arch/x86_64/lib/clear_page.S +++ b/arch/x86_64/lib/clear_page.S @@ -5,8 +5,46 @@ .globl clear_page .p2align 4 clear_page: + xorl %eax,%eax + movl $4096/64,%ecx + .p2align 4 +.Lloop: + decl %ecx +#define PUT(x) movq %rax,x*8(%rdi) + movq %rax,(%rdi) + PUT(1) + PUT(2) + PUT(3) + PUT(4) + PUT(5) + PUT(6) + PUT(7) + leaq 64(%rdi),%rdi + jnz .Lloop + nop + ret +clear_page_end: + + /* Some CPUs run faster using the string instructions. + It is also a lot simpler. Use this when possible */ + +#include <asm/cpufeature.h> + + .section .altinstructions,"a" + .align 8 + .quad clear_page + .quad clear_page_c + .byte X86_FEATURE_REP_GOOD + .byte clear_page_end-clear_page + .byte clear_page_c_end-clear_page_c + .previous + + .section .altinstr_replacement,"ax" +clear_page_c: movl $4096/8,%ecx xorl %eax,%eax rep stosq ret +clear_page_c_end: + .previous diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S index 621a19769406..8fa19d96a7ee 100644 --- a/arch/x86_64/lib/copy_page.S +++ b/arch/x86_64/lib/copy_page.S @@ -8,7 +8,94 @@ .globl copy_page .p2align 4 copy_page: + subq $3*8,%rsp + movq %rbx,(%rsp) + movq %r12,1*8(%rsp) + movq %r13,2*8(%rsp) + + movl $(4096/64)-5,%ecx + .p2align 4 +.Loop64: + dec %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %rdx + movq 24 (%rsi), %r8 + movq 32 (%rsi), %r9 + movq 40 (%rsi), %r10 + movq 48 (%rsi), %r11 + movq 56 (%rsi), %r12 + + prefetcht0 5*64(%rsi) + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %rdx, 16 (%rdi) + movq %r8, 24 (%rdi) + movq %r9, 32 (%rdi) + movq %r10, 40 (%rdi) + movq %r11, 48 (%rdi) + movq %r12, 56 (%rdi) + + leaq 64 (%rsi), %rsi + leaq 64 (%rdi), %rdi + + jnz .Loop64 + + movl $5,%ecx + .p2align 4 +.Loop2: + decl %ecx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %rdx + movq 24 (%rsi), %r8 + movq 32 (%rsi), %r9 + movq 40 (%rsi), %r10 + movq 48 (%rsi), %r11 + movq 56 (%rsi), %r12 + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %rdx, 16 (%rdi) + movq %r8, 24 (%rdi) + movq %r9, 32 (%rdi) + movq %r10, 40 (%rdi) + movq %r11, 48 (%rdi) + movq %r12, 56 (%rdi) + + leaq 64(%rdi),%rdi + leaq 64(%rsi),%rsi + + jnz .Loop2 + + movq (%rsp),%rbx + movq 1*8(%rsp),%r12 + movq 2*8(%rsp),%r13 + addq $3*8,%rsp + ret + + /* Some CPUs run faster using the string copy instructions. + It is also a lot simpler. Use this when possible */ + +#include <asm/cpufeature.h> + + .section .altinstructions,"a" + .align 8 + .quad copy_page + .quad copy_page_c + .byte X86_FEATURE_REP_GOOD + .byte copy_page_c_end-copy_page_c + .byte copy_page_c_end-copy_page_c + .previous + + .section .altinstr_replacement,"ax" +copy_page_c: movl $4096/8,%ecx rep movsq ret +copy_page_c_end: + .previous diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S index 79422b6559c3..f64569b83b54 100644 --- a/arch/x86_64/lib/copy_user.S +++ b/arch/x86_64/lib/copy_user.S @@ -4,9 +4,12 @@ * Functions to copy from and to user space. */ +#define FIX_ALIGNMENT 1 + #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> + #include <asm/cpufeature.h> /* Standard copy_to_user with segment limit checking */ .globl copy_to_user @@ -18,7 +21,23 @@ copy_to_user: jc bad_to_user cmpq threadinfo_addr_limit(%rax),%rcx jae bad_to_user - jmp copy_user_generic +2: + .byte 0xe9 /* 32bit jump */ + .long .Lcug-1f +1: + + .section .altinstr_replacement,"ax" +3: .byte 0xe9 /* replacement jmp with 8 bit immediate */ + .long copy_user_generic_c-1b /* offset */ + .previous + .section .altinstructions,"a" + .align 8 + .quad 2b + .quad 3b + .byte X86_FEATURE_REP_GOOD + .byte 5 + .byte 5 + .previous /* Standard copy_from_user with segment limit checking */ .globl copy_from_user @@ -53,44 +72,230 @@ bad_to_user: * rsi source * rdx count * - * Only 4GB of copy is supported. This shouldn't be a problem - * because the kernel normally only writes from/to page sized chunks - * even if user space passed a longer buffer. - * And more would be dangerous because both Intel and AMD have - * errata with rep movsq > 4GB. If someone feels the need to fix - * this please consider this. - * * Output: * eax uncopied bytes or 0 if successful. */ - .globl copy_user_generic + .p2align 4 copy_user_generic: + .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */ + .byte 0x66,0x90 +1: + .section .altinstr_replacement,"ax" +2: .byte 0xe9 /* near jump with 32bit immediate */ + .long copy_user_generic_c-1b /* offset */ + .previous + .section .altinstructions,"a" + .align 8 + .quad copy_user_generic + .quad 2b + .byte X86_FEATURE_REP_GOOD + .byte 5 + .byte 5 + .previous +.Lcug: + pushq %rbx + xorl %eax,%eax /*zero for the exception handler */ + +#ifdef FIX_ALIGNMENT + /* check for bad alignment of destination */ + movl %edi,%ecx + andl $7,%ecx + jnz .Lbad_alignment +.Lafter_bad_alignment: +#endif + + movq %rdx,%rcx + + movl $64,%ebx + shrq $6,%rdx + decq %rdx + js .Lhandle_tail + + .p2align 4 +.Lloop: +.Ls1: movq (%rsi),%r11 +.Ls2: movq 1*8(%rsi),%r8 +.Ls3: movq 2*8(%rsi),%r9 +.Ls4: movq 3*8(%rsi),%r10 +.Ld1: movq %r11,(%rdi) +.Ld2: movq %r8,1*8(%rdi) +.Ld3: movq %r9,2*8(%rdi) +.Ld4: movq %r10,3*8(%rdi) + +.Ls5: movq 4*8(%rsi),%r11 +.Ls6: movq 5*8(%rsi),%r8 +.Ls7: movq 6*8(%rsi),%r9 +.Ls8: movq 7*8(%rsi),%r10 +.Ld5: movq %r11,4*8(%rdi) +.Ld6: movq %r8,5*8(%rdi) +.Ld7: movq %r9,6*8(%rdi) +.Ld8: movq %r10,7*8(%rdi) + + decq %rdx + + leaq 64(%rsi),%rsi + leaq 64(%rdi),%rdi + + jns .Lloop + + .p2align 4 +.Lhandle_tail: + movl %ecx,%edx + andl $63,%ecx + shrl $3,%ecx + jz .Lhandle_7 + movl $8,%ebx + .p2align 4 +.Lloop_8: +.Ls9: movq (%rsi),%r8 +.Ld9: movq %r8,(%rdi) + decl %ecx + leaq 8(%rdi),%rdi + leaq 8(%rsi),%rsi + jnz .Lloop_8 + +.Lhandle_7: + movl %edx,%ecx + andl $7,%ecx + jz .Lende + .p2align 4 +.Lloop_1: +.Ls10: movb (%rsi),%bl +.Ld10: movb %bl,(%rdi) + incq %rdi + incq %rsi + decl %ecx + jnz .Lloop_1 + +.Lende: + popq %rbx + ret + +#ifdef FIX_ALIGNMENT + /* align destination */ + .p2align 4 +.Lbad_alignment: + movl $8,%r9d + subl %ecx,%r9d + movl %r9d,%ecx + cmpq %r9,%rdx + jz .Lhandle_7 + js .Lhandle_7 +.Lalign_1: +.Ls11: movb (%rsi),%bl +.Ld11: movb %bl,(%rdi) + incq %rsi + incq %rdi + decl %ecx + jnz .Lalign_1 + subq %r9,%rdx + jmp .Lafter_bad_alignment +#endif + + /* table sorted by exception address */ + .section __ex_table,"a" + .align 8 + .quad .Ls1,.Ls1e + .quad .Ls2,.Ls2e + .quad .Ls3,.Ls3e + .quad .Ls4,.Ls4e + .quad .Ld1,.Ls1e + .quad .Ld2,.Ls2e + .quad .Ld3,.Ls3e + .quad .Ld4,.Ls4e + .quad .Ls5,.Ls5e + .quad .Ls6,.Ls6e + .quad .Ls7,.Ls7e + .quad .Ls8,.Ls8e + .quad .Ld5,.Ls5e + .quad .Ld6,.Ls6e + .quad .Ld7,.Ls7e + .quad .Ld8,.Ls8e + .quad .Ls9,.Le_quad + .quad .Ld9,.Le_quad + .quad .Ls10,.Le_byte + .quad .Ld10,.Le_byte +#ifdef FIX_ALIGNMENT + .quad .Ls11,.Lzero_rest + .quad .Ld11,.Lzero_rest +#endif + .quad .Le5,.Le_zero + .previous + + /* compute 64-offset for main loop. 8 bytes accuracy with error on the + pessimistic side. this is gross. it would be better to fix the + interface. */ + /* eax: zero, ebx: 64 */ +.Ls1e: addl $8,%eax +.Ls2e: addl $8,%eax +.Ls3e: addl $8,%eax +.Ls4e: addl $8,%eax +.Ls5e: addl $8,%eax +.Ls6e: addl $8,%eax +.Ls7e: addl $8,%eax +.Ls8e: addl $8,%eax + addq %rbx,%rdi /* +64 */ + subq %rax,%rdi /* correct destination with computed offset */ + + shlq $6,%rdx /* loop counter * 64 (stride length) */ + addq %rax,%rdx /* add offset to loopcnt */ + andl $63,%ecx /* remaining bytes */ + addq %rcx,%rdx /* add them */ + jmp .Lzero_rest + + /* exception on quad word loop in tail handling */ + /* ecx: loopcnt/8, %edx: length, rdi: correct */ +.Le_quad: + shll $3,%ecx + andl $7,%edx + addl %ecx,%edx + /* edx: bytes to zero, rdi: dest, eax:zero */ +.Lzero_rest: + movq %rdx,%rcx +.Le_byte: + xorl %eax,%eax +.Le5: rep + stosb + /* when there is another exception while zeroing the rest just return */ +.Le_zero: + movq %rdx,%rax + jmp .Lende + + /* Some CPUs run faster using the string copy instructions. + This is also a lot simpler. Use them when possible. + Patch in jmps to this code instead of copying it fully + to avoid unwanted aliasing in the exception tables. */ + + /* rdi destination + * rsi source + * rdx count + * + * Output: + * eax uncopied bytes or 0 if successfull. + * + * Only 4GB of copy is supported. This shouldn't be a problem + * because the kernel normally only writes from/to page sized chunks + * even if user space passed a longer buffer. + * And more would be dangerous because both Intel and AMD have + * errata with rep movsq > 4GB. If someone feels the need to fix + * this please consider this. + */ +copy_user_generic_c: movl %edx,%ecx shrl $3,%ecx andl $7,%edx - jz 5f 1: rep movsq movl %edx,%ecx - xor %eax,%eax 2: rep movsb +4: movl %ecx,%eax ret - /* align here? */ -5: xorl %eax,%eax -6: rep movsq - ret - - .section .fixup,"ax" 3: lea (%rdx,%rcx,8),%rax ret -4: movl %ecx,%eax - ret - .previous .section __ex_table,"a" .quad 1b,3b .quad 2b,4b - .quad 6b,4b .previous diff --git a/arch/x86_64/lib/iomap_copy.S b/arch/x86_64/lib/iomap_copy.S new file mode 100644 index 000000000000..8bbade5fea05 --- /dev/null +++ b/arch/x86_64/lib/iomap_copy.S @@ -0,0 +1,26 @@ +/* + * Copyright 2006 PathScale, Inc. All Rights Reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * override generic version in lib/iomap_copy.c + */ + .globl __iowrite32_copy + .p2align 4 +__iowrite32_copy: + movl %edx,%ecx + rep movsd + ret diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S index 92dd80544602..5554948b5554 100644 --- a/arch/x86_64/lib/memcpy.S +++ b/arch/x86_64/lib/memcpy.S @@ -11,8 +11,6 @@ * * Output: * rax original destination - * - * TODO: check best memcpy for PSC */ .globl __memcpy @@ -20,6 +18,95 @@ .p2align 4 __memcpy: memcpy: + pushq %rbx + movq %rdi,%rax + + movl %edx,%ecx + shrl $6,%ecx + jz .Lhandle_tail + + .p2align 4 +.Lloop_64: + decl %ecx + + movq (%rsi),%r11 + movq 8(%rsi),%r8 + + movq %r11,(%rdi) + movq %r8,1*8(%rdi) + + movq 2*8(%rsi),%r9 + movq 3*8(%rsi),%r10 + + movq %r9,2*8(%rdi) + movq %r10,3*8(%rdi) + + movq 4*8(%rsi),%r11 + movq 5*8(%rsi),%r8 + + movq %r11,4*8(%rdi) + movq %r8,5*8(%rdi) + + movq 6*8(%rsi),%r9 + movq 7*8(%rsi),%r10 + + movq %r9,6*8(%rdi) + movq %r10,7*8(%rdi) + + leaq 64(%rsi),%rsi + leaq 64(%rdi),%rdi + jnz .Lloop_64 + +.Lhandle_tail: + movl %edx,%ecx + andl $63,%ecx + shrl $3,%ecx + jz .Lhandle_7 + .p2align 4 +.Lloop_8: + decl %ecx + movq (%rsi),%r8 + movq %r8,(%rdi) + leaq 8(%rdi),%rdi + leaq 8(%rsi),%rsi + jnz .Lloop_8 + +.Lhandle_7: + movl %edx,%ecx + andl $7,%ecx + jz .Lende + .p2align 4 +.Lloop_1: + movb (%rsi),%r8b + movb %r8b,(%rdi) + incq %rdi + incq %rsi + decl %ecx + jnz .Lloop_1 + +.Lende: + popq %rbx + ret +.Lfinal: + + /* Some CPUs run faster using the string copy instructions. + It is also a lot simpler. Use this when possible */ + + .section .altinstructions,"a" + .align 8 + .quad memcpy + .quad memcpy_c + .byte X86_FEATURE_REP_GOOD + .byte .Lfinal-memcpy + .byte memcpy_c_end-memcpy_c + .previous + + .section .altinstr_replacement,"ax" + /* rdi destination + * rsi source + * rdx count + */ +memcpy_c: movq %rdi,%rax movl %edx,%ecx shrl $3,%ecx @@ -30,3 +117,5 @@ memcpy: rep movsb ret +memcpy_c_end: + .previous diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S index 2aa48f24ed1e..ad397f2c7de8 100644 --- a/arch/x86_64/lib/memset.S +++ b/arch/x86_64/lib/memset.S @@ -13,6 +13,98 @@ .p2align 4 memset: __memset: + movq %rdi,%r10 + movq %rdx,%r11 + + /* expand byte value */ + movzbl %sil,%ecx + movabs $0x0101010101010101,%rax + mul %rcx /* with rax, clobbers rdx */ + + /* align dst */ + movl %edi,%r9d + andl $7,%r9d + jnz .Lbad_alignment +.Lafter_bad_alignment: + + movl %r11d,%ecx + shrl $6,%ecx + jz .Lhandle_tail + + .p2align 4 +.Lloop_64: + decl %ecx + movq %rax,(%rdi) + movq %rax,8(%rdi) + movq %rax,16(%rdi) + movq %rax,24(%rdi) + movq %rax,32(%rdi) + movq %rax,40(%rdi) + movq %rax,48(%rdi) + movq %rax,56(%rdi) + leaq 64(%rdi),%rdi + jnz .Lloop_64 + + /* Handle tail in loops. The loops should be faster than hard + to predict jump tables. */ + .p2align 4 +.Lhandle_tail: + movl %r11d,%ecx + andl $63&(~7),%ecx + jz .Lhandle_7 + shrl $3,%ecx + .p2align 4 +.Lloop_8: + decl %ecx + movq %rax,(%rdi) + leaq 8(%rdi),%rdi + jnz .Lloop_8 + +.Lhandle_7: + movl %r11d,%ecx + andl $7,%ecx + jz .Lende + .p2align 4 +.Lloop_1: + decl %ecx + movb %al,(%rdi) + leaq 1(%rdi),%rdi + jnz .Lloop_1 + +.Lende: + movq %r10,%rax + ret + +.Lbad_alignment: + cmpq $7,%r11 + jbe .Lhandle_7 + movq %rax,(%rdi) /* unaligned store */ + movq $8,%r8 + subq %r9,%r8 + addq %r8,%rdi + subq %r8,%r11 + jmp .Lafter_bad_alignment + + /* Some CPUs run faster using the string instructions. + It is also a lot simpler. Use this when possible */ + +#include <asm/cpufeature.h> + + .section .altinstructions,"a" + .align 8 + .quad memset + .quad memset_c + .byte X86_FEATURE_REP_GOOD + .byte memset_c_end-memset_c + .byte memset_c_end-memset_c + .previous + + .section .altinstr_replacement,"ax" + /* rdi destination + * rsi value + * rdx count + */ +memset_c: movq %rdi,%r9 movl %edx,%r8d andl $7,%r8d @@ -29,3 +121,5 @@ __memset: stosb movq %r9,%rax ret +memset_c_end: + .previous diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 26eac194064b..2e7c3c8ffe03 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -33,7 +33,6 @@ #include <asm/proto.h> #include <asm/kdebug.h> #include <asm-generic/sections.h> -#include <asm/kdebug.h> /* Page fault error code bits */ #define PF_PROT (1<<0) /* or no page found */ @@ -157,8 +156,8 @@ void dump_pagetable(unsigned long address) pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); pgd += pgd_index(address); - printk("PGD %lx ", pgd_val(*pgd)); if (bad_address(pgd)) goto bad; + printk("PGD %lx ", pgd_val(*pgd)); if (!pgd_present(*pgd)) goto ret; pud = __pud_offset_k((pud_t *)pgd_page(*pgd), address); diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 8b7f85608fa8..cd25300726fc 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -26,6 +26,10 @@ static nodemask_t nodes_found __initdata; static struct node nodes[MAX_NUMNODES] __initdata; static u8 pxm2node[256] = { [0 ... 255] = 0xff }; +/* Too small nodes confuse the VM badly. Usually they result + from BIOS bugs. */ +#define NODE_MIN_SIZE (4*1024*1024) + static int node_to_pxm(int n); int pxm_to_node(int pxm) @@ -131,7 +135,12 @@ void __init acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) { int pxm, node; - if (srat_disabled() || pa->flags.enabled == 0) + if (srat_disabled()) + return; + if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { bad_srat(); + return; + } + if (pa->flags.enabled == 0) return; pxm = pa->proximity_domain; node = setup_node(pxm); @@ -155,8 +164,16 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) int node, pxm; int i; - if (srat_disabled() || ma->flags.enabled == 0) + if (srat_disabled()) + return; + if (ma->header.length != sizeof(struct acpi_table_memory_affinity)) { + bad_srat(); return; + } + if (ma->flags.enabled == 0) + return; + start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); + end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); pxm = ma->proximity_domain; node = setup_node(pxm); if (node < 0) { @@ -164,8 +181,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) bad_srat(); return; } - start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); - end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); /* It is fine to add this area to the nodes data it will be used later*/ if (ma->flags.hot_pluggable == 1) printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n", @@ -223,6 +238,16 @@ static int nodes_cover_memory(void) return 1; } +static void unparse_node(int node) +{ + int i; + node_clear(node, nodes_parsed); + for (i = 0; i < MAX_LOCAL_APIC; i++) { + if (apicid_to_node[i] == node) + apicid_to_node[i] = NUMA_NO_NODE; + } +} + void __init acpi_numa_arch_fixup(void) {} /* Use the information discovered above to actually set up the nodes. */ @@ -230,16 +255,16 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) { int i; - if (acpi_numa <= 0) - return -1; - /* First clean up the node list */ - for_each_node_mask(i, nodes_parsed) { + for (i = 0; i < MAX_NUMNODES; i++) { cutoff_node(i, start, end); - if (nodes[i].start == nodes[i].end) - node_clear(i, nodes_parsed); + if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) + unparse_node(i); } + if (acpi_numa <= 0) + return -1; + if (!nodes_cover_memory()) { bad_srat(); return -1; diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index f16c0d57c552..18f371fe37f8 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -29,11 +29,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) while (1) { ++cfg_num; - if (cfg_num >= pci_mmcfg_config_num) { - /* Not found - fall back to type 1. This happens - e.g. on the internal devices of a K8 northbridge. */ - return NULL; - } + if (cfg_num >= pci_mmcfg_config_num) + break; cfg = pci_mmcfg_virt[cfg_num].cfg; if (cfg->pci_segment_group_number != seg) continue; @@ -41,6 +38,18 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) (cfg->end_bus_number >= bus)) return pci_mmcfg_virt[cfg_num].virt; } + + /* Handle more broken MCFG tables on Asus etc. + They only contain a single entry for bus 0-0. Assume + this applies to all busses. */ + cfg = &pci_mmcfg_config[0]; + if (pci_mmcfg_config_num == 1 && + cfg->pci_segment_group_number == 0 && + (cfg->start_bus_number | cfg->end_bus_number) == 0) + return pci_mmcfg_virt[0].virt; + + /* Fall back to type 0 */ + return NULL; } static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c index 4fbddf92a921..94fdfe474ac1 100644 --- a/arch/xtensa/platform-iss/console.c +++ b/arch/xtensa/platform-iss/console.c @@ -128,9 +128,7 @@ static void rs_poll(unsigned long priv) while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){ __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0); - tty->flip.count++; - *tty->flip.char_buf_ptr++ = c; - *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + tty_insert_flip_char(tty, c, TTY_NORMAL); i++; } diff --git a/block/elevator.c b/block/elevator.c index c9f424d5399c..24b702d649a9 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -139,35 +139,16 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e, static char chosen_elevator[16]; -static void elevator_setup_default(void) +static int __init elevator_setup(char *str) { - struct elevator_type *e; - - /* - * If default has not been set, use the compiled-in selection. - */ - if (!chosen_elevator[0]) - strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); - /* * Be backwards-compatible with previous kernels, so users * won't get the wrong elevator. */ - if (!strcmp(chosen_elevator, "as")) + if (!strcmp(str, "as")) strcpy(chosen_elevator, "anticipatory"); - - /* - * If the given scheduler is not available, fall back to the default - */ - if ((e = elevator_find(chosen_elevator))) - elevator_put(e); else - strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); -} - -static int __init elevator_setup(char *str) -{ - strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); + strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); return 0; } @@ -184,14 +165,16 @@ int elevator_init(request_queue_t *q, char *name) q->end_sector = 0; q->boundary_rq = NULL; - elevator_setup_default(); + if (name && !(e = elevator_get(name))) + return -EINVAL; - if (!name) - name = chosen_elevator; + if (!e && *chosen_elevator && !(e = elevator_get(chosen_elevator))) + printk("I/O scheduler %s not found\n", chosen_elevator); - e = elevator_get(name); - if (!e) - return -EINVAL; + if (!e && !(e = elevator_get(CONFIG_DEFAULT_IOSCHED))) { + printk("Default I/O scheduler not found, using no-op\n"); + e = elevator_get("noop"); + } eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); if (!eq) { @@ -310,7 +293,7 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE, 0); + elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); } static void elv_drain_elevator(request_queue_t *q) @@ -327,40 +310,11 @@ static void elv_drain_elevator(request_queue_t *q) } } -void __elv_add_request(request_queue_t *q, struct request *rq, int where, - int plug) +void elv_insert(request_queue_t *q, struct request *rq, int where) { struct list_head *pos; unsigned ordseq; - if (q->ordcolor) - rq->flags |= REQ_ORDERED_COLOR; - - if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { - /* - * toggle ordered color - */ - q->ordcolor ^= 1; - - /* - * barriers implicitly indicate back insertion - */ - if (where == ELEVATOR_INSERT_SORT) - where = ELEVATOR_INSERT_BACK; - - /* - * this request is scheduling boundary, update end_sector - */ - if (blk_fs_request(rq)) { - q->end_sector = rq_end_sector(rq); - q->boundary_rq = rq; - } - } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) - where = ELEVATOR_INSERT_BACK; - - if (plug) - blk_plug_device(q); - rq->q = q; switch (where) { @@ -441,6 +395,42 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, } } +void __elv_add_request(request_queue_t *q, struct request *rq, int where, + int plug) +{ + if (q->ordcolor) + rq->flags |= REQ_ORDERED_COLOR; + + if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { + /* + * toggle ordered color + */ + if (blk_barrier_rq(rq)) + q->ordcolor ^= 1; + + /* + * barriers implicitly indicate back insertion + */ + if (where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + + /* + * this request is scheduling boundary, update + * end_sector + */ + if (blk_fs_request(rq)) { + q->end_sector = rq_end_sector(rq); + q->boundary_rq = rq; + } + } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + + if (plug) + blk_plug_device(q); + + elv_insert(q, rq, where); +} + void elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { @@ -669,8 +659,10 @@ int elv_register(struct elevator_type *e) spin_unlock_irq(&elv_list_lock); printk(KERN_INFO "io scheduler %s registered", e->elevator_name); - if (!strcmp(e->elevator_name, chosen_elevator)) - printk(" (default)"); + if (!strcmp(e->elevator_name, chosen_elevator) || + (!*chosen_elevator && + !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) + printk(" (default)"); printk("\n"); return 0; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 8e27d0ab0d7c..03d9c82b0fe7 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -304,6 +304,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq) * blk_queue_ordered - does this queue support ordered writes * @q: the request queue * @ordered: one of QUEUE_ORDERED_* + * @prepare_flush_fn: rq setup helper for cache flush ordered writes * * Description: * For journalled file systems, doing ordered writes on a commit @@ -332,6 +333,7 @@ int blk_queue_ordered(request_queue_t *q, unsigned ordered, return -EINVAL; } + q->ordered = ordered; q->next_ordered = ordered; q->prepare_flush_fn = prepare_flush_fn; @@ -452,7 +454,7 @@ static void queue_flush(request_queue_t *q, unsigned which) rq->end_io = end_io; q->prepare_flush_fn(q, rq); - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); + elv_insert(q, rq, ELEVATOR_INSERT_FRONT); } static inline struct request *start_ordered(request_queue_t *q, @@ -488,7 +490,7 @@ static inline struct request *start_ordered(request_queue_t *q, else q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH; - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); + elv_insert(q, rq, ELEVATOR_INSERT_FRONT); if (q->ordered & QUEUE_ORDERED_PREFLUSH) { queue_flush(q, QUEUE_ORDERED_PREFLUSH); @@ -506,7 +508,7 @@ static inline struct request *start_ordered(request_queue_t *q, int blk_do_ordered(request_queue_t *q, struct request **rqp) { - struct request *rq = *rqp, *allowed_rq; + struct request *rq = *rqp; int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); if (!q->ordseq) { @@ -530,32 +532,26 @@ int blk_do_ordered(request_queue_t *q, struct request **rqp) } } + /* + * Ordered sequence in progress + */ + + /* Special requests are not subject to ordering rules. */ + if (!blk_fs_request(rq) && + rq != &q->pre_flush_rq && rq != &q->post_flush_rq) + return 1; + if (q->ordered & QUEUE_ORDERED_TAG) { + /* Ordered by tag. Blocking the next barrier is enough. */ if (is_barrier && rq != &q->bar_rq) *rqp = NULL; - return 1; - } - - switch (blk_ordered_cur_seq(q)) { - case QUEUE_ORDSEQ_PREFLUSH: - allowed_rq = &q->pre_flush_rq; - break; - case QUEUE_ORDSEQ_BAR: - allowed_rq = &q->bar_rq; - break; - case QUEUE_ORDSEQ_POSTFLUSH: - allowed_rq = &q->post_flush_rq; - break; - default: - allowed_rq = NULL; - break; + } else { + /* Ordered by draining. Wait for turn. */ + WARN_ON(blk_ordered_req_seq(rq) < blk_ordered_cur_seq(q)); + if (blk_ordered_req_seq(rq) > blk_ordered_cur_seq(q)) + *rqp = NULL; } - if (rq != allowed_rq && - (blk_fs_request(rq) || rq == &q->pre_flush_rq || - rq == &q->post_flush_rq)) - *rqp = NULL; - return 1; } @@ -662,7 +658,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit); * Enables a low level driver to set an upper limit on the size of * received requests. **/ -void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors) +void blk_queue_max_sectors(request_queue_t *q, unsigned int max_sectors) { if ((max_sectors << 9) < PAGE_CACHE_SIZE) { max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); @@ -2577,6 +2573,8 @@ void disk_round_stats(struct gendisk *disk) disk->stamp = now; } +EXPORT_SYMBOL_GPL(disk_round_stats); + /* * queue lock must be held */ @@ -2632,6 +2630,7 @@ EXPORT_SYMBOL(blk_put_request); /** * blk_end_sync_rq - executes a completion event on a request * @rq: request to complete + * @error: end io status of the request */ void blk_end_sync_rq(struct request *rq, int error) { @@ -3153,7 +3152,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (blk_fs_request(req) && req->rq_disk) { const int rw = rq_data_dir(req); - __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); + disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); } total_bytes = bio_nbytes = 0; @@ -3448,7 +3447,7 @@ 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++) + for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index cc72210687eb..24f7af9d0abc 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -310,6 +310,8 @@ static int sg_io(struct file *file, request_queue_t *q, if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; + rq->retries = 0; + start_time = jiffies; /* ignore return value. All information is passed back to caller @@ -427,6 +429,7 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q, rq->data = buffer; rq->data_len = bytes; rq->flags |= REQ_BLOCK_PC; + rq->retries = 0; blk_execute_rq(q, bd_disk, rq, 0); err = rq->errors & 0xff; /* only 8 bit SCSI status */ diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 47ac90e615f4..2953e2cc56f0 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -17,7 +17,6 @@ #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/highmem.h> -#include <asm/bug.h> #include <asm/scatterlist.h> #include "internal.h" #include "scatterwalk.h" diff --git a/drivers/Kconfig b/drivers/Kconfig index 283c089537bc..bddf431bbb72 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -68,4 +68,6 @@ source "drivers/infiniband/Kconfig" source "drivers/sn/Kconfig" +source "drivers/edac/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 7c45050ecd03..5c69b86db624 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -63,12 +63,13 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ obj-$(CONFIG_ISDN) += isdn/ +obj-$(CONFIG_EDAC) += edac/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_INFINIBAND) += infiniband/ -obj-$(CONFIG_SGI_IOC4) += sn/ +obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 6d61945260a8..0cce28c4025b 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -267,7 +267,6 @@ config ACPI_DEBUG config ACPI_EC bool - depends on X86 default y help This driver is required on some systems for the proper operation of diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 2143609d2936..d882bf87fa96 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -71,8 +71,8 @@ static struct acpi_driver acpi_memory_device_driver = { struct acpi_memory_device { acpi_handle handle; unsigned int state; /* State of the memory device */ - unsigned short cache_attribute; /* memory cache attribute */ - unsigned short read_write_attribute; /* memory read/write attribute */ + unsigned short caching; /* memory cache attribute */ + unsigned short write_protect; /* memory read/write attribute */ u64 start_addr; /* Memory Range start physical addr */ u64 end_addr; /* Memory Range end physical addr */ }; @@ -97,12 +97,12 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) if (ACPI_SUCCESS(status)) { if (address64.resource_type == ACPI_MEMORY_RANGE) { /* Populate the structure */ - mem_device->cache_attribute = - address64.attribute.memory.cache_attribute; - mem_device->read_write_attribute = - address64.attribute.memory.read_write_attribute; - mem_device->start_addr = address64.min_address_range; - mem_device->end_addr = address64.max_address_range; + mem_device->caching = + address64.info.mem.caching; + mem_device->write_protect = + address64.info.mem.write_protect; + mem_device->start_addr = address64.minimum; + mem_device->end_addr = address64.maximum; } } @@ -250,7 +250,6 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device) int result; u64 start = mem_device->start_addr; u64 len = mem_device->end_addr - start + 1; - unsigned long attr = mem_device->read_write_attribute; ACPI_FUNCTION_TRACE("acpi_memory_disable_device"); diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index fec895af6ae6..f4c87750dbf2 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -78,9 +78,9 @@ MODULE_LICENSE("GPL"); static uid_t asus_uid; static gid_t asus_gid; module_param(asus_uid, uint, 0); -MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n"); +MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus.\n"); module_param(asus_gid, uint, 0); -MODULE_PARM_DESC(gid, "GID for entries in /proc/acpi/asus.\n"); +MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus.\n"); /* For each model, all features implemented, * those marked with R are relative to HOTK, A for absolute */ @@ -302,7 +302,7 @@ static struct model_data model_conf[END_MODEL] = { .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", - .display_get = "\\SSTE"}, + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, { .name = "M6R", .mt_mled = "MLED", @@ -851,6 +851,8 @@ static int __init asus_hotk_add_fs(struct acpi_device *device) mode = S_IFREG | S_IRUGO | S_IWUGO; } else { mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; + printk(KERN_WARNING " asus_uid and asus_gid parameters are " + "deprecated, use chown and chmod instead!\n"); } acpi_device_dir(device) = asus_proc_dir; @@ -987,9 +989,21 @@ static int __init asus_hotk_get_info(void) printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result); - /* Samsung P30 has a device with a valid _HID whose INIT does not - * return anything. Catch this one and any similar here */ - if (buffer.pointer == NULL) { + /* This is unlikely with implicit return */ + if (buffer.pointer == NULL) + return -EINVAL; + + model = (union acpi_object *) buffer.pointer; + /* + * Samsung P30 has a device with a valid _HID whose INIT does not + * return anything. It used to be possible to catch this exception, + * but the implicit return code will now happily confuse the + * driver. We assume that every ACPI_TYPE_STRING is a valid model + * identifier but it's still possible to get completely bogus data. + */ + if (model->type == ACPI_TYPE_STRING) { + printk(KERN_NOTICE " %s model detected, ", model->string.pointer); + } else { if (asus_info && /* Samsung P30 */ strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { hotk->model = P30; @@ -1002,13 +1016,10 @@ static int __init asus_hotk_get_info(void) "the developers with your DSDT\n"); } hotk->methods = &model_conf[hotk->model]; - return AE_OK; - } + + acpi_os_free(model); - model = (union acpi_object *)buffer.pointer; - if (model->type == ACPI_TYPE_STRING) { - printk(KERN_NOTICE " %s model detected, ", - model->string.pointer); + return AE_OK; } hotk->model = END_MODEL; diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 2022aeaecfbb..76bc0463f6de 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -128,7 +128,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node)); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); } } @@ -232,7 +232,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + (acpi_integer) arg->common.value.size; if (position > ACPI_UINT32_MAX) { - ACPI_REPORT_ERROR(("Bit offset within field too large (> 0xFFFFFFFF)\n")); + ACPI_ERROR((AE_INFO, + "Bit offset within field too large (> 0xFFFFFFFF)")); return_ACPI_STATUS(AE_SUPPORT); } @@ -268,8 +269,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ACPI_NS_DONT_OPEN_SCOPE, walk_state, &info->field_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR((char *)&arg->named.name, - status); + ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + status); if (status != AE_ALREADY_EXISTS) { return_ACPI_STATUS(status); } @@ -293,7 +294,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + (acpi_integer) arg->common.value.size; if (position > ACPI_UINT32_MAX) { - ACPI_REPORT_ERROR(("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n", (char *)&info->field_node->name)); + ACPI_ERROR((AE_INFO, + "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", + ACPI_CAST_PTR(char, + &info->field_node-> + name))); return_ACPI_STATUS(AE_SUPPORT); } @@ -302,9 +307,9 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid opcode in field list: %X\n", - arg->common.aml_opcode)); + ACPI_ERROR((AE_INFO, + "Invalid opcode in field list: %X", + arg->common.aml_opcode)); return_ACPI_STATUS(AE_AML_BAD_OPCODE); } @@ -349,7 +354,7 @@ acpi_ds_create_field(union acpi_parse_object *op, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.name, status); + ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); } } @@ -431,8 +436,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ACPI_NS_ERROR_IF_FOUND, walk_state, &node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR((char *)&arg->named.name, - status); + ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + status); if (status != AE_ALREADY_EXISTS) { return_ACPI_STATUS(status); } @@ -488,7 +493,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.name, status); + ACPI_ERROR_NAMESPACE(arg->common.value.name, status); return_ACPI_STATUS(status); } } @@ -502,7 +507,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); } @@ -560,7 +565,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); } @@ -573,7 +578,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index 8693c704aea6..e65a07ad2422 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, acpi_object_type type; acpi_status status; - ACPI_FUNCTION_NAME("ds_init_one_object"); + ACPI_FUNCTION_ENTRY(); /* * We are only interested in NS nodes owned by the table that @@ -105,11 +105,10 @@ acpi_ds_init_one_object(acpi_handle obj_handle, status = acpi_ds_initialize_region(obj_handle); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Region %p [%4.4s] - Init failure, %s\n", - obj_handle, - acpi_ut_get_node_name(obj_handle), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "During Region initialization %p [%4.4s]", + obj_handle, + acpi_ut_get_node_name(obj_handle))); } info->op_region_count++; @@ -118,14 +117,6 @@ acpi_ds_init_one_object(acpi_handle obj_handle, case ACPI_TYPE_METHOD: /* - * Print a dot for each method unless we are going to print - * the entire pathname - */ - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. * TBD: This is really for possible future support of integer width @@ -134,6 +125,21 @@ acpi_ds_init_one_object(acpi_handle obj_handle, if (info->table_desc->pointer->revision == 1) { node->flags |= ANOBJ_DATA_WIDTH_32; } +#ifdef ACPI_INIT_PARSE_METHODS + /* + * Note 11/2005: Removed this code to parse all methods during table + * load because it causes problems if there are any errors during the + * parse. Also, it seems like overkill and we probably don't want to + * abort a table load because of an issue with a single method. + */ + + /* + * Print a dot for each method unless we are going to print + * the entire pathname + */ + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); + } /* * Always parse methods to detect errors, we will delete @@ -141,15 +147,15 @@ acpi_ds_init_one_object(acpi_handle obj_handle, */ status = acpi_ds_parse_method(obj_handle); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "\n+Method %p [%4.4s] - parse failure, %s\n", - obj_handle, - acpi_ut_get_node_name(obj_handle), - acpi_format_exception(status))); + ACPI_ERROR((AE_INFO, + "Method %p [%4.4s] - parse failure, %s", + obj_handle, + acpi_ut_get_node_name(obj_handle), + acpi_format_exception(status))); /* This parse failed, but we will continue parsing more methods */ } - +#endif info->method_count++; break; @@ -207,8 +213,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, acpi_ds_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 36c1ca0b9adb..c475546535b6 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,135 +47,66 @@ #include <acpi/acdispat.h> #include <acpi/acinterp.h> #include <acpi/acnamesp.h> +#include <acpi/acdisasm.h> #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsmethod") /******************************************************************************* * - * FUNCTION: acpi_ds_parse_method + * FUNCTION: acpi_ds_method_error * - * PARAMETERS: Node - Method node + * PARAMETERS: Status - Execution status + * walk_state - Current state * * RETURN: Status * - * DESCRIPTION: Parse the AML that is associated with the method. + * DESCRIPTION: Called on method error. Invoke the global exception handler if + * present, dump the method data if the disassembler is configured * - * MUTEX: Assumes parser is locked + * Note: Allows the exception handler to change the status code * ******************************************************************************/ -acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) +acpi_status +acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) { - acpi_status status; - union acpi_operand_object *obj_desc; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); + ACPI_FUNCTION_ENTRY(); - /* Parameter Validation */ + /* Ignore AE_OK and control exception codes */ - if (!node) { - return_ACPI_STATUS(AE_NULL_ENTRY); + if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) { + return (status); } - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** Parsing [%4.4s] **** named_obj=%p\n", - acpi_ut_get_node_name(node), node)); - - /* Extract the method object from the method Node */ + /* Invoke the global exception handler */ - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - return_ACPI_STATUS(AE_NULL_OBJECT); - } + if (acpi_gbl_exception_handler) { + /* Exit the interpreter, allow handler to execute methods */ - /* Create a mutex for the method if there is a concurrency limit */ + acpi_ex_exit_interpreter(); - if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && - (!obj_desc->method.semaphore)) { - status = acpi_os_create_semaphore(obj_desc->method.concurrency, - obj_desc->method.concurrency, - &obj_desc->method.semaphore); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - /* - * Allocate a new parser op to be the root of the parsed - * method tree - */ - op = acpi_ps_alloc_op(AML_METHOD_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Init new op with the method name and pointer back to the Node */ - - acpi_ps_set_name(op, node->name.integer); - op->common.node = node; - - /* - * Get a new owner_id for objects created by this method. Namespace - * objects (such as Operation Regions) can be created during the - * first pass parse. - */ - status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Create and initialize a new walk state */ - - walk_state = - acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, - NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup2; + /* + * Handler can map the exception code to anything it wants, including + * AE_OK, in which case the executing method will not be aborted. + */ + status = acpi_gbl_exception_handler(status, + walk_state->method_node ? + walk_state->method_node-> + name.integer : 0, + walk_state->opcode, + walk_state->aml_offset, + NULL); + (void)acpi_ex_enter_interpreter(); } - - status = acpi_ds_init_aml_walk(walk_state, op, node, - obj_desc->method.aml_start, - obj_desc->method.aml_length, NULL, 1); +#ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup2; - } + /* Display method locals/args if disassembler is present */ - /* - * Parse the method, first pass - * - * The first pass load is where newly declared named objects are added into - * the namespace. Actual evaluation of the named objects (what would be - * called a "second pass") happens during the actual execution of the - * method so that operands to the named objects can take on dynamic - * run-time values. - */ - status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup2; + acpi_dm_dump_method_info(status, walk_state, walk_state->op); } +#endif - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", - acpi_ut_get_node_name(node), node, op)); - - /* - * Delete the parse tree. We simply re-parse the method for every - * execution since there isn't much overhead (compared to keeping lots - * of parse trees around) - */ - acpi_ns_delete_namespace_subtree(node); - acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); - - cleanup2: - acpi_ut_release_owner_id(&obj_desc->method.owner_id); - - cleanup: - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(status); + return (status); } /******************************************************************************* @@ -195,9 +126,9 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) ******************************************************************************/ acpi_status -acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, - union acpi_operand_object *obj_desc, - struct acpi_namespace_node *calling_method_node) +acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node, + union acpi_operand_object * obj_desc, + struct acpi_namespace_node * calling_method_node) { acpi_status status = AE_OK; @@ -210,7 +141,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, /* Prevent wraparound of thread count */ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { - ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n")); + ACPI_ERROR((AE_INFO, + "Method reached maximum reentrancy limit (255)")); return_ACPI_STATUS(AE_AML_METHOD_LIMIT); } @@ -539,22 +471,61 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) acpi_os_signal_semaphore(walk_state->method_desc->method. semaphore, 1); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not signal method semaphore\n")); + ACPI_ERROR((AE_INFO, + "Could not signal method semaphore")); /* Ignore error and continue cleanup */ } } + /* + * There are no more threads executing this method. Perform + * additional cleanup. + * + * The method Node is stored in the walk state + */ + method_node = walk_state->method_node; + + /* Lock namespace for possible update */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* + * Delete any namespace entries created immediately underneath + * the method + */ + if (method_node->child) { + acpi_ns_delete_namespace_subtree(method_node); + } + + /* + * Delete any namespace entries created anywhere else within + * the namespace by the execution of this method + */ + acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method. + owner_id); + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + /* Are there any other threads currently executing this method? */ + if (walk_state->method_desc->method.thread_count) { + /* + * Additional threads. Do not release the owner_id in this case, + * we immediately reuse it for the next thread executing this method + */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "*** Not deleting method namespace, there are still %d threads\n", + "*** Completed execution of one thread, %d threads remaining\n", walk_state->method_desc->method. thread_count)); - } else { /* This is the last executing thread */ + } else { + /* This is the only executing thread for this method */ /* * Support to dynamically change a method from not_serialized to - * Serialized if it appears that the method is written foolishly and + * Serialized if it appears that the method is incorrectly written and * does not support multiple thread execution. The best example of this * is if such a method creates namespace objects and blocks. A second * thread will fail with an AE_ALREADY_EXISTS exception @@ -570,34 +541,8 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) semaphore); } - /* - * There are no more threads executing this method. Perform - * additional cleanup. - * - * The method Node is stored in the walk state - */ - method_node = walk_state->method_node; - - /* - * Delete any namespace entries created immediately underneath - * the method - */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - if (method_node->child) { - acpi_ns_delete_namespace_subtree(method_node); - } + /* No more threads, we can free the owner_id */ - /* - * Delete any namespace entries created anywhere else within - * the namespace - */ - acpi_ns_delete_namespace_by_owner(walk_state->method_desc-> - method.owner_id); - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); acpi_ut_release_owner_id(&walk_state->method_desc->method. owner_id); } @@ -606,3 +551,140 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); return_VOID; } + +#ifdef ACPI_INIT_PARSE_METHODS + /* + * Note 11/2005: Removed this code to parse all methods during table + * load because it causes problems if there are any errors during the + * parse. Also, it seems like overkill and we probably don't want to + * abort a table load because of an issue with a single method. + */ + +/******************************************************************************* + * + * FUNCTION: acpi_ds_parse_method + * + * PARAMETERS: Node - Method node + * + * RETURN: Status + * + * DESCRIPTION: Parse the AML that is associated with the method. + * + * MUTEX: Assumes parser is locked + * + ******************************************************************************/ + +acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) +{ + acpi_status status; + union acpi_operand_object *obj_desc; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); + + /* Parameter Validation */ + + if (!node) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "**** Parsing [%4.4s] **** named_obj=%p\n", + acpi_ut_get_node_name(node), node)); + + /* Extract the method object from the method Node */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return_ACPI_STATUS(AE_NULL_OBJECT); + } + + /* Create a mutex for the method if there is a concurrency limit */ + + if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && + (!obj_desc->method.semaphore)) { + status = acpi_os_create_semaphore(obj_desc->method.concurrency, + obj_desc->method.concurrency, + &obj_desc->method.semaphore); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* + * Allocate a new parser op to be the root of the parsed + * method tree + */ + op = acpi_ps_alloc_op(AML_METHOD_OP); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Init new op with the method name and pointer back to the Node */ + + acpi_ps_set_name(op, node->name.integer); + op->common.node = node; + + /* + * Get a new owner_id for objects created by this method. Namespace + * objects (such as Operation Regions) can be created during the + * first pass parse. + */ + status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Create and initialize a new walk state */ + + walk_state = + acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, + NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup2; + } + + status = acpi_ds_init_aml_walk(walk_state, op, node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, 1); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup2; + } + + /* + * Parse the method, first pass + * + * The first pass load is where newly declared named objects are added into + * the namespace. Actual evaluation of the named objects (what would be + * called a "second pass") happens during the actual execution of the + * method so that operands to the named objects can take on dynamic + * run-time values. + */ + status = acpi_ps_parse_aml(walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup2; + } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", + acpi_ut_get_node_name(node), node, op)); + + /* + * Delete the parse tree. We simply re-parse the method for every + * execution since there isn't much overhead (compared to keeping lots + * of parse trees around) + */ + acpi_ns_delete_namespace_subtree(node); + acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); + + cleanup2: + acpi_ut_release_owner_id(&obj_desc->method.owner_id); + + cleanup: + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} +#endif diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index 4095ce70982b..c025674f938b 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -260,9 +260,9 @@ acpi_ds_method_data_get_node(u16 opcode, case AML_LOCAL_OP: if (index > ACPI_METHOD_MAX_LOCAL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Local index %d is invalid (max %d)\n", - index, ACPI_METHOD_MAX_LOCAL)); + ACPI_ERROR((AE_INFO, + "Local index %d is invalid (max %d)", + index, ACPI_METHOD_MAX_LOCAL)); return_ACPI_STATUS(AE_AML_INVALID_INDEX); } @@ -274,9 +274,9 @@ acpi_ds_method_data_get_node(u16 opcode, case AML_ARG_OP: if (index > ACPI_METHOD_MAX_ARG) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Arg index %d is invalid (max %d)\n", - index, ACPI_METHOD_MAX_ARG)); + ACPI_ERROR((AE_INFO, + "Arg index %d is invalid (max %d)", + index, ACPI_METHOD_MAX_ARG)); return_ACPI_STATUS(AE_AML_INVALID_INDEX); } @@ -286,8 +286,7 @@ acpi_ds_method_data_get_node(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Opcode %d is invalid\n", - opcode)); + ACPI_ERROR((AE_INFO, "Opcode %d is invalid", opcode)); return_ACPI_STATUS(AE_AML_BAD_OPCODE); } @@ -378,8 +377,7 @@ acpi_ds_method_data_get_value(u16 opcode, /* Validate the object descriptor */ if (!dest_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null object descriptor pointer\n")); + ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -424,23 +422,24 @@ acpi_ds_method_data_get_value(u16 opcode, switch (opcode) { case AML_ARG_OP: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Uninitialized Arg[%d] at node %p\n", - index, node)); + ACPI_ERROR((AE_INFO, + "Uninitialized Arg[%d] at node %p", + index, node)); return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); case AML_LOCAL_OP: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Uninitialized Local[%d] at node %p\n", - index, node)); + ACPI_ERROR((AE_INFO, + "Uninitialized Local[%d] at node %p", + index, node)); return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); default: - ACPI_REPORT_ERROR(("Not Arg/Local opcode: %X\n", - opcode)); + ACPI_ERROR((AE_INFO, + "Not a Arg/Local opcode: %X", + opcode)); return_ACPI_STATUS(AE_AML_INTERNAL); } } diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 8ac0cd93adb5..8b21f0f9e517 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsobject") +/* Local prototypes */ static acpi_status acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, union acpi_parse_object *op, @@ -85,7 +86,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, *obj_desc_ptr = NULL; if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* - * This is an named object reference. If this name was + * This is a named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ @@ -96,18 +97,48 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, - (struct acpi_namespace_node **) - &(op->common.node)); - + ACPI_CAST_INDIRECT_PTR(struct + acpi_namespace_node, + &(op-> + common. + node))); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(op->common.value.string, - status); + /* Check if we are resolving a named reference within a package */ + + if ((status == AE_NOT_FOUND) + && (acpi_gbl_enable_interpreter_slack) + && + ((op->common.parent->common.aml_opcode == + AML_PACKAGE_OP) + || (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP))) { + /* + * We didn't find the target and we are populating elements + * of a package - ignore if slack enabled. Some ASL code + * contains dangling invalid references in packages and + * expects that no exception will be issued. Leave the + * element as a null element. It cannot be used, but it + * can be overwritten by subsequent ASL code - this is + * typically the case. + */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Ignoring unresolved reference in package [%4.4s]\n", + walk_state-> + scope_info->scope. + node->name.ascii)); + + return_ACPI_STATUS(AE_OK); + } else { + ACPI_ERROR_NAMESPACE(op->common.value. + string, status); + } + return_ACPI_STATUS(status); } } } - /* Create and init the internal ACPI object */ + /* Create and init a new internal ACPI object */ obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info (op->common.aml_opcode))-> @@ -157,13 +188,13 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj"); + /* + * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". + * The buffer object already exists (from the NS node), otherwise it must + * be created. + */ obj_desc = *obj_desc_ptr; - if (obj_desc) { - /* - * We are evaluating a Named buffer object "Name (xxxx, Buffer)". - * The buffer object already exists (from the NS node) - */ - } else { + if (!obj_desc) { /* Create a new buffer object */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); @@ -183,10 +214,9 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, byte_list = arg->named.next; if (byte_list) { if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Expecting bytelist, got AML opcode %X in op %p\n", - byte_list->common.aml_opcode, - byte_list)); + ACPI_ERROR((AE_INFO, + "Expecting bytelist, got AML opcode %X in op %p", + byte_list->common.aml_opcode, byte_list)); acpi_ut_remove_reference(obj_desc); return (AE_TYPE); @@ -259,7 +289,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_operand_object *obj_desc = NULL; u32 package_list_length; acpi_status status = AE_OK; - u32 i; + acpi_native_uint i; ACPI_FUNCTION_TRACE("ds_build_internal_package_obj"); @@ -271,13 +301,12 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, parent = parent->common.parent; } + /* + * If we are evaluating a Named package object "Name (xxxx, Package)", + * the package object already exists, otherwise it must be created. + */ obj_desc = *obj_desc_ptr; - if (obj_desc) { - /* - * We are evaluating a Named package object "Name (xxxx, Package)". - * Get the existing package object from the NS node - */ - } else { + if (!obj_desc) { obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); *obj_desc_ptr = obj_desc; if (!obj_desc) { @@ -291,11 +320,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, /* Count the number of items in the package list */ - package_list_length = 0; arg = op->common.value.arg; arg = arg->common.next; - while (arg) { - package_list_length++; + for (package_list_length = 0; arg; package_list_length++) { arg = arg->common.next; } @@ -322,12 +349,11 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } /* - * Now init the elements of the package + * Initialize all elements of the package */ - i = 0; arg = op->common.value.arg; arg = arg->common.next; - while (arg) { + for (i = 0; arg; i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { /* Object (package or buffer) is already built */ @@ -340,8 +366,6 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, package. elements[i]); } - - i++; arg = arg->common.next; } @@ -518,9 +542,9 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown constant opcode %X\n", - opcode)); + ACPI_ERROR((AE_INFO, + "Unknown constant opcode %X", + opcode)); status = AE_AML_OPERAND_TYPE; break; } @@ -535,9 +559,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown Integer type %X\n", - op_info->type)); + ACPI_ERROR((AE_INFO, "Unknown Integer type %X", + op_info->type)); status = AE_AML_OPERAND_TYPE; break; } @@ -615,9 +638,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unimplemented data type: %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc))); + ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", + ACPI_GET_OBJECT_TYPE(obj_desc))); status = AE_AML_OPERAND_TYPE; break; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 939d167bf87b..6229c10674e1 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -245,7 +245,9 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) node = obj_desc->buffer.node; if (!node) { - ACPI_REPORT_ERROR(("No pointer back to NS node in buffer obj %p\n", obj_desc)); + ACPI_ERROR((AE_INFO, + "No pointer back to NS node in buffer obj %p", + obj_desc)); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -287,8 +289,9 @@ acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) node = obj_desc->package.node; if (!node) { - ACPI_REPORT_ERROR(("No pointer back to NS node in package %p\n", - obj_desc)); + ACPI_ERROR((AE_INFO, + "No pointer back to NS node in package %p", + obj_desc)); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -413,9 +416,9 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Host object must be a Buffer */ if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Target of Create Field is not a Buffer object - %s\n", - acpi_ut_get_object_type_name(buffer_desc))); + ACPI_ERROR((AE_INFO, + "Target of Create Field is not a Buffer object - %s", + acpi_ut_get_object_type_name(buffer_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -427,10 +430,10 @@ acpi_ds_init_buffer_field(u16 aml_opcode, * after resolution in acpi_ex_resolve_operands(). */ if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(%s) destination not a NS Node [%s]\n", - acpi_ps_get_opcode_name(aml_opcode), - acpi_ut_get_descriptor_name(result_desc))); + ACPI_ERROR((AE_INFO, + "(%s) destination not a NS Node [%s]", + acpi_ps_get_opcode_name(aml_opcode), + acpi_ut_get_descriptor_name(result_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -453,8 +456,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Must have a valid (>0) bit count */ if (bit_count == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Attempt to create_field of length 0\n")); + ACPI_ERROR((AE_INFO, + "Attempt to create_field of length zero")); status = AE_AML_OPERAND_VALUE; goto cleanup; } @@ -507,9 +510,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown field creation opcode %02x\n", - aml_opcode)); + ACPI_ERROR((AE_INFO, + "Unknown field creation opcode %02x", aml_opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -517,13 +519,12 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Entire field must fit within the current length of the buffer */ if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n", - acpi_ut_get_node_name(result_desc), - bit_offset + bit_count, - acpi_ut_get_node_name(buffer_desc->buffer. - node), - 8 * (u32) buffer_desc->buffer.length)); + ACPI_ERROR((AE_INFO, + "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)", + acpi_ut_get_node_name(result_desc), + bit_offset + bit_count, + acpi_ut_get_node_name(buffer_desc->buffer.node), + 8 * (u32) buffer_desc->buffer.length)); status = AE_AML_BUFFER_LIMIT; goto cleanup; } @@ -629,9 +630,9 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, "after acpi_ex_resolve_operands"); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n", - acpi_ps_get_opcode_name(op->common. - aml_opcode), status)); + ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", + acpi_ps_get_opcode_name(op->common.aml_opcode), + status)); return_ACPI_STATUS(status); } @@ -1155,9 +1156,8 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown control opcode=%X Op=%p\n", - op->common.aml_opcode, op)); + ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", + op->common.aml_opcode, op)); status = AE_AML_BAD_OPCODE; break; diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 83ae1c1aa286..53356a591ac1 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,8 +176,8 @@ acpi_ds_is_result_used(union acpi_parse_object * op, /* Must have both an Op and a Result Object */ if (!op) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n")); - return_VALUE(TRUE); + ACPI_ERROR((AE_INFO, "Null Op")); + return_UINT8(TRUE); } /* @@ -208,7 +208,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, "At Method level, result of [%s] not used\n", acpi_ps_get_opcode_name(op->common. aml_opcode))); - return_VALUE(FALSE); + return_UINT8(FALSE); } /* Get info on the parent. The root_op is AML_SCOPE */ @@ -216,9 +216,8 @@ acpi_ds_is_result_used(union acpi_parse_object * op, parent_info = acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown parent opcode. Op=%p\n", op)); - return_VALUE(FALSE); + ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); + return_UINT8(FALSE); } /* @@ -304,7 +303,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_VALUE(TRUE); + return_UINT8(TRUE); result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, @@ -313,7 +312,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_VALUE(FALSE); + return_UINT8(FALSE); } /******************************************************************************* @@ -344,7 +343,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj); if (!op) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null Op\n")); + ACPI_ERROR((AE_INFO, "Null Op")); return_VOID; } @@ -567,7 +566,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, } if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(name_string, status); + ACPI_ERROR_NAMESPACE(name_string, status); } } @@ -616,7 +615,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, if (op_info->flags & AML_HAS_RETVAL) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Argument previously created, already stacked \n")); + "Argument previously created, already stacked\n")); ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object (walk_state-> @@ -635,10 +634,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * Only error is underflow, and this indicates * a missing or null operand! */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Missing or null operand, %s\n", - acpi_format_exception - (status))); + ACPI_EXCEPTION((AE_INFO, status, + "Missing or null operand")); return_ACPI_STATUS(status); } } else { @@ -730,7 +727,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, */ (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "While creating Arg %d - %s\n", - (arg_count + 1), acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", + (arg_count + 1))); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index e522763bb692..f1af655ff113 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -100,9 +100,8 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, if (result_obj) { status = acpi_ds_result_pop(&obj_desc, walk_state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not get result from predicate evaluation, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not get result from predicate evaluation")); return_ACPI_STATUS(status); } @@ -123,9 +122,9 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, } if (!obj_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No predicate obj_desc=%p State=%p\n", - obj_desc, walk_state)); + ACPI_ERROR((AE_INFO, + "No predicate obj_desc=%p State=%p", + obj_desc, walk_state)); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -140,10 +139,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, } if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n", - obj_desc, walk_state, - ACPI_GET_OBJECT_TYPE(obj_desc))); + ACPI_ERROR((AE_INFO, + "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X", + obj_desc, walk_state, + ACPI_GET_OBJECT_TYPE(obj_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -314,12 +313,13 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* * Most operators with arguments. * Start a new result/operand state */ - status = acpi_ds_result_stack_push(walk_state); + if (walk_state->opcode != AML_CREATE_FIELD_OP) { + status = acpi_ds_result_stack_push(walk_state); + } break; default: @@ -361,8 +361,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) op_class = walk_state->op_info->class; if (op_class == AML_CLASS_UNKNOWN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown opcode %X\n", - op->common.aml_opcode)); + ACPI_ERROR((AE_INFO, "Unknown opcode %X", + op->common.aml_opcode)); return_ACPI_STATUS(AE_NOT_IMPLEMENTED); } @@ -452,12 +452,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) walk_state->operands[1]->reference.offset)) { status = AE_OK; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "[%s]: Could not resolve operands, %s\n", - acpi_ps_get_opcode_name - (walk_state->opcode), - acpi_format_exception - (status))); + ACPI_EXCEPTION((AE_INFO, status, + "While resolving operands for [%s]", + acpi_ps_get_opcode_name + (walk_state->opcode))); } } @@ -676,8 +674,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) case AML_TYPE_UNDEFINED: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Undefined opcode type Op=%p\n", op)); + ACPI_ERROR((AE_INFO, + "Undefined opcode type Op=%p", op)); return_ACPI_STATUS(AE_NOT_IMPLEMENTED); case AML_TYPE_BOGUS: @@ -689,10 +687,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n", - op_class, op_type, - op->common.aml_opcode, op)); + ACPI_ERROR((AE_INFO, + "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p", + op_class, op_type, op->common.aml_opcode, + op)); status = AE_NOT_IMPLEMENTED; break; @@ -723,20 +721,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) cleanup: - /* Invoke exception handler on error */ - - if (ACPI_FAILURE(status) && - acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) { - acpi_ex_exit_interpreter(); - status = acpi_gbl_exception_handler(status, - walk_state->method_node-> - name.integer, - walk_state->opcode, - walk_state->aml_offset, - NULL); - (void)acpi_ex_enter_interpreter(); - } - if (walk_state->result_obj) { /* Break to debugger to display result */ @@ -758,18 +742,14 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) } #endif - /* Always clear the object stack */ - - walk_state->num_operands = 0; - -#ifdef ACPI_DISASSEMBLER - - /* On error, display method locals/args */ + /* Invoke exception handler on error */ if (ACPI_FAILURE(status)) { - acpi_dm_dump_method_info(status, walk_state, op); + status = acpi_ds_method_error(status, walk_state); } -#endif + /* Always clear the object stack */ + + walk_state->num_operands = 0; return_ACPI_STATUS(status); } diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 411731261c29..d3d24da31c81 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, char *path; u32 flags; - ACPI_FUNCTION_NAME("ds_load1_begin_op"); + ACPI_FUNCTION_TRACE("ds_load1_begin_op"); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -138,14 +138,14 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, if (op) { if (!(walk_state->op_info->flags & AML_NAMED)) { *out_op = op; - return (AE_OK); + return_ACPI_STATUS(AE_OK); } /* Check if this object has already been installed in the namespace */ if (op->common.node) { *out_op = op; - return (AE_OK); + return_ACPI_STATUS(AE_OK); } } @@ -187,8 +187,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, } #endif if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(path, status); - return (status); + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); } /* @@ -233,9 +233,11 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* All other types are an error */ - ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path)); + ACPI_ERROR((AE_INFO, + "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", + acpi_ut_get_type_name(node->type), path)); - return (AE_AML_OPERAND_TYPE); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } break; @@ -257,6 +259,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * buffer_field, or Package), the name of the object is already * in the namespace. */ + if (walk_state->deferred_node) { /* This name is already in the namespace, get the node */ @@ -265,6 +268,16 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, break; } + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (walk_state->method_node) { + node = NULL; + status = AE_OK; + break; + } + flags = ACPI_NS_NO_UPSEARCH; if ((walk_state->opcode != AML_SCOPE_OP) && (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { @@ -289,8 +302,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node)); if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(path, status); - return (status); + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); } break; } @@ -302,28 +315,29 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, op = acpi_ps_alloc_op(walk_state->opcode); if (!op) { - return (AE_NO_MEMORY); + return_ACPI_STATUS(AE_NO_MEMORY); } } - /* Initialize */ - - op->named.name = node->name.integer; + /* Initialize the op */ #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) - op->named.path = (u8 *) path; + op->named.path = ACPI_CAST_PTR(u8, path); #endif - /* - * Put the Node in the "op" object that the parser uses, so we - * can get it again quickly when this scope is closed - */ - op->common.node = node; + if (node) { + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->common.node = node; + op->named.name = node->name.integer; + } + acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), op); - *out_op = op; - return (status); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -339,13 +353,13 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * ******************************************************************************/ -acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) +acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) { union acpi_parse_object *op; acpi_object_type object_type; acpi_status status = AE_OK; - ACPI_FUNCTION_NAME("ds_load1_end_op"); + ACPI_FUNCTION_TRACE("ds_load1_end_op"); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -354,7 +368,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { - return (AE_OK); + return_ACPI_STATUS(AE_OK); } /* Get the object type to determine if we should pop the scope */ @@ -363,21 +377,37 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) #ifndef ACPI_NO_METHOD_EXECUTION if (walk_state->op_info->flags & AML_FIELD) { - if (walk_state->opcode == AML_FIELD_OP || - walk_state->opcode == AML_BANK_FIELD_OP || - walk_state->opcode == AML_INDEX_FIELD_OP) { - status = acpi_ds_init_field_objects(op, walk_state); + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (walk_state->opcode == AML_FIELD_OP || + walk_state->opcode == AML_BANK_FIELD_OP || + walk_state->opcode == AML_INDEX_FIELD_OP) { + status = + acpi_ds_init_field_objects(op, walk_state); + } } - return (status); + return_ACPI_STATUS(status); } - if (op->common.aml_opcode == AML_REGION_OP) { - status = acpi_ex_create_region(op->named.data, op->named.length, - (acpi_adr_space_type) - ((op->common.value.arg)->common. - value.integer), walk_state); - if (ACPI_FAILURE(status)) { - return (status); + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (op->common.aml_opcode == AML_REGION_OP) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + (acpi_adr_space_type) + ((op->common.value.arg)-> + common.value.integer), + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } #endif @@ -391,47 +421,63 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) common. aml_opcode))-> object_type; - op->common.node->type = (u8) object_type; + + /* Set node type if we have a namespace node */ + + if (op->common.node) { + op->common.node->type = (u8) object_type; + } } } - if (op->common.aml_opcode == AML_METHOD_OP) { - /* - * method_op pkg_length name_string method_flags term_list - * - * Note: We must create the method node/object pair as soon as we - * see the method declaration. This allows later pass1 parsing - * of invocations of the method (need to know the number of - * arguments.) - */ - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p named_obj=%p\n", - walk_state, op, op->named.node)); + /* + * If we are executing a method, do not create any namespace objects + * during the load phase, only during execution. + */ + if (!walk_state->method_node) { + if (op->common.aml_opcode == AML_METHOD_OP) { + /* + * method_op pkg_length name_string method_flags term_list + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p named_obj=%p\n", + walk_state, op, op->named.node)); - if (!acpi_ns_get_attached_object(op->named.node)) { - walk_state->operands[0] = (void *)op->named.node; - walk_state->num_operands = 1; + if (!acpi_ns_get_attached_object(op->named.node)) { + walk_state->operands[0] = + ACPI_CAST_PTR(void, op->named.node); + walk_state->num_operands = 1; - status = - acpi_ds_create_operands(walk_state, - op->common.value.arg); - if (ACPI_SUCCESS(status)) { - status = acpi_ex_create_method(op->named.data, - op->named.length, - walk_state); - } - walk_state->operands[0] = NULL; - walk_state->num_operands = 0; + status = + acpi_ds_create_operands(walk_state, + op->common.value. + arg); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_create_method(op->named. + data, + op->named. + length, + walk_state); + } + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; - if (ACPI_FAILURE(status)) { - return (status); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } } } - /* Pop the scope stack */ + /* Pop the scope stack (only if loading a table) */ - if (acpi_ns_opens_scope(object_type)) { + if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", acpi_ut_get_type_name(object_type), op)); @@ -439,7 +485,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) status = acpi_ds_scope_stack_pop(walk_state); } - return (status); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -456,8 +502,8 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) ******************************************************************************/ acpi_status -acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, - union acpi_parse_object ** out_op) +acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) { union acpi_parse_object *op; struct acpi_namespace_node *node; @@ -574,10 +620,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, if (status == AE_NOT_FOUND) { status = AE_OK; } else { - ACPI_REPORT_NSERROR(buffer_ptr, status); + ACPI_ERROR_NAMESPACE(buffer_ptr, status); } #else - ACPI_REPORT_NSERROR(buffer_ptr, status); + ACPI_ERROR_NAMESPACE(buffer_ptr, status); #endif return_ACPI_STATUS(status); } @@ -607,7 +653,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, * Scope (DEB) { ... } */ - ACPI_REPORT_WARNING(("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", buffer_ptr, acpi_ut_get_type_name(node->type))); + ACPI_WARNING((AE_INFO, + "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", + buffer_ptr, + acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; walk_state->scope_info->common.value = ACPI_TYPE_ANY; @@ -617,7 +666,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, /* All other types are an error */ - ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s]\n", acpi_ut_get_type_name(node->type), buffer_ptr)); + ACPI_ERROR((AE_INFO, + "Invalid type (%s) for target of Scope operator [%4.4s]", + acpi_ut_get_type_name(node->type), + buffer_ptr)); return (AE_AML_OPERAND_TYPE); } @@ -670,7 +722,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, } if (ACPI_FAILURE(status)) { - ACPI_REPORT_NSERROR(buffer_ptr, status); + ACPI_ERROR_NAMESPACE(buffer_ptr, status); return_ACPI_STATUS(status); } @@ -840,6 +892,13 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) case AML_TYPE_NAMED_FIELD: + /* + * If we are executing a method, initialize the field + */ + if (walk_state->method_node) { + status = acpi_ds_init_field_objects(op, walk_state); + } + switch (op->common.aml_opcode) { case AML_INDEX_FIELD_OP: @@ -929,6 +988,24 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) switch (op->common.aml_opcode) { #ifndef ACPI_NO_METHOD_EXECUTION case AML_REGION_OP: + + /* + * If we are executing a method, initialize the region + */ + if (walk_state->method_node) { + status = + acpi_ex_create_region(op->named.data, + op->named.length, + (acpi_adr_space_type) + ((op->common.value. + arg)->common.value. + integer), + walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + } + /* * The op_region is not fully parsed at this time. Only valid * argument is the space_id. (We must save the address of the @@ -957,11 +1034,50 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) status = acpi_ds_create_node(walk_state, node, op); break; + + case AML_METHOD_OP: + /* + * method_op pkg_length name_string method_flags term_list + * + * Note: We must create the method node/object pair as soon as we + * see the method declaration. This allows later pass1 parsing + * of invocations of the method (need to know the number of + * arguments.) + */ + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "LOADING-Method: State=%p Op=%p named_obj=%p\n", + walk_state, op, op->named.node)); + + if (!acpi_ns_get_attached_object(op->named.node)) { + walk_state->operands[0] = + ACPI_CAST_PTR(void, op->named.node); + walk_state->num_operands = 1; + + status = + acpi_ds_create_operands(walk_state, + op->common.value. + arg); + if (ACPI_SUCCESS(status)) { + status = + acpi_ex_create_method(op->named. + data, + op->named. + length, + walk_state); + } + walk_state->operands[0] = NULL; + walk_state->num_operands = 0; + + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + break; + #endif /* ACPI_NO_METHOD_EXECUTION */ default: /* All NAMED_COMPLEX opcodes must be handled above */ - /* Note: Method objects were already created in Pass 1 */ break; } break; @@ -1004,7 +1120,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) */ op->common.node = new_node; } else { - ACPI_REPORT_NSERROR(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(arg->common.value.string, status); } break; diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index defe956ef751..ada21ef4a174 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -107,14 +107,14 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node, if (!node) { /* Invalid scope */ - ACPI_REPORT_ERROR(("ds_scope_stack_push: null scope passed\n")); + ACPI_ERROR((AE_INFO, "Null scope parameter")); return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Make sure object type is valid */ if (!acpi_ut_valid_object_type(type)) { - ACPI_REPORT_WARNING(("ds_scope_stack_push: Invalid object type: 0x%X\n", type)); + ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type)); } /* Allocate a new scope object */ diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 7d68a5aaf3c4..fa78cb74ee36 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,26 +92,23 @@ acpi_ds_result_remove(union acpi_operand_object **object, state = walk_state->results; if (!state) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No result object pushed! State=%p\n", - walk_state)); + ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", + walk_state)); return (AE_NOT_EXIST); } if (index >= ACPI_OBJ_MAX_OPERAND) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Index out of range: %X State=%p Num=%X\n", - index, walk_state, - state->results.num_results)); + ACPI_ERROR((AE_INFO, + "Index out of range: %X State=%p Num=%X", + index, walk_state, state->results.num_results)); } /* Check for a valid result object */ if (!state->results.obj_desc[index]) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null operand! State=%p #Ops=%X, Index=%X\n", - walk_state, state->results.num_results, - index)); + ACPI_ERROR((AE_INFO, + "Null operand! State=%p #Ops=%X, Index=%X", + walk_state, state->results.num_results, index)); return (AE_AML_NO_RETURN_VALUE); } @@ -163,9 +160,8 @@ acpi_ds_result_pop(union acpi_operand_object ** object, } if (!state->results.num_results) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Result stack is empty! State=%p\n", - walk_state)); + ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", + walk_state)); return (AE_AML_NO_RETURN_VALUE); } @@ -192,8 +188,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object, } } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No result objects! State=%p\n", walk_state)); + ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } @@ -222,15 +217,14 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, state = walk_state->results; if (!state) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Warning: No result object pushed! State=%p\n", - walk_state)); + ACPI_ERROR((AE_INFO, + "No result object pushed! State=%p", walk_state)); return (AE_NOT_EXIST); } if (!state->results.num_results) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No result objects! State=%p\n", walk_state)); + ACPI_ERROR((AE_INFO, "No result objects! State=%p", + walk_state)); return (AE_AML_NO_RETURN_VALUE); } @@ -250,10 +244,10 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, /* Check for a valid result object */ if (!*object) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null operand! State=%p #Ops=%X Index=%X\n", - walk_state, state->results.num_results, - (u32) index)); + ACPI_ERROR((AE_INFO, + "Null operand! State=%p #Ops=%X Index=%X", + walk_state, state->results.num_results, + (u32) index)); return (AE_AML_NO_RETURN_VALUE); } @@ -288,23 +282,21 @@ acpi_ds_result_push(union acpi_operand_object * object, state = walk_state->results; if (!state) { - ACPI_REPORT_ERROR(("No result stack frame during push\n")); + ACPI_ERROR((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Result stack overflow: Obj=%p State=%p Num=%X\n", - object, walk_state, - state->results.num_results)); + ACPI_ERROR((AE_INFO, + "Result stack overflow: Obj=%p State=%p Num=%X", + object, walk_state, state->results.num_results)); return (AE_STACK_OVERFLOW); } if (!object) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null Object! Obj=%p State=%p Num=%X\n", - object, walk_state, - state->results.num_results)); + ACPI_ERROR((AE_INFO, + "Null Object! Obj=%p State=%p Num=%X", + object, walk_state, state->results.num_results)); return (AE_BAD_PARAMETER); } @@ -413,10 +405,9 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) /* Check for stack overflow */ if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "overflow! Obj=%p State=%p #Ops=%X\n", - object, walk_state, - walk_state->num_operands)); + ACPI_ERROR((AE_INFO, + "Object stack overflow! Obj=%p State=%p #Ops=%X", + object, walk_state, walk_state->num_operands)); return (AE_STACK_OVERFLOW); } @@ -460,10 +451,10 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) /* Check for stack underflow */ if (walk_state->num_operands == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Underflow! Count=%X State=%p #Ops=%X\n", - pop_count, walk_state, - walk_state->num_operands)); + ACPI_ERROR((AE_INFO, + "Object stack underflow! Count=%X State=%p #Ops=%X", + pop_count, walk_state, + walk_state->num_operands)); return (AE_STACK_UNDERFLOW); } @@ -506,10 +497,10 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count, /* Check for stack underflow */ if (walk_state->num_operands == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Underflow! Count=%X State=%p #Ops=%X\n", - pop_count, walk_state, - walk_state->num_operands)); + ACPI_ERROR((AE_INFO, + "Object stack underflow! Count=%X State=%p #Ops=%X", + pop_count, walk_state, + walk_state->num_operands)); return (AE_STACK_UNDERFLOW); } @@ -826,16 +817,14 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) } if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%p is not a valid walk state\n", - walk_state)); + ACPI_ERROR((AE_INFO, "%p is not a valid walk state", + walk_state)); return; } if (walk_state->parser_state.scope) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%p walk still has a scope list\n", - walk_state)); + ACPI_ERROR((AE_INFO, "%p walk still has a scope list", + walk_state)); } /* Always must free any linked control states */ @@ -894,25 +883,24 @@ acpi_ds_result_insert(void *object, state = walk_state->results; if (!state) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No result object pushed! State=%p\n", - walk_state)); + ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", + walk_state)); return (AE_NOT_EXIST); } if (index >= ACPI_OBJ_NUM_OPERANDS) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Index out of range: %X Obj=%p State=%p Num=%X\n", - index, object, walk_state, - state->results.num_results)); + ACPI_ERROR((AE_INFO, + "Index out of range: %X Obj=%p State=%p Num=%X", + index, object, walk_state, + state->results.num_results)); return (AE_BAD_PARAMETER); } if (!object) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null Object! Index=%X Obj=%p State=%p Num=%X\n", - index, object, walk_state, - state->results.num_results)); + ACPI_ERROR((AE_INFO, + "Null Object! Index=%X Obj=%p State=%p Num=%X", + index, object, walk_state, + state->results.num_results)); return (AE_BAD_PARAMETER); } @@ -986,9 +974,9 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, /* Check for stack underflow */ if (walk_state->num_operands == 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Missing operand/stack empty! State=%p #Ops=%X\n", - walk_state, walk_state->num_operands)); + ACPI_ERROR((AE_INFO, + "Missing operand/stack empty! State=%p #Ops=%X", + walk_state, walk_state->num_operands)); *object = NULL; return (AE_AML_NO_OPERAND); } @@ -1000,9 +988,9 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, /* Check for a valid operand */ if (!walk_state->operands[walk_state->num_operands]) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null operand! State=%p #Ops=%X\n", - walk_state, walk_state->num_operands)); + ACPI_ERROR((AE_INFO, + "Null operand! State=%p #Ops=%X", + walk_state, walk_state->num_operands)); *object = NULL; return (AE_AML_NO_OPERAND); } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3758b558d2b5..79b09d76c180 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -60,20 +60,20 @@ ACPI_MODULE_NAME("acpi_ec") #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 -#define EC_POLLING 0xFF -#define EC_BURST 0x00 +#define EC_POLL 0xFF +#define EC_INTR 0x00 static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_burst_add(struct acpi_device *device); -static int acpi_ec_polling_add(struct acpi_device *device); +static int acpi_ec_intr_add(struct acpi_device *device); +static int acpi_ec_poll_add(struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_polling_add, + .add = acpi_ec_intr_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, @@ -105,7 +105,7 @@ union acpi_ec { atomic_t pending_gpe; struct semaphore sem; wait_queue_head_t wait; - } burst; + } intr; struct { u32 mode; @@ -117,37 +117,37 @@ union acpi_ec { struct acpi_generic_address data_addr; unsigned long global_lock; spinlock_t lock; - } polling; + } poll; }; -static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event); -static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event); -static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data); -static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data); -static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data); -static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data); -static void acpi_ec_gpe_polling_query(void *ec_cxt); -static void acpi_ec_gpe_burst_query(void *ec_cxt); -static u32 acpi_ec_gpe_polling_handler(void *data); -static u32 acpi_ec_gpe_burst_handler(void *data); +static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event); +static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event); +static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data); +static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data); +static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data); +static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data); +static void acpi_ec_gpe_poll_query(void *ec_cxt); +static void acpi_ec_gpe_intr_query(void *ec_cxt); +static u32 acpi_ec_gpe_poll_handler(void *data); +static u32 acpi_ec_gpe_intr_handler(void *data); static acpi_status __init -acpi_fake_ecdt_polling_callback(acpi_handle handle, +acpi_fake_ecdt_poll_callback(acpi_handle handle, u32 Level, void *context, void **retval); static acpi_status __init -acpi_fake_ecdt_burst_callback(acpi_handle handle, +acpi_fake_ecdt_intr_callback(acpi_handle handle, u32 Level, void *context, void **retval); -static int __init acpi_ec_polling_get_real_ecdt(void); -static int __init acpi_ec_burst_get_real_ecdt(void); +static int __init acpi_ec_poll_get_real_ecdt(void); +static int __init acpi_ec_intr_get_real_ecdt(void); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ static union acpi_ec *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; -static int acpi_ec_polling_mode = EC_POLLING; +static int acpi_ec_poll_mode = EC_INTR; /* -------------------------------------------------------------------------- Transaction Management @@ -163,13 +163,13 @@ static u32 acpi_ec_read_status(union acpi_ec *ec) static int acpi_ec_wait(union acpi_ec *ec, u8 event) { - if (acpi_ec_polling_mode) - return acpi_ec_polling_wait(ec, event); + if (acpi_ec_poll_mode) + return acpi_ec_poll_wait(ec, event); else - return acpi_ec_burst_wait(ec, event); + return acpi_ec_intr_wait(ec, event); } -static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event) +static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event) { u32 acpi_ec_status = 0; u32 i = ACPI_EC_UDELAY_COUNT; @@ -203,36 +203,31 @@ static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event) return -ETIME; } -static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) +static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event) { int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_wait"); - ec->burst.expect_event = event; + ec->intr.expect_event = event; smp_mb(); switch (event) { - case ACPI_EC_EVENT_OBF: - if (acpi_ec_read_status(ec) & event) { - ec->burst.expect_event = 0; - return_VALUE(0); - } - break; - case ACPI_EC_EVENT_IBE: if (~acpi_ec_read_status(ec) & event) { - ec->burst.expect_event = 0; + ec->intr.expect_event = 0; return_VALUE(0); } break; + default: + break; } - result = wait_event_timeout(ec->burst.wait, - !ec->burst.expect_event, + result = wait_event_timeout(ec->intr.wait, + !ec->intr.expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - ec->burst.expect_event = 0; + ec->intr.expect_event = 0; smp_mb(); /* @@ -255,7 +250,12 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) return_VALUE(-ETIME); } -static int acpi_ec_enter_burst_mode(union acpi_ec *ec) +#ifdef ACPI_FUTURE_USAGE +/* + * Note: samsung nv5000 doesn't work with ec burst mode. + * http://bugzilla.kernel.org/show_bug.cgi?id=4980 + */ +int acpi_ec_enter_burst_mode(union acpi_ec *ec) { u32 tmp = 0; int status = 0; @@ -270,45 +270,56 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec) acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) - return_VALUE(-EINVAL); acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); if (tmp != 0x90) { /* Burst ACK byte */ return_VALUE(-EINVAL); } } - atomic_set(&ec->burst.leaving_burst, 0); + atomic_set(&ec->intr.leaving_burst, 0); return_VALUE(0); end: - printk("Error in acpi_ec_wait\n"); + printk(KERN_WARNING PREFIX "Error in acpi_ec_wait\n"); return_VALUE(-1); } -static int acpi_ec_leave_burst_mode(union acpi_ec *ec) +int acpi_ec_leave_burst_mode(union acpi_ec *ec) { + int status = 0; ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); - atomic_set(&ec->burst.leaving_burst, 1); + status = acpi_ec_read_status(ec); + if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ + status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); + if(status) + goto end; + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); + acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); + } + atomic_set(&ec->intr.leaving_burst, 1); return_VALUE(0); +end: + printk(KERN_WARNING PREFIX "leave burst_mode:error\n"); + return_VALUE(-1); } +#endif /* ACPI_FUTURE_USAGE */ static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data) { - if (acpi_ec_polling_mode) - return acpi_ec_polling_read(ec, address, data); + if (acpi_ec_poll_mode) + return acpi_ec_poll_read(ec, address, data); else - return acpi_ec_burst_read(ec, address, data); + return acpi_ec_intr_read(ec, address, data); } static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data) { - if (acpi_ec_polling_mode) - return acpi_ec_polling_write(ec, address, data); + if (acpi_ec_poll_mode) + return acpi_ec_poll_write(ec, address, data); else - return acpi_ec_burst_write(ec, address, data); + return acpi_ec_intr_write(ec, address, data); } -static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) { acpi_status status = AE_OK; int result = 0; @@ -328,7 +339,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data) return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->polling.lock, flags); + spin_lock_irqsave(&ec->poll.lock, flags); acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); @@ -347,7 +358,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data) *data, address)); end: - spin_unlock_irqrestore(&ec->polling.lock, flags); + spin_unlock_irqrestore(&ec->poll.lock, flags); if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -355,7 +366,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data) return_VALUE(result); } -static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data) +static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) { int result = 0; acpi_status status = AE_OK; @@ -373,7 +384,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data) return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->polling.lock, flags); + spin_lock_irqsave(&ec->poll.lock, flags); acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); @@ -395,7 +406,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data) data, address)); end: - spin_unlock_irqrestore(&ec->polling.lock, flags); + spin_unlock_irqrestore(&ec->poll.lock, flags); if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -403,7 +414,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data) return_VALUE(result); } -static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) +static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data) { int status = 0; u32 glk; @@ -422,25 +433,24 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) } WARN_ON(in_interrupt()); - down(&ec->burst.sem); + down(&ec->intr.sem); - acpi_ec_enter_burst_mode(ec); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("read EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); goto end; } acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("read EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); } acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) { - printk("read EC, OB not full\n"); + printk(KERN_DEBUG PREFIX "read EC, OB not full\n"); goto end; } acpi_hw_low_level_read(8, data, &ec->common.data_addr); @@ -448,8 +458,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) *data, address)); end: - acpi_ec_leave_burst_mode(ec); - up(&ec->burst.sem); + up(&ec->intr.sem); if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -457,7 +466,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) return_VALUE(status); } -static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) +static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data) { int status = 0; u32 glk; @@ -474,25 +483,23 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) } WARN_ON(in_interrupt()); - down(&ec->burst.sem); - - acpi_ec_enter_burst_mode(ec); + down(&ec->intr.sem); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("write EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); } acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("write EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); } acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("write EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); } acpi_hw_low_level_write(8, data, &ec->common.data_addr); @@ -500,8 +507,7 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", data, address)); - acpi_ec_leave_burst_mode(ec); - up(&ec->burst.sem); + up(&ec->intr.sem); if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -553,12 +559,12 @@ EXPORT_SYMBOL(ec_write); static int acpi_ec_query(union acpi_ec *ec, u32 * data) { - if (acpi_ec_polling_mode) - return acpi_ec_polling_query(ec, data); + if (acpi_ec_poll_mode) + return acpi_ec_poll_query(ec, data); else - return acpi_ec_burst_query(ec, data); + return acpi_ec_intr_query(ec, data); } -static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data) +static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) { int result = 0; acpi_status status = AE_OK; @@ -583,7 +589,7 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data) * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - spin_lock_irqsave(&ec->polling.lock, flags); + spin_lock_irqsave(&ec->poll.lock, flags); acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); @@ -596,14 +602,14 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data) result = -ENODATA; end: - spin_unlock_irqrestore(&ec->polling.lock, flags); + spin_unlock_irqrestore(&ec->poll.lock, flags); if (ec->common.global_lock) acpi_release_global_lock(glk); return_VALUE(result); } -static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) +static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data) { int status = 0; u32 glk; @@ -620,11 +626,11 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) return_VALUE(-ENODEV); } - down(&ec->burst.sem); + down(&ec->intr.sem); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - printk("query EC, IB not empty\n"); + printk(KERN_DEBUG PREFIX "query EC, IB not empty\n"); goto end; } /* @@ -636,7 +642,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) { - printk("query EC, OB not full\n"); + printk(KERN_DEBUG PREFIX "query EC, OB not full\n"); goto end; } @@ -645,7 +651,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) status = -ENODATA; end: - up(&ec->burst.sem); + up(&ec->intr.sem); if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -664,13 +670,13 @@ union acpi_ec_query_data { static void acpi_ec_gpe_query(void *ec_cxt) { - if (acpi_ec_polling_mode) - acpi_ec_gpe_polling_query(ec_cxt); + if (acpi_ec_poll_mode) + acpi_ec_gpe_poll_query(ec_cxt); else - acpi_ec_gpe_burst_query(ec_cxt); + acpi_ec_gpe_intr_query(ec_cxt); } -static void acpi_ec_gpe_polling_query(void *ec_cxt) +static void acpi_ec_gpe_poll_query(void *ec_cxt) { union acpi_ec *ec = (union acpi_ec *)ec_cxt; u32 value = 0; @@ -685,9 +691,9 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt) if (!ec_cxt) goto end; - spin_lock_irqsave(&ec->polling.lock, flags); + spin_lock_irqsave(&ec->poll.lock, flags); acpi_hw_low_level_read(8, &value, &ec->common.command_addr); - spin_unlock_irqrestore(&ec->polling.lock, flags); + spin_unlock_irqrestore(&ec->poll.lock, flags); /* TBD: Implement asynch events! * NOTE: All we care about are EC-SCI's. Other EC events are @@ -711,7 +717,7 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt) end: acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); } -static void acpi_ec_gpe_burst_query(void *ec_cxt) +static void acpi_ec_gpe_intr_query(void *ec_cxt) { union acpi_ec *ec = (union acpi_ec *)ec_cxt; u32 value; @@ -736,18 +742,18 @@ static void acpi_ec_gpe_burst_query(void *ec_cxt) acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - atomic_dec(&ec->burst.pending_gpe); + atomic_dec(&ec->intr.pending_gpe); return; } static u32 acpi_ec_gpe_handler(void *data) { - if (acpi_ec_polling_mode) - return acpi_ec_gpe_polling_handler(data); + if (acpi_ec_poll_mode) + return acpi_ec_gpe_poll_handler(data); else - return acpi_ec_gpe_burst_handler(data); + return acpi_ec_gpe_intr_handler(data); } -static u32 acpi_ec_gpe_polling_handler(void *data) +static u32 acpi_ec_gpe_poll_handler(void *data) { acpi_status status = AE_OK; union acpi_ec *ec = (union acpi_ec *)data; @@ -765,7 +771,7 @@ static u32 acpi_ec_gpe_polling_handler(void *data) else return ACPI_INTERRUPT_NOT_HANDLED; } -static u32 acpi_ec_gpe_burst_handler(void *data) +static u32 acpi_ec_gpe_intr_handler(void *data) { acpi_status status = AE_OK; u32 value; @@ -777,22 +783,22 @@ static u32 acpi_ec_gpe_burst_handler(void *data) acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); - switch (ec->burst.expect_event) { + switch (ec->intr.expect_event) { case ACPI_EC_EVENT_OBF: if (!(value & ACPI_EC_FLAG_OBF)) break; case ACPI_EC_EVENT_IBE: if ((value & ACPI_EC_FLAG_IBF)) break; - ec->burst.expect_event = 0; - wake_up(&ec->burst.wait); + ec->intr.expect_event = 0; + wake_up(&ec->intr.wait); return ACPI_INTERRUPT_HANDLED; default: break; } if (value & ACPI_EC_FLAG_SCI) { - atomic_add(1, &ec->burst.pending_gpe); + atomic_add(1, &ec->intr.pending_gpe); status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_ec_gpe_query, ec); return status == AE_OK ? @@ -980,7 +986,7 @@ static int acpi_ec_remove_fs(struct acpi_device *device) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_ec_polling_add(struct acpi_device *device) +static int acpi_ec_poll_add(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; @@ -999,7 +1005,7 @@ static int acpi_ec_polling_add(struct acpi_device *device) ec->common.handle = device->handle; ec->common.uid = -1; - spin_lock_init(&ec->polling.lock); + spin_lock_init(&ec->poll.lock); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; @@ -1038,7 +1044,7 @@ static int acpi_ec_polling_add(struct acpi_device *device) if (result) goto end; - printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n", acpi_device_name(device), acpi_device_bid(device), (u32) ec->common.gpe_bit); @@ -1051,7 +1057,7 @@ static int acpi_ec_polling_add(struct acpi_device *device) return_VALUE(result); } -static int acpi_ec_burst_add(struct acpi_device *device) +static int acpi_ec_intr_add(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; @@ -1070,10 +1076,10 @@ static int acpi_ec_burst_add(struct acpi_device *device) ec->common.handle = device->handle; ec->common.uid = -1; - atomic_set(&ec->burst.pending_gpe, 0); - atomic_set(&ec->burst.leaving_burst, 1); - init_MUTEX(&ec->burst.sem); - init_waitqueue_head(&ec->burst.wait); + atomic_set(&ec->intr.pending_gpe, 0); + atomic_set(&ec->intr.leaving_burst, 1); + init_MUTEX(&ec->intr.sem); + init_waitqueue_head(&ec->intr.wait); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; @@ -1112,8 +1118,7 @@ static int acpi_ec_burst_add(struct acpi_device *device) if (result) goto end; - printk("burst-mode-ec-10-Aug\n"); - printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n", acpi_device_name(device), acpi_device_bid(device), (u32) ec->common.gpe_bit); @@ -1151,7 +1156,7 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context) union acpi_ec *ec = (union acpi_ec *)context; struct acpi_generic_address *addr; - if (resource->id != ACPI_RSTYPE_IO) { + if (resource->type != ACPI_RESOURCE_TYPE_IO) { return AE_OK; } @@ -1171,7 +1176,7 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context) addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; addr->register_bit_width = 8; addr->register_bit_offset = 0; - addr->address = resource->data.io.min_base_address; + addr->address = resource->data.io.minimum; return AE_OK; } @@ -1267,16 +1272,16 @@ acpi_fake_ecdt_callback(acpi_handle handle, u32 Level, void *context, void **retval) { - if (acpi_ec_polling_mode) - return acpi_fake_ecdt_polling_callback(handle, + if (acpi_ec_poll_mode) + return acpi_fake_ecdt_poll_callback(handle, Level, context, retval); else - return acpi_fake_ecdt_burst_callback(handle, + return acpi_fake_ecdt_intr_callback(handle, Level, context, retval); } static acpi_status __init -acpi_fake_ecdt_polling_callback(acpi_handle handle, +acpi_fake_ecdt_poll_callback(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; @@ -1295,7 +1300,7 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle, &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - spin_lock_init(&ec_ecdt->polling.lock); + spin_lock_init(&ec_ecdt->poll.lock); ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.handle = handle; @@ -1308,13 +1313,13 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle, } static acpi_status __init -acpi_fake_ecdt_burst_callback(acpi_handle handle, +acpi_fake_ecdt_intr_callback(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; - init_MUTEX(&ec_ecdt->burst.sem); - init_waitqueue_head(&ec_ecdt->burst.wait); + init_MUTEX(&ec_ecdt->intr.sem); + init_waitqueue_head(&ec_ecdt->intr.wait); status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) @@ -1380,13 +1385,13 @@ static int __init acpi_ec_fake_ecdt(void) static int __init acpi_ec_get_real_ecdt(void) { - if (acpi_ec_polling_mode) - return acpi_ec_polling_get_real_ecdt(); + if (acpi_ec_poll_mode) + return acpi_ec_poll_get_real_ecdt(); else - return acpi_ec_burst_get_real_ecdt(); + return acpi_ec_intr_get_real_ecdt(); } -static int __init acpi_ec_polling_get_real_ecdt(void) +static int __init acpi_ec_poll_get_real_ecdt(void) { acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1411,7 +1416,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void) ec_ecdt->common.status_addr = ecdt_ptr->ec_control; ec_ecdt->common.data_addr = ecdt_ptr->ec_data; ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; - spin_lock_init(&ec_ecdt->polling.lock); + spin_lock_init(&ec_ecdt->poll.lock); /* use the GL just to be safe */ ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.uid = ecdt_ptr->uid; @@ -1431,7 +1436,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void) return -ENODEV; } -static int __init acpi_ec_burst_get_real_ecdt(void) +static int __init acpi_ec_intr_get_real_ecdt(void) { acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1452,8 +1457,8 @@ static int __init acpi_ec_burst_get_real_ecdt(void) return -ENOMEM; memset(ec_ecdt, 0, sizeof(union acpi_ec)); - init_MUTEX(&ec_ecdt->burst.sem); - init_waitqueue_head(&ec_ecdt->burst.wait); + init_MUTEX(&ec_ecdt->intr.sem); + init_waitqueue_head(&ec_ecdt->intr.wait); ec_ecdt->common.command_addr = ecdt_ptr->ec_control; ec_ecdt->common.status_addr = ecdt_ptr->ec_control; ec_ecdt->common.data_addr = ecdt_ptr->ec_data; @@ -1571,22 +1576,22 @@ static int __init acpi_fake_ecdt_setup(char *str) } __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); -static int __init acpi_ec_set_polling_mode(char *str) +static int __init acpi_ec_set_intr_mode(char *str) { - int burst; + int intr; - if (!get_option(&str, &burst)) + if (!get_option(&str, &intr)) return 0; - if (burst) { - acpi_ec_polling_mode = EC_BURST; - acpi_ec_driver.ops.add = acpi_ec_burst_add; + if (intr) { + acpi_ec_poll_mode = EC_INTR; + acpi_ec_driver.ops.add = acpi_ec_intr_add; } else { - acpi_ec_polling_mode = EC_POLLING; - acpi_ec_driver.ops.add = acpi_ec_polling_add; + acpi_ec_poll_mode = EC_POLL; + acpi_ec_driver.ops.add = acpi_ec_poll_add; } - printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling"); + printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling"); return 0; } -__setup("ec_burst=", acpi_ec_set_polling_mode); +__setup("ec_intr=", acpi_ec_set_intr_mode); diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index 842d1e3fb37b..c9ac05c4685f 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,7 @@ acpi_status acpi_ev_initialize_events(void) /* Make sure we have ACPI tables */ if (!acpi_gbl_DSDT) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No ACPI tables present!\n")); + ACPI_WARNING((AE_INFO, "No ACPI tables present!")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -84,14 +84,15 @@ acpi_status acpi_ev_initialize_events(void) */ status = acpi_ev_fixed_event_initialize(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Unable to initialize fixed events, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize fixed events")); return_ACPI_STATUS(status); } status = acpi_ev_gpe_initialize(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Unable to initialize general purpose events, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize general purpose events")); return_ACPI_STATUS(status); } @@ -100,6 +101,48 @@ acpi_status acpi_ev_initialize_events(void) /******************************************************************************* * + * FUNCTION: acpi_ev_install_fadt_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks + * (0 and 1). This causes the _PRW methods to be run, so the HW + * must be fully initialized at this point, including global lock + * support. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_fadt_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE("ev_install_fadt_gpes"); + + /* Namespace must be locked */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* FADT GPE Block 0 */ + + (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, + acpi_gbl_gpe_fadt_blocks[0]); + + /* FADT GPE Block 1 */ + + (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, + acpi_gbl_gpe_fadt_blocks[1]); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ev_install_xrupt_handlers * * PARAMETERS: None @@ -120,7 +163,8 @@ acpi_status acpi_ev_install_xrupt_handlers(void) status = acpi_ev_install_sci_handler(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Unable to install System Control Interrupt Handler, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to install System Control Interrupt handler")); return_ACPI_STATUS(status); } @@ -128,7 +172,8 @@ acpi_status acpi_ev_install_xrupt_handlers(void) status = acpi_ev_init_global_lock_handler(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Unable to initialize Global Lock handler, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to initialize Global Lock handler")); return_ACPI_STATUS(status); } @@ -262,7 +307,9 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) enable_register_id, 0, ACPI_MTX_DO_NOT_LOCK); - ACPI_REPORT_ERROR(("No installed handler for fixed event [%08X]\n", event)); + ACPI_ERROR((AE_INFO, + "No installed handler for fixed event [%08X]", + event)); return (ACPI_INTERRUPT_NOT_HANDLED); } diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index b2f232df13d8..f64f977dd3d5 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -372,14 +372,14 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) { + acpi_status status; + struct acpi_gpe_block_info *gpe_block; + struct acpi_gpe_register_info *gpe_register_info; u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u8 enabled_status_byte; - struct acpi_gpe_register_info *gpe_register_info; u32 status_reg; u32 enable_reg; - u32 flags; - acpi_status status; - struct acpi_gpe_block_info *gpe_block; + acpi_cpu_flags flags; acpi_native_uint i; acpi_native_uint j; @@ -546,7 +546,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = acpi_ns_evaluate_by_handle(&info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception(status), acpi_ut_get_node_name(local_gpe_event_info.dispatch.method_node), gpe_number)); + ACPI_EXCEPTION((AE_INFO, status, + "While evaluating method [%4.4s] for GPE[%2X]", + acpi_ut_get_node_name + (local_gpe_event_info.dispatch. + method_node), gpe_number)); } } @@ -599,8 +603,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) ACPI_GPE_EDGE_TRIGGERED) { status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number)); - return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } } @@ -637,8 +643,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) ACPI_GPE_LEVEL_TRIGGERED) { status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n", acpi_format_exception(status), gpe_number)); - return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } } break; @@ -651,8 +659,10 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) */ status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number)); - return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to disable GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } /* @@ -663,7 +673,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) acpi_ev_asynch_execute_gpe_method, gpe_event_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n", acpi_format_exception(status), gpe_number)); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to queue handler for GPE[%2X] - event disabled", + gpe_number)); } break; @@ -671,7 +683,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) /* No handler or method to run! */ - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n", gpe_number)); + ACPI_ERROR((AE_INFO, + "No handler or method for GPE[%2X], disabling event", + gpe_number)); /* * Disable the GPE. The GPE will remain disabled until the ACPI @@ -679,13 +693,15 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) */ status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n", acpi_format_exception(status), gpe_number)); - return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); + ACPI_EXCEPTION((AE_INFO, status, + "Unable to disable GPE[%2X]", + gpe_number)); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); } break; } - return_VALUE(ACPI_INTERRUPT_HANDLED); + return_UINT32(ACPI_INTERRUPT_HANDLED); } #ifdef ACPI_GPE_NOTIFY_CHECK @@ -722,7 +738,9 @@ acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info) acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); - ACPI_REPORT_INFO(("GPE %p was updated from wake/run to wake-only\n", gpe_event_info)); + ACPI_INFO((AE_INFO, + "GPE %p was updated from wake/run to wake-only", + gpe_event_info)); /* This was a wake-only GPE */ diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index b312eb33c43e..0fd00b5ad650 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,7 +78,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block); * * RETURN: TRUE if the gpe_event is valid * - * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. + * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. * Should be called only when the GPE lists are semaphore locked * and not subject to change. * @@ -136,7 +136,7 @@ acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback) struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; acpi_status status = AE_OK; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("ev_walk_gpe_list"); @@ -264,7 +264,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, * 2) Edge/Level determination is based on the 2nd character * of the method name * - * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE + * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE * if a _PRW object is found that points to this GPE. */ switch (name[1]) { @@ -279,9 +279,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle, default: /* Unknown method type, just ignore it! */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown GPE method type: %s (name not of form _Lxx or _Exx)\n", - name)); + ACPI_ERROR((AE_INFO, + "Unknown GPE method type: %s (name not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -291,9 +291,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle, if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)\n", - name)); + ACPI_ERROR((AE_INFO, + "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -313,14 +313,14 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* * Now we can add this information to the gpe_event_info block - * for use during dispatch of this GPE. Default type is RUNTIME, although + * for use during dispatch of this GPE. Default type is RUNTIME, although * this may change when the _PRW methods are executed later. */ gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; - gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD | - ACPI_GPE_TYPE_RUNTIME); + gpe_event_info->flags = (u8) + (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *)obj_handle; @@ -341,11 +341,11 @@ acpi_ev_save_method_info(acpi_handle obj_handle, * * PARAMETERS: Callback from walk_namespace * - * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is + * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is * not aborted on a single _PRW failure. * * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a - * Device. Run the _PRW method. If present, extract the GPE + * Device. Run the _PRW method. If present, extract the GPE * number and mark the GPE as a WAKE GPE. * ******************************************************************************/ @@ -443,6 +443,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); + status = acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); if (ACPI_FAILURE(status)) { @@ -466,7 +467,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, * * RETURN: A GPE interrupt block * - * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt + * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt * block per unique interrupt level used for GPEs. * Should be called only when the GPE lists are semaphore locked * and not subject to change. @@ -479,7 +480,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 struct acpi_gpe_xrupt_info *next_gpe_xrupt; struct acpi_gpe_xrupt_info *gpe_xrupt; acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block"); @@ -526,9 +527,9 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 acpi_ev_gpe_xrupt_handler, gpe_xrupt); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not install GPE interrupt handler at level 0x%X\n", - interrupt_number)); + ACPI_ERROR((AE_INFO, + "Could not install GPE interrupt handler at level 0x%X", + interrupt_number)); return_PTR(NULL); } } @@ -553,7 +554,7 @@ static acpi_status acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) { acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt"); @@ -566,8 +567,9 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) /* Disable this interrupt */ - status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number, - acpi_ev_gpe_xrupt_handler); + status = + acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number, + acpi_ev_gpe_xrupt_handler); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -610,7 +612,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_block; acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("ev_install_gpe_block"); @@ -663,7 +665,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) { acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("ev_install_gpe_block"); @@ -743,22 +745,22 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) sizeof(struct acpi_gpe_register_info)); if (!gpe_register_info) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not allocate the gpe_register_info table\n")); + ACPI_ERROR((AE_INFO, + "Could not allocate the gpe_register_info table")); return_ACPI_STATUS(AE_NO_MEMORY); } /* * Allocate the GPE event_info block. There are eight distinct GPEs - * per register. Initialization to zeros is sufficient. + * per register. Initialization to zeros is sufficient. */ gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block-> register_count * ACPI_GPE_REGISTER_WIDTH) * sizeof(struct acpi_gpe_event_info)); if (!gpe_event_info) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not allocate the gpe_event_info table\n")); + ACPI_ERROR((AE_INFO, + "Could not allocate the gpe_event_info table")); status = AE_NO_MEMORY; goto error_exit; } @@ -769,9 +771,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) gpe_block->event_info = gpe_event_info; /* - * Initialize the GPE Register and Event structures. A goal of these + * Initialize the GPE Register and Event structures. A goal of these * tables is to hide the fact that there are two separate GPE register sets - * in a given gpe hardware block, the status registers occupy the first half, + * in a given GPE hardware block, the status registers occupy the first half, * and the enable registers occupy the second half. */ this_register = gpe_register_info; @@ -812,11 +814,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) this_event++; } - /* - * Clear the status/enable registers. Note that status registers - * are cleared by writing a '1', while enable registers are cleared - * by writing a '0'. - */ + /* Disable all GPEs within this register */ + status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00, &this_register-> enable_address); @@ -824,6 +823,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) goto error_exit; } + /* Clear any pending GPE events within this register */ + status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF, &this_register-> status_address); @@ -860,7 +861,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) * * RETURN: Status * - * DESCRIPTION: Create and Install a block of GPE registers + * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within + * the block are disabled at exit. + * Note: Assumes namespace is locked. * ******************************************************************************/ @@ -872,14 +875,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block) { - struct acpi_gpe_block_info *gpe_block; - struct acpi_gpe_event_info *gpe_event_info; - acpi_native_uint i; - acpi_native_uint j; - u32 wake_gpe_count; - u32 gpe_enabled_count; acpi_status status; - struct acpi_gpe_walk_info gpe_info; + struct acpi_gpe_block_info *gpe_block; ACPI_FUNCTION_TRACE("ev_create_gpe_block"); @@ -896,22 +893,24 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, /* Initialize the new GPE block */ + gpe_block->node = gpe_device; gpe_block->register_count = register_count; gpe_block->block_base_number = gpe_block_base_number; - gpe_block->node = gpe_device; ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, sizeof(struct acpi_generic_address)); - /* Create the register_info and event_info sub-structures */ - + /* + * Create the register_info and event_info sub-structures + * Note: disables and clears all GPEs in the block + */ status = acpi_ev_create_gpe_info_blocks(gpe_block); if (ACPI_FAILURE(status)) { ACPI_MEM_FREE(gpe_block); return_ACPI_STATUS(status); } - /* Install the new block in the global list(s) */ + /* Install the new block in the global lists */ status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { @@ -926,16 +925,70 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, acpi_ev_save_method_info, gpe_block, NULL); + /* Return the new block */ + + if (return_gpe_block) { + (*return_gpe_block) = gpe_block; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", + (u32) gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * + ACPI_GPE_REGISTER_WIDTH) - 1)), + gpe_device->name.ascii, gpe_block->register_count, + interrupt_number)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_gpe_block + * + * PARAMETERS: gpe_device - Handle to the parent GPE block + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Initialize and enable a GPE block. First find and run any + * _PRT methods associated with the block, then enable the + * appropriate GPEs. + * Note: Assumes namespace is locked. + * + ******************************************************************************/ + +acpi_status +acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, + struct acpi_gpe_block_info *gpe_block) +{ + acpi_status status; + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_gpe_walk_info gpe_info; + u32 wake_gpe_count; + u32 gpe_enabled_count; + acpi_native_uint i; + acpi_native_uint j; + + ACPI_FUNCTION_TRACE("ev_initialize_gpe_block"); + + /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ + + if (!gpe_block) { + return_ACPI_STATUS(AE_OK); + } + /* - * Runtime option: Should Wake GPEs be enabled at runtime? The default - * is No, they should only be enabled just as the machine goes to sleep. + * Runtime option: Should wake GPEs be enabled at runtime? The default + * is no, they should only be enabled just as the machine goes to sleep. */ if (acpi_gbl_leave_wake_gpes_disabled) { /* - * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. - * (Each GPE that has one or more _PRWs that reference it is by - * definition a WAKE GPE and will not be enabled while the machine - * is running.) + * Differentiate runtime vs wake GPEs, via the _PRW control methods. + * Each GPE that has one or more _PRWs that reference it is by + * definition a wake GPE and will not be enabled while the machine + * is running. */ gpe_info.gpe_block = gpe_block; gpe_info.gpe_device = gpe_device; @@ -948,9 +1001,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, } /* - * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs, - * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must - * be enabled via the acpi_enable_gpe() external interface. + * Enable all GPEs in this block that have these attributes: + * 1) are "runtime" or "run/wake" GPEs, and + * 2) have a corresponding _Lxx or _Exx method + * + * Any other GPEs within this block must be enabled via the acpi_enable_gpe() + * external interface. */ wake_gpe_count = 0; gpe_enabled_count = 0; @@ -976,32 +1032,19 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, } } - /* Dump info about this GPE block */ - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", - (u32) gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * - ACPI_GPE_REGISTER_WIDTH) - 1)), - gpe_device->name.ascii, gpe_block->register_count, - interrupt_number)); - - /* Enable all valid GPEs found above */ - - status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block); - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Found %u Wake, Enabled %u Runtime GPEs in this block\n", wake_gpe_count, gpe_enabled_count)); - /* Return the new block */ + /* Enable all valid runtime GPEs found above */ - if (return_gpe_block) { - (*return_gpe_block) = gpe_block; + status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p", + gpe_block)); } - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -1072,8 +1115,8 @@ acpi_status acpi_ev_gpe_initialize(void) &acpi_gbl_gpe_fadt_blocks[0]); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not create GPE Block 0")); } } @@ -1086,7 +1129,12 @@ acpi_status acpi_ev_gpe_initialize(void) if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) { - ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1))); + ACPI_ERROR((AE_INFO, + "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", + gpe_number_max, acpi_gbl_FADT->gpe1_base, + acpi_gbl_FADT->gpe1_base + + ((register_count1 * + ACPI_GPE_REGISTER_WIDTH) - 1))); /* Ignore GPE1 block by setting the register count to zero */ @@ -1104,7 +1152,8 @@ acpi_status acpi_ev_gpe_initialize(void) [1]); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not create GPE Block 1")); } /* @@ -1130,7 +1179,9 @@ acpi_status acpi_ev_gpe_initialize(void) /* Check for Max GPE number out-of-range */ if (gpe_number_max > ACPI_GPE_MAX) { - ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max)); + ACPI_ERROR((AE_INFO, + "Maximum GPE number from FADT is too large: 0x%X", + gpe_number_max)); status = AE_BAD_VALUE; goto cleanup; } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 7e57b8470f55..0909ba69577e 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -303,7 +303,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context) acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, acpi_gbl_global_lock_thread_count); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not signal Global Lock semaphore\n")); + ACPI_ERROR((AE_INFO, + "Could not signal Global Lock semaphore")); } } } @@ -344,7 +345,8 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_ev_global_lock_thread, context); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not queue Global Lock thread, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not queue Global Lock thread")); return (ACPI_INTERRUPT_NOT_HANDLED); } @@ -384,7 +386,8 @@ acpi_status acpi_ev_init_global_lock_handler(void) * with an error. */ if (status == AE_NO_HARDWARE_RESPONSE) { - ACPI_REPORT_ERROR(("No response from Global Lock hardware, disabling lock\n")); + ACPI_ERROR((AE_INFO, + "No response from Global Lock hardware, disabling lock")); acpi_gbl_global_lock_present = FALSE; status = AE_OK; @@ -480,7 +483,8 @@ acpi_status acpi_ev_release_global_lock(void) ACPI_FUNCTION_TRACE("ev_release_global_lock"); if (!acpi_gbl_global_lock_thread_count) { - ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n")); + ACPI_WARNING((AE_INFO, + "Cannot release HW Global Lock, it has not been acquired")); return_ACPI_STATUS(AE_NOT_ACQUIRED); } @@ -542,9 +546,9 @@ void acpi_ev_terminate(void) for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { status = acpi_disable_event((u32) i, 0); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not disable fixed event %d\n", - (u32) i)); + ACPI_ERROR((AE_INFO, + "Could not disable fixed event %d", + (u32) i)); } } @@ -556,8 +560,7 @@ void acpi_ev_terminate(void) status = acpi_ev_remove_sci_handler(); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not remove SCI handler\n")); + ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); } } @@ -570,8 +573,7 @@ void acpi_ev_terminate(void) if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { status = acpi_disable(); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "acpi_disable failed\n")); + ACPI_WARNING((AE_INFO, "acpi_disable failed")); } } return_VOID; diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 84fad082d80d..6da58e776413 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -295,12 +295,12 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, handler_desc = region_obj->region.handler; if (!handler_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No handler for Region [%4.4s] (%p) [%s]\n", - acpi_ut_get_node_name(region_obj->region. - node), region_obj, - acpi_ut_get_region_name(region_obj->region. - space_id))); + ACPI_ERROR((AE_INFO, + "No handler for Region [%4.4s] (%p) [%s]", + acpi_ut_get_node_name(region_obj->region.node), + region_obj, + acpi_ut_get_region_name(region_obj->region. + space_id))); return_ACPI_STATUS(AE_NOT_EXIST); } @@ -317,12 +317,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, if (!region_setup) { /* No initialization routine, exit with error */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No init routine for region(%p) [%s]\n", - region_obj, - acpi_ut_get_region_name(region_obj-> - region. - space_id))); + ACPI_ERROR((AE_INFO, + "No init routine for region(%p) [%s]", + region_obj, + acpi_ut_get_region_name(region_obj->region. + space_id))); return_ACPI_STATUS(AE_NOT_EXIST); } @@ -347,12 +346,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Check for failure of the Region Setup */ if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Region Init: %s [%s]\n", - acpi_format_exception(status), - acpi_ut_get_region_name(region_obj-> - region. - space_id))); + ACPI_EXCEPTION((AE_INFO, status, + "During region initialization: [%s]", + acpi_ut_get_region_name(region_obj-> + region. + space_id))); return_ACPI_STATUS(status); } @@ -406,10 +404,9 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, region_obj2->extra.region_context); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Handler for [%s] returned %s\n", - acpi_ut_get_region_name(region_obj->region. - space_id), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", + acpi_ut_get_region_name(region_obj->region. + space_id))); } if (! @@ -501,12 +498,10 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, status = acpi_ev_execute_reg_method(region_obj, 0); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%s from region _REG, [%s]\n", - acpi_format_exception(status), - acpi_ut_get_region_name - (region_obj->region. - space_id))); + ACPI_EXCEPTION((AE_INFO, status, + "from region _REG, [%s]", + acpi_ut_get_region_name + (region_obj->region.space_id))); } if (acpi_ns_is_locked) { @@ -528,12 +523,10 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, /* Init routine may fail, Just ignore errors */ if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%s from region init, [%s]\n", - acpi_format_exception(status), - acpi_ut_get_region_name - (region_obj->region. - space_id))); + ACPI_EXCEPTION((AE_INFO, status, + "from region init, [%s]", + acpi_ut_get_region_name + (region_obj->region.space_id))); } region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index a1bd2da27c45..baed8c1a1b9f 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -233,7 +233,11 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, */ status = AE_OK; } else { - ACPI_REPORT_ERROR(("Could not install pci_config handler for Root Bridge %4.4s, %s\n", acpi_ut_get_node_name(pci_root_node), acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, + status, + "Could not install pci_config handler for Root Bridge %4.4s", + acpi_ut_get_node_name + (pci_root_node))); } } break; diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c index 141835977002..9a622169008a 100644 --- a/drivers/acpi/events/evsci.c +++ b/drivers/acpi/events/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,7 +88,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_VALUE(interrupt_handled); + return_UINT32(interrupt_handled); } /******************************************************************************* @@ -121,7 +121,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_VALUE(interrupt_handled); + return_UINT32(interrupt_handled); } /****************************************************************************** diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 43b33d19cdf9..b38b39dde543 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -143,8 +143,8 @@ acpi_install_fixed_event_handler(u32 event, if (ACPI_SUCCESS(status)) status = acpi_enable_event(event, 0); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Could not enable fixed event.\n")); + ACPI_WARNING((AE_INFO, "Could not enable fixed event %X", + event)); /* Remove the handler */ @@ -204,10 +204,11 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) acpi_gbl_fixed_event_handlers[event].context = NULL; if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Could not write to fixed event enable register.\n")); + ACPI_WARNING((AE_INFO, + "Could not write to fixed event enable register %X", + event)); } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X.\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n", event)); } @@ -434,7 +435,7 @@ acpi_remove_notify_handler(acpi_handle device, if (device == ACPI_ROOT_OBJECT) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Removing notify handler for ROOT object.\n")); + "Removing notify handler for namespace root object\n")); if (((handler_type & ACPI_SYSTEM_NOTIFY) && !acpi_gbl_system_notify.handler) || @@ -562,7 +563,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, struct acpi_gpe_event_info *gpe_event_info; struct acpi_handler_info *handler; acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("acpi_install_gpe_handler"); @@ -653,7 +654,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, struct acpi_gpe_event_info *gpe_event_info; struct acpi_handler_info *handler; acpi_status status; - u32 flags; + acpi_cpu_flags flags; ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler"); diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 887ff9f28a0d..ec9ce8429f15 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,8 +70,7 @@ acpi_status acpi_enable(void) /* Make sure we have the FADT */ if (!acpi_gbl_FADT) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "No FADT information present!\n")); + ACPI_WARNING((AE_INFO, "No FADT information present!")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -83,7 +82,8 @@ acpi_status acpi_enable(void) status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not transition to ACPI mode.\n")); + ACPI_ERROR((AE_INFO, + "Could not transition to ACPI mode")); return_ACPI_STATUS(status); } @@ -113,8 +113,7 @@ acpi_status acpi_disable(void) ACPI_FUNCTION_TRACE("acpi_disable"); if (!acpi_gbl_FADT) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "No FADT information present!\n")); + ACPI_WARNING((AE_INFO, "No FADT information present!")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -127,8 +126,8 @@ acpi_status acpi_disable(void) status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not exit ACPI mode to legacy mode")); + ACPI_ERROR((AE_INFO, + "Could not exit ACPI mode to legacy mode")); return_ACPI_STATUS(status); } @@ -185,9 +184,9 @@ acpi_status acpi_enable_event(u32 event, u32 flags) } if (value != 1) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not enable %s event\n", - acpi_ut_get_event_name(event))); + ACPI_ERROR((AE_INFO, + "Could not enable %s event", + acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } @@ -384,9 +383,9 @@ acpi_status acpi_disable_event(u32 event, u32 flags) } if (value != 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not disable %s events\n", - acpi_ut_get_event_name(event))); + ACPI_ERROR((AE_INFO, + "Could not disable %s events", + acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } @@ -626,6 +625,13 @@ acpi_install_gpe_block(acpi_handle gpe_device, goto unlock_and_exit; } + /* Run the _PRW methods and enable the GPEs */ + + status = acpi_ev_initialize_gpe_block(node, gpe_block); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + /* Get the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index 6f28ea2db5ba..abf5caca9ae5 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 1ce365d651d8..a29782fe3ecf 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -413,9 +413,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, (!ACPI_STRNCMP(table_ptr->signature, acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", - table_ptr->signature)); + ACPI_ERROR((AE_INFO, + "Table has invalid signature [%4.4s], must be SSDT or PSDT", + table_ptr->signature)); status = AE_BAD_SIGNATURE; goto cleanup; } diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 04e5194989a6..e6d52e12d77a 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -504,18 +504,12 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, } /* - * Perform the conversion. + * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) */ - string_length--; - if (string_length > ACPI_MAX_STRING_CONVERSION) { /* ACPI limit */ - return_ACPI_STATUS(AE_AML_STRING_LIMIT); - } - - /* Create a new string object and string buffer */ - return_desc = - acpi_ut_create_string_object((acpi_size) string_length); + acpi_ut_create_string_object((acpi_size) + (string_length - 1)); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -647,7 +641,9 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: - ACPI_REPORT_ERROR(("Bad destination type during conversion: %X\n", destination_type)); + ACPI_ERROR((AE_INFO, + "Bad destination type during conversion: %X", + destination_type)); status = AE_AML_INTERNAL; break; } @@ -660,17 +656,13 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown Target type ID 0x%X Op %s dest_type %s\n", - GET_CURRENT_ARG_TYPE(walk_state->op_info-> - runtime_args), - walk_state->op_info->name, - acpi_ut_get_type_name(destination_type))); - - ACPI_REPORT_ERROR(("Bad Target Type (ARGI): %X\n", - GET_CURRENT_ARG_TYPE(walk_state->op_info-> - runtime_args))) - status = AE_AML_INTERNAL; + ACPI_ERROR((AE_INFO, + "Unknown Target type ID 0x%X aml_opcode %X dest_type %s", + GET_CURRENT_ARG_TYPE(walk_state->op_info-> + runtime_args), + walk_state->opcode, + acpi_ut_get_type_name(destination_type))); + status = AE_AML_INTERNAL; } /* diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 91c49188fb07..680575402835 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -300,8 +300,8 @@ acpi_ex_create_region(u8 * aml_start, */ if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && (region_space < ACPI_USER_REGION_BEGIN)) { - ACPI_REPORT_ERROR(("Invalid address_space type %X\n", - region_space)); + ACPI_ERROR((AE_INFO, "Invalid address_space type %X", + region_space)); return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index bc2fa996047e..a7cca8d4f855 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,20 +55,386 @@ ACPI_MODULE_NAME("exdump") */ #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* Local prototypes */ -#ifdef ACPI_FUTURE_USAGE static void acpi_ex_out_string(char *title, char *value); static void acpi_ex_out_pointer(char *title, void *value); -static void acpi_ex_out_integer(char *title, u32 value); - static void acpi_ex_out_address(char *title, acpi_physical_address value); -static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc); +static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc); static void -acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index); -#endif /* ACPI_FUTURE_USAGE */ +acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, + u32 level, u32 index); + +/******************************************************************************* + * + * Object Descriptor info tables + * + * Note: The first table entry must be an INIT opcode and must contain + * the table length (number of table entries) + * + ******************************************************************************/ + +static struct acpi_exdump_info acpi_ex_dump_integer[2] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_integer), NULL}, + {ACPI_EXD_UINT64, ACPI_EXD_OFFSET(integer.value), "Value"} +}; + +static struct acpi_exdump_info acpi_ex_dump_string[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_string), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(string.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(string.pointer), "Pointer"}, + {ACPI_EXD_STRING, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_buffer[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, + {ACPI_EXD_BUFFER, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_package[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"}, + {ACPI_EXD_PACKAGE, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_device[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), + "Device Notify"} +}; + +static struct acpi_exdump_info acpi_ex_dump_event[2] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_event), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.semaphore), "Semaphore"} +}; + +static struct acpi_exdump_info acpi_ex_dump_method[8] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.thread_count), "Thread Count"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(method.aml_length), "Aml Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"} +}; + +static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), + "Acquire Depth"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.semaphore), "Semaphore"} +}; + +static struct acpi_exdump_info acpi_ex_dump_region[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.space_id), "Space Id"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(region.flags), "Flags"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(region.address), "Address"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(region.length), "Length"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(region.next), "Next"} +}; + +static struct acpi_exdump_info acpi_ex_dump_power[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_power), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.system_level), + "System Level"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), + "Resource Order"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), + "Device Notify"} +}; + +static struct acpi_exdump_info acpi_ex_dump_processor[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.length), "Length"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} +}; + +static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), + "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), + "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} +}; + +static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer_field.buffer_obj), + "Buffer Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_region_field[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(bank_field.value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.region_obj), + "Region Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(bank_field.bank_obj), "Bank Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_bank_field), NULL}, + {ACPI_EXD_FIELD, 0, NULL}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(index_field.value), "Value"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.index_obj), + "Index Object"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} +}; + +static struct acpi_exdump_info acpi_ex_dump_reference[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(reference.offset), "Offset"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, + {ACPI_EXD_REFERENCE, 0, NULL} +}; + +static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_address_handler), + NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(address_space.space_id), "Space Id"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.next), "Next"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.region_list), + "Region List"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} +}; + +static struct acpi_exdump_info acpi_ex_dump_notify[3] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} +}; + +/* Miscellaneous tables */ + +static struct acpi_exdump_info acpi_ex_dump_common[4] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_common), NULL}, + {ACPI_EXD_TYPE, 0, NULL}, + {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(common.reference_count), + "Reference Count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common.flags), "Flags"} +}; + +static struct acpi_exdump_info acpi_ex_dump_field_common[7] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_field_common), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.field_flags), + "Field Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.access_byte_width), + "Access Byte Width"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.bit_length), + "Bit Length"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(common_field.start_field_bit_offset), + "Field Bit Offset"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(common_field.base_byte_offset), + "Base Byte Offset"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} +}; + +static struct acpi_exdump_info acpi_ex_dump_node[6] = { + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, + {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, + {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count), + "Reference Count"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, + {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} +}; + +/* Dispatch table, indexed by object type */ + +static struct acpi_exdump_info *acpi_ex_dump_info[] = { + NULL, + acpi_ex_dump_integer, + acpi_ex_dump_string, + acpi_ex_dump_buffer, + acpi_ex_dump_package, + NULL, + acpi_ex_dump_device, + acpi_ex_dump_event, + acpi_ex_dump_method, + acpi_ex_dump_mutex, + acpi_ex_dump_region, + acpi_ex_dump_power, + acpi_ex_dump_processor, + acpi_ex_dump_thermal, + acpi_ex_dump_buffer_field, + NULL, + NULL, + acpi_ex_dump_region_field, + acpi_ex_dump_bank_field, + acpi_ex_dump_index_field, + acpi_ex_dump_reference, + NULL, + NULL, + acpi_ex_dump_notify, + acpi_ex_dump_address_handler, + NULL, + NULL, + NULL +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ex_dump_object + * + * PARAMETERS: obj_desc - Descriptor to dump + * Info - Info table corresponding to this object + * type + * + * RETURN: None + * + * DESCRIPTION: Walk the info table for this object + * + ******************************************************************************/ + +static void +acpi_ex_dump_object(union acpi_operand_object *obj_desc, + struct acpi_exdump_info *info) +{ + u8 *target; + char *name; + u8 count; + + if (!info) { + acpi_os_printf + ("ex_dump_object: Display not implemented for object type %s\n", + acpi_ut_get_object_type_name(obj_desc)); + return; + } + + /* First table entry must contain the table length (# of table entries) */ + + count = info->offset; + + while (count) { + target = ACPI_ADD_PTR(u8, obj_desc, info->offset); + name = info->name; + + switch (info->opcode) { + case ACPI_EXD_INIT: + break; + + case ACPI_EXD_TYPE: + acpi_ex_out_string("Type", + acpi_ut_get_object_type_name + (obj_desc)); + break; + + case ACPI_EXD_UINT8: + + acpi_os_printf("%20s : %2.2X\n", name, *target); + break; + + case ACPI_EXD_UINT16: + + acpi_os_printf("%20s : %4.4X\n", name, + ACPI_GET16(target)); + break; + + case ACPI_EXD_UINT32: + + acpi_os_printf("%20s : %8.8X\n", name, + ACPI_GET32(target)); + break; + + case ACPI_EXD_UINT64: + + acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", + ACPI_FORMAT_UINT64(ACPI_GET64(target))); + break; + + case ACPI_EXD_POINTER: + + acpi_ex_out_pointer(name, + *ACPI_CAST_PTR(void *, target)); + break; + + case ACPI_EXD_ADDRESS: + + acpi_ex_out_address(name, + *ACPI_CAST_PTR + (acpi_physical_address, target)); + break; + + case ACPI_EXD_STRING: + + acpi_ut_print_string(obj_desc->string.pointer, + ACPI_UINT8_MAX); + acpi_os_printf("\n"); + break; + + case ACPI_EXD_BUFFER: + + ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, + obj_desc->buffer.length); + break; + + case ACPI_EXD_PACKAGE: + + /* Dump the package contents */ + + acpi_os_printf("\nPackage Contents:\n"); + acpi_ex_dump_package_obj(obj_desc, 0, 0); + break; + + case ACPI_EXD_FIELD: + + acpi_ex_dump_object(obj_desc, + acpi_ex_dump_field_common); + break; + + case ACPI_EXD_REFERENCE: + + acpi_ex_out_string("Opcode", + (acpi_ps_get_opcode_info + (obj_desc->reference.opcode))-> + name); + acpi_ex_dump_reference_obj(obj_desc); + break; + + default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", + info->opcode); + return; + } + + info++; + count--; + } +} /******************************************************************************* * @@ -214,7 +580,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_BUFFER: - acpi_os_printf("Buffer len %X @ %p \n", + acpi_os_printf("Buffer len %X @ %p\n", obj_desc->buffer.length, obj_desc->buffer.pointer); @@ -320,17 +686,17 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_BUFFER_FIELD: - acpi_os_printf("buffer_field: %X bits at byte %X bit %X of \n", + acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n", obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, obj_desc->buffer_field.start_field_bit_offset); if (!obj_desc->buffer_field.buffer_obj) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL* \n")); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); } else if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) != ACPI_TYPE_BUFFER) { - acpi_os_printf("*not a Buffer* \n"); + acpi_os_printf("*not a Buffer*\n"); } else { acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, depth + 1); @@ -441,7 +807,6 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, return; } -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_ex_out* functions @@ -465,11 +830,6 @@ static void acpi_ex_out_pointer(char *title, void *value) acpi_os_printf("%20s : %p\n", title, value); } -static void acpi_ex_out_integer(char *title, u32 value) -{ - acpi_os_printf("%20s : %.2X\n", title, value); -} - static void acpi_ex_out_address(char *title, acpi_physical_address value) { @@ -482,16 +842,16 @@ static void acpi_ex_out_address(char *title, acpi_physical_address value) /******************************************************************************* * - * FUNCTION: acpi_ex_dump_node + * FUNCTION: acpi_ex_dump_namespace_node * - * PARAMETERS: *Node - Descriptor to dump + * PARAMETERS: Node - Descriptor to dump * Flags - Force display if TRUE * * DESCRIPTION: Dumps the members of the given.Node * ******************************************************************************/ -void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags) +void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) { ACPI_FUNCTION_ENTRY(); @@ -506,19 +866,17 @@ void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags) acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); - acpi_ex_out_integer("Flags", node->flags); - acpi_ex_out_integer("Owner Id", node->owner_id); - acpi_ex_out_integer("Reference Count", node->reference_count); acpi_ex_out_pointer("Attached Object", acpi_ns_get_attached_object(node)); - acpi_ex_out_pointer("child_list", node->child); - acpi_ex_out_pointer("next_peer", node->peer); acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node)); + + acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), + acpi_ex_dump_node); } /******************************************************************************* * - * FUNCTION: acpi_ex_dump_reference + * FUNCTION: acpi_ex_dump_reference_obj * * PARAMETERS: Object - Descriptor to dump * @@ -526,14 +884,16 @@ void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags) * ******************************************************************************/ -static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc) +static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) { struct acpi_buffer ret_buf; acpi_status status; + ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; + if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { acpi_os_printf("Named Object %p ", obj_desc->reference.node); - ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_desc->reference.node, &ret_buf); @@ -551,9 +911,9 @@ static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc) /******************************************************************************* * - * FUNCTION: acpi_ex_dump_package + * FUNCTION: acpi_ex_dump_package_obj * - * PARAMETERS: Object - Descriptor to dump + * PARAMETERS: obj_desc - Descriptor to dump * Level - Indentation Level * Index - Package index for this object * @@ -562,7 +922,8 @@ static void acpi_ex_dump_reference(union acpi_operand_object *obj_desc) ******************************************************************************/ static void -acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index) +acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, + u32 level, u32 index) { u32 i; @@ -608,7 +969,8 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index) acpi_os_printf("[Buffer] Length %.2X = ", obj_desc->buffer.length); if (obj_desc->buffer.length) { - acpi_ut_dump_buffer((u8 *) obj_desc->buffer.pointer, + acpi_ut_dump_buffer(ACPI_CAST_PTR + (u8, obj_desc->buffer.pointer), obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT); } else { @@ -618,19 +980,19 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index) case ACPI_TYPE_PACKAGE: - acpi_os_printf("[Package] Contains %d Elements: \n", + acpi_os_printf("[Package] Contains %d Elements:\n", obj_desc->package.count); for (i = 0; i < obj_desc->package.count; i++) { - acpi_ex_dump_package(obj_desc->package.elements[i], - level + 1, i); + acpi_ex_dump_package_obj(obj_desc->package.elements[i], + level + 1, i); } break; case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf("[Object Reference] "); - acpi_ex_dump_reference(obj_desc); + acpi_ex_dump_reference_obj(obj_desc); break; default: @@ -645,7 +1007,7 @@ acpi_ex_dump_package(union acpi_operand_object *obj_desc, u32 level, u32 index) * * FUNCTION: acpi_ex_dump_object_descriptor * - * PARAMETERS: Object - Descriptor to dump + * PARAMETERS: obj_desc - Descriptor to dump * Flags - Force display if TRUE * * DESCRIPTION: Dumps the members of the object descriptor given. @@ -670,11 +1032,13 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { - acpi_ex_dump_node((struct acpi_namespace_node *)obj_desc, - flags); + acpi_ex_dump_namespace_node((struct acpi_namespace_node *) + obj_desc, flags); + acpi_os_printf("\nAttached Object (%p):\n", ((struct acpi_namespace_node *)obj_desc)-> object); + acpi_ex_dump_object_descriptor(((struct acpi_namespace_node *) obj_desc)->object, flags); return_VOID; @@ -687,233 +1051,18 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) return_VOID; } - /* Common Fields */ - - acpi_ex_out_string("Type", acpi_ut_get_object_type_name(obj_desc)); - acpi_ex_out_integer("Reference Count", - obj_desc->common.reference_count); - acpi_ex_out_integer("Flags", obj_desc->common.flags); - - /* Object-specific Fields */ - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_INTEGER: - - acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", - ACPI_FORMAT_UINT64(obj_desc->integer.value)); - break; - - case ACPI_TYPE_STRING: - - acpi_ex_out_integer("Length", obj_desc->string.length); - - acpi_os_printf("%20s : %p ", "Pointer", - obj_desc->string.pointer); - acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); - acpi_os_printf("\n"); - break; - - case ACPI_TYPE_BUFFER: - - acpi_ex_out_integer("Length", obj_desc->buffer.length); - acpi_ex_out_pointer("Pointer", obj_desc->buffer.pointer); - ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, - obj_desc->buffer.length); - break; - - case ACPI_TYPE_PACKAGE: - - acpi_ex_out_integer("Flags", obj_desc->package.flags); - acpi_ex_out_integer("Elements", obj_desc->package.count); - acpi_ex_out_pointer("Element List", obj_desc->package.elements); - - /* Dump the package contents */ - - acpi_os_printf("\nPackage Contents:\n"); - acpi_ex_dump_package(obj_desc, 0, 0); - break; - - case ACPI_TYPE_DEVICE: - - acpi_ex_out_pointer("Handler", obj_desc->device.handler); - acpi_ex_out_pointer("system_notify", - obj_desc->device.system_notify); - acpi_ex_out_pointer("device_notify", - obj_desc->device.device_notify); - break; - - case ACPI_TYPE_EVENT: - - acpi_ex_out_pointer("Semaphore", obj_desc->event.semaphore); - break; - - case ACPI_TYPE_METHOD: - - acpi_ex_out_integer("param_count", - obj_desc->method.param_count); - acpi_ex_out_integer("Concurrency", - obj_desc->method.concurrency); - acpi_ex_out_pointer("Semaphore", obj_desc->method.semaphore); - acpi_ex_out_integer("owner_id", obj_desc->method.owner_id); - acpi_ex_out_integer("aml_length", obj_desc->method.aml_length); - acpi_ex_out_pointer("aml_start", obj_desc->method.aml_start); - break; - - case ACPI_TYPE_MUTEX: - - acpi_ex_out_integer("sync_level", obj_desc->mutex.sync_level); - acpi_ex_out_pointer("owner_thread", - obj_desc->mutex.owner_thread); - acpi_ex_out_integer("acquire_depth", - obj_desc->mutex.acquisition_depth); - acpi_ex_out_pointer("Semaphore", obj_desc->mutex.semaphore); - break; - - case ACPI_TYPE_REGION: - - acpi_ex_out_integer("space_id", obj_desc->region.space_id); - acpi_ex_out_integer("Flags", obj_desc->region.flags); - acpi_ex_out_address("Address", obj_desc->region.address); - acpi_ex_out_integer("Length", obj_desc->region.length); - acpi_ex_out_pointer("Handler", obj_desc->region.handler); - acpi_ex_out_pointer("Next", obj_desc->region.next); - break; - - case ACPI_TYPE_POWER: - - acpi_ex_out_integer("system_level", - obj_desc->power_resource.system_level); - acpi_ex_out_integer("resource_order", - obj_desc->power_resource.resource_order); - acpi_ex_out_pointer("system_notify", - obj_desc->power_resource.system_notify); - acpi_ex_out_pointer("device_notify", - obj_desc->power_resource.device_notify); - break; - - case ACPI_TYPE_PROCESSOR: - - acpi_ex_out_integer("Processor ID", - obj_desc->processor.proc_id); - acpi_ex_out_integer("Length", obj_desc->processor.length); - acpi_ex_out_address("Address", - (acpi_physical_address) obj_desc->processor. - address); - acpi_ex_out_pointer("system_notify", - obj_desc->processor.system_notify); - acpi_ex_out_pointer("device_notify", - obj_desc->processor.device_notify); - acpi_ex_out_pointer("Handler", obj_desc->processor.handler); - break; - - case ACPI_TYPE_THERMAL: - - acpi_ex_out_pointer("system_notify", - obj_desc->thermal_zone.system_notify); - acpi_ex_out_pointer("device_notify", - obj_desc->thermal_zone.device_notify); - acpi_ex_out_pointer("Handler", obj_desc->thermal_zone.handler); - break; - - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - acpi_ex_out_integer("field_flags", - obj_desc->common_field.field_flags); - acpi_ex_out_integer("access_byte_width", - obj_desc->common_field.access_byte_width); - acpi_ex_out_integer("bit_length", - obj_desc->common_field.bit_length); - acpi_ex_out_integer("fld_bit_offset", - obj_desc->common_field. - start_field_bit_offset); - acpi_ex_out_integer("base_byte_offset", - obj_desc->common_field.base_byte_offset); - acpi_ex_out_pointer("parent_node", obj_desc->common_field.node); - - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER_FIELD: - acpi_ex_out_pointer("buffer_obj", - obj_desc->buffer_field.buffer_obj); - break; - - case ACPI_TYPE_LOCAL_REGION_FIELD: - acpi_ex_out_pointer("region_obj", - obj_desc->field.region_obj); - break; - - case ACPI_TYPE_LOCAL_BANK_FIELD: - acpi_ex_out_integer("Value", - obj_desc->bank_field.value); - acpi_ex_out_pointer("region_obj", - obj_desc->bank_field.region_obj); - acpi_ex_out_pointer("bank_obj", - obj_desc->bank_field.bank_obj); - break; - - case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_ex_out_integer("Value", - obj_desc->index_field.value); - acpi_ex_out_pointer("Index", - obj_desc->index_field.index_obj); - acpi_ex_out_pointer("Data", - obj_desc->index_field.data_obj); - break; - - default: - /* All object types covered above */ - break; - } - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - - acpi_ex_out_integer("target_type", - obj_desc->reference.target_type); - acpi_ex_out_string("Opcode", - (acpi_ps_get_opcode_info - (obj_desc->reference.opcode))->name); - acpi_ex_out_integer("Offset", obj_desc->reference.offset); - acpi_ex_out_pointer("obj_desc", obj_desc->reference.object); - acpi_ex_out_pointer("Node", obj_desc->reference.node); - acpi_ex_out_pointer("Where", obj_desc->reference.where); - - acpi_ex_dump_reference(obj_desc); - break; - - case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - - acpi_ex_out_integer("space_id", - obj_desc->address_space.space_id); - acpi_ex_out_pointer("Next", obj_desc->address_space.next); - acpi_ex_out_pointer("region_list", - obj_desc->address_space.region_list); - acpi_ex_out_pointer("Node", obj_desc->address_space.node); - acpi_ex_out_pointer("Context", obj_desc->address_space.context); - break; + if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { + return_VOID; + } - case ACPI_TYPE_LOCAL_NOTIFY: + /* Common Fields */ - acpi_ex_out_pointer("Node", obj_desc->notify.node); - acpi_ex_out_pointer("Context", obj_desc->notify.context); - break; + acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); - case ACPI_TYPE_LOCAL_ALIAS: - case ACPI_TYPE_LOCAL_METHOD_ALIAS: - case ACPI_TYPE_LOCAL_EXTRA: - case ACPI_TYPE_LOCAL_DATA: - default: - - acpi_os_printf - ("ex_dump_object_descriptor: Display not implemented for object type %s\n", - acpi_ut_get_object_type_name(obj_desc)); - break; - } + /* Object-specific fields */ + acpi_ex_dump_object(obj_desc, acpi_ex_dump_info[obj_desc->common.type]); return_VOID; } -#endif /* ACPI_FUTURE_USAGE */ #endif diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index ab1ba399aa28..e259201ce9a0 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -249,13 +249,18 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). */ if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { - ACPI_REPORT_ERROR(("SMBus write requires Buffer, found type %s\n", acpi_ut_get_object_type_name(source_desc))); + ACPI_ERROR((AE_INFO, + "SMBus write requires Buffer, found type %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { - ACPI_REPORT_ERROR(("SMBus write requires Buffer of length %X, found length %X\n", ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length)); + ACPI_ERROR((AE_INFO, + "SMBus write requires Buffer of length %X, found length %X", + ACPI_SMBUS_BUFFER_SIZE, + source_desc->buffer.length)); return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); } diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index ba6e08843c29..bd1af35f7fcf 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,10 +94,9 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, /* We must have a valid region */ if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed Region, found type %X (%s)\n", - ACPI_GET_OBJECT_TYPE(rgn_desc), - acpi_ut_get_object_type_name(rgn_desc))); + ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)", + ACPI_GET_OBJECT_TYPE(rgn_desc), + acpi_ut_get_object_type_name(rgn_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -162,31 +161,28 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", - acpi_ut_get_node_name(obj_desc-> - common_field. - node), - obj_desc->common_field. - access_byte_width, - acpi_ut_get_node_name(rgn_desc-> - region.node), - rgn_desc->region.length)); + ACPI_ERROR((AE_INFO, + "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)", + acpi_ut_get_node_name(obj_desc-> + common_field.node), + obj_desc->common_field.access_byte_width, + acpi_ut_get_node_name(rgn_desc->region. + node), + rgn_desc->region.length)); } /* * Offset rounded up to next multiple of field width * exceeds region length, indicate an error */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", - acpi_ut_get_node_name(obj_desc->common_field. - node), - obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, - obj_desc->common_field.access_byte_width, - acpi_ut_get_node_name(rgn_desc->region.node), - rgn_desc->region.length)); + ACPI_ERROR((AE_INFO, + "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)", + acpi_ut_get_node_name(obj_desc->common_field.node), + obj_desc->common_field.base_byte_offset, + field_datum_byte_offset, + obj_desc->common_field.access_byte_width, + acpi_ut_get_node_name(rgn_desc->region.node), + rgn_desc->region.length)); return_ACPI_STATUS(AE_AML_REGION_LIMIT); } @@ -270,18 +266,17 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, if (ACPI_FAILURE(status)) { if (status == AE_NOT_IMPLEMENTED) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Region %s(%X) not implemented\n", - acpi_ut_get_region_name(rgn_desc-> - region. - space_id), - rgn_desc->region.space_id)); + ACPI_ERROR((AE_INFO, + "Region %s(%X) not implemented", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id)); } else if (status == AE_NOT_EXIST) { - ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n", - acpi_ut_get_region_name(rgn_desc-> - region. - space_id), - rgn_desc->region.space_id)); + ACPI_ERROR((AE_INFO, + "Region %s(%X) has no handler", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id)); } } @@ -514,8 +509,8 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, default: - ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc))); + ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X", + ACPI_GET_OBJECT_TYPE(obj_desc))); status = AE_AML_INTERNAL; break; } @@ -618,11 +613,11 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "write_with_update_rule: Unknown update_rule setting: %X\n", - (obj_desc->common_field. - field_flags & - AML_FIELD_UPDATE_RULE_MASK))); + ACPI_ERROR((AE_INFO, + "Unknown update_rule value: %X", + (obj_desc->common_field. + field_flags & + AML_FIELD_UPDATE_RULE_MASK))); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } } @@ -677,10 +672,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Field size %X (bits) is too large for buffer (%X)\n", - obj_desc->common_field.bit_length, - buffer_length)); + ACPI_ERROR((AE_INFO, + "Field size %X (bits) is too large for buffer (%X)", + obj_desc->common_field.bit_length, buffer_length)); return_ACPI_STATUS(AE_BUFFER_OVERFLOW); } @@ -792,10 +786,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Field size %X (bits) is too large for buffer (%X)\n", - obj_desc->common_field.bit_length, - buffer_length)); + ACPI_ERROR((AE_INFO, + "Field size %X (bits) is too large for buffer (%X)", + obj_desc->common_field.bit_length, buffer_length)); return_ACPI_STATUS(AE_BUFFER_OVERFLOW); } diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index a3f4d72bedc9..48c18d29222a 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,7 @@ #include <acpi/acpi.h> #include <acpi/acinterp.h> #include <acpi/amlcode.h> +#include <acpi/amlresrc.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exmisc") @@ -97,7 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, default: - ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", + obj_desc->reference.opcode)); return_ACPI_STATUS(AE_AML_INTERNAL); } break; @@ -112,7 +114,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, default: - ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); + ACPI_ERROR((AE_INFO, "Invalid descriptor type %X", + ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); return_ACPI_STATUS(AE_TYPE); } @@ -157,48 +160,65 @@ acpi_ex_concat_template(union acpi_operand_object *operand0, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { + acpi_status status; union acpi_operand_object *return_desc; u8 *new_buf; - u8 *end_tag1; - u8 *end_tag2; + u8 *end_tag; + acpi_size length0; acpi_size length1; - acpi_size length2; + acpi_size new_length; ACPI_FUNCTION_TRACE("ex_concat_template"); - /* Find the end_tags in each resource template */ + /* + * Find the end_tag descriptor in each resource template. + * Note1: returned pointers point TO the end_tag, not past it. + * Note2: zero-length buffers are allowed; treated like one end_tag + */ + + /* Get the length of the first resource template */ - end_tag1 = acpi_ut_get_resource_end_tag(operand0); - end_tag2 = acpi_ut_get_resource_end_tag(operand1); - if (!end_tag1 || !end_tag2) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + status = acpi_ut_get_resource_end_tag(operand0, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - /* Compute the length of each part */ + length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); + + /* Get the length of the second resource template */ + + status = acpi_ut_get_resource_end_tag(operand1, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer); - length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2; /* Size of END_TAG */ + length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); - /* Create a new buffer object for the result */ + /* Combine both lengths, minimum size will be 2 for end_tag */ - return_desc = acpi_ut_create_buffer_object(length1 + length2); + new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); + + /* Create a new buffer object for the result (with one end_tag) */ + + return_desc = acpi_ut_create_buffer_object(new_length); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } - /* Copy the templates to the new descriptor */ - + /* + * Copy the templates to the new buffer, 0 first, then 1 follows. One + * end_tag descriptor is copied from Operand1. + */ new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1); - ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2); + ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0); + ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1); - /* Compute the new checksum */ + /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ - new_buf[return_desc->buffer.length - 1] = - acpi_ut_generate_checksum(return_desc->buffer.pointer, - (return_desc->buffer.length - 1)); + new_buf[new_length - 1] = 0; + new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; - /* Return the completed template descriptor */ + /* Return the completed resource template */ *actual_return_desc = return_desc; return_ACPI_STATUS(AE_OK); @@ -229,7 +249,6 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, union acpi_operand_object *return_desc; char *new_buf; acpi_status status; - acpi_size new_length; ACPI_FUNCTION_TRACE("ex_do_concatenate"); @@ -256,8 +275,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, break; default: - ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n", - ACPI_GET_OBJECT_TYPE(operand0))); + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); status = AE_AML_INTERNAL; } @@ -296,8 +315,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Copy the first integer, LSB first */ - ACPI_MEMCPY(new_buf, - &operand0->integer.value, + ACPI_MEMCPY(new_buf, &operand0->integer.value, acpi_gbl_integer_byte_width); /* Copy the second integer (LSB first) after the first */ @@ -311,14 +329,11 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Result of two Strings is a String */ - new_length = (acpi_size) operand0->string.length + - (acpi_size) local_operand1->string.length; - if (new_length > ACPI_MAX_STRING_CONVERSION) { - status = AE_AML_STRING_LIMIT; - goto cleanup; - } - - return_desc = acpi_ut_create_string_object(new_length); + return_desc = acpi_ut_create_string_object((acpi_size) + (operand0->string. + length + + local_operand1-> + string.length)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -338,11 +353,10 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_buffer_object((acpi_size) - operand0->buffer. - length + - (acpi_size) - local_operand1-> - buffer.length); + (operand0->buffer. + length + + local_operand1-> + buffer.length)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -352,8 +366,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Concatenate the buffers */ - ACPI_MEMCPY(new_buf, - operand0->buffer.pointer, operand0->buffer.length); + ACPI_MEMCPY(new_buf, operand0->buffer.pointer, + operand0->buffer.length); ACPI_MEMCPY(new_buf + operand0->buffer.length, local_operand1->buffer.pointer, local_operand1->buffer.length); @@ -363,8 +377,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Invalid object type, should not happen here */ - ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n", - ACPI_GET_OBJECT_TYPE(operand0))); + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); status = AE_AML_INTERNAL; goto cleanup; } @@ -625,9 +639,8 @@ acpi_ex_do_logical_op(u16 opcode, /* Lexicographic compare: compare the data bytes */ - compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer, - (const char *)local_operand1->buffer. - pointer, + compare = ACPI_MEMCMP(operand0->buffer.pointer, + local_operand1->buffer.pointer, (length0 > length1) ? length1 : length0); switch (opcode) { diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index ab47f6d8b5c0..f843b22e20b9 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -153,7 +153,9 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Sanity check -- we must have a valid thread ID */ if (!walk_state->thread) { - ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node))); + ACPI_ERROR((AE_INFO, + "Cannot acquire Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -162,7 +164,9 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, * mutex. This mechanism provides some deadlock prevention */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { - ACPI_REPORT_ERROR(("Cannot acquire Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node))); + ACPI_ERROR((AE_INFO, + "Cannot acquire Mutex [%4.4s], incorrect sync_level", + acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } @@ -237,14 +241,18 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* The mutex must have been previously acquired in order to release it */ if (!obj_desc->mutex.owner_thread) { - ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], not acquired\n", acpi_ut_get_node_name(obj_desc->mutex.node))); + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], not acquired", + acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } /* Sanity check -- we must have a valid thread ID */ if (!walk_state->thread) { - ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], null thread info\n", acpi_ut_get_node_name(obj_desc->mutex.node))); + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -255,7 +263,11 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) && (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) { - ACPI_REPORT_ERROR(("Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), obj_desc->mutex.owner_thread->thread_id)); + ACPI_ERROR((AE_INFO, + "Thread %X cannot release Mutex [%4.4s] acquired by thread %X", + walk_state->thread->thread_id, + acpi_ut_get_node_name(obj_desc->mutex.node), + obj_desc->mutex.owner_thread->thread_id)); return_ACPI_STATUS(AE_AML_NOT_OWNER); } @@ -264,7 +276,9 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * equal to the current sync level */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { - ACPI_REPORT_ERROR(("Cannot release Mutex [%4.4s], incorrect sync_level\n", acpi_ut_get_node_name(obj_desc->mutex.node))); + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], incorrect sync_level", + acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 239d8473e9a5..054fe5e1a314 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -99,7 +99,8 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) */ name_string = ACPI_MEM_ALLOCATE(size_needed); if (!name_string) { - ACPI_REPORT_ERROR(("ex_allocate_name_string: Could not allocate size %d\n", size_needed)); + ACPI_ERROR((AE_INFO, + "Could not allocate size %d", size_needed)); return_PTR(NULL); } @@ -167,8 +168,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) char_buf[0] = *aml_address; if ('0' <= char_buf[0] && char_buf[0] <= '9') { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "leading digit: %c\n", - char_buf[0])); + ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0])); return_ACPI_STATUS(AE_CTRL_PENDING); } @@ -191,10 +191,10 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) if (name_string) { ACPI_STRCAT(name_string, char_buf); ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Appended to - %s \n", name_string)); + "Appended to - %s\n", name_string)); } else { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "No Name string - %s \n", char_buf)); + "No Name string - %s\n", char_buf)); } } else if (index == 0) { /* @@ -211,12 +211,12 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) * the required 4 */ status = AE_AML_BAD_NAME; - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Bad character %02x in name, at %p\n", - *aml_address, aml_address)); + ACPI_ERROR((AE_INFO, + "Bad character %02x in name, at %p", + *aml_address, aml_address)); } - *in_aml_address = (u8 *) aml_address; + *in_aml_address = ACPI_CAST_PTR(u8, aml_address); return_ACPI_STATUS(status); } @@ -412,8 +412,7 @@ acpi_ex_get_name_string(acpi_object_type data_type, if (AE_CTRL_PENDING == status && has_prefix) { /* Ran out of segments after processing a prefix */ - ACPI_REPORT_ERROR(("ex_do_name: Malformed Name at %p\n", - name_string)); + ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); status = AE_AML_BAD_NAME; } diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 97e34542f5e4..23d0823bcd5e 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,7 +111,8 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) default: /* Unknown opcode */ - ACPI_REPORT_ERROR(("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; break; } @@ -188,7 +189,8 @@ acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state) default: /* Unknown opcode */ - ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; break; } @@ -227,7 +229,8 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state) default: /* Unknown opcode */ - ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -346,9 +349,9 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) /* Check the range of the digit */ if (temp32 > 9) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "BCD digit too large (not decimal): 0x%X\n", - temp32)); + ACPI_ERROR((AE_INFO, + "BCD digit too large (not decimal): 0x%X", + temp32)); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; @@ -393,12 +396,10 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) /* Overflow if there is any data left in Digit */ if (digit > 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Integer too large to convert to BCD: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(operand - [0]-> - integer. - value))); + ACPI_ERROR((AE_INFO, + "Integer too large to convert to BCD: %8.8X%8.8X", + ACPI_FORMAT_UINT64(operand[0]-> + integer.value))); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } @@ -525,15 +526,16 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) /* These are two obsolete opcodes */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%s is obsolete and not implemented\n", - acpi_ps_get_opcode_name(walk_state->opcode))); + ACPI_ERROR((AE_INFO, + "%s is obsolete and not implemented", + acpi_ps_get_opcode_name(walk_state->opcode))); status = AE_SUPPORT; goto cleanup; default: /* Unknown opcode */ - ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -639,11 +641,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc, walk_state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%s: bad operand(s) %s\n", - acpi_ps_get_opcode_name(walk_state-> - opcode), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "While resolving operands for [%s]", + acpi_ps_get_opcode_name(walk_state-> + opcode))); goto cleanup; } @@ -742,9 +743,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n", - acpi_ut_get_type_name(type))); + ACPI_ERROR((AE_INFO, + "Operand is not Buf/Int/Str/Pkg - found type %s", + acpi_ut_get_type_name(type))); status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -941,11 +942,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown Index target_type %X in obj %p\n", - operand[0]->reference. - target_type, - operand[0])); + ACPI_ERROR((AE_INFO, + "Unknown Index target_type %X in obj %p", + operand[0]->reference. + target_type, operand[0])); status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -971,11 +971,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown opcode in ref(%p) - %X\n", - operand[0], - operand[0]->reference. - opcode)); + ACPI_ERROR((AE_INFO, + "Unknown opcode in ref(%p) - %X", + operand[0], + operand[0]->reference.opcode)); status = AE_TYPE; goto cleanup; @@ -985,7 +984,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 8d70c6beef00..e263a5ddd405 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,9 +111,9 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) /* Are notifies allowed on this object? */ if (!acpi_ev_is_notify_object(node)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unexpected notify object type [%s]\n", - acpi_ut_get_type_name(node->type))); + ACPI_ERROR((AE_INFO, + "Unexpected notify object type [%s]", + acpi_ut_get_type_name(node->type))); status = AE_AML_OPERAND_TYPE; break; @@ -157,7 +157,8 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; } @@ -221,7 +222,8 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -344,10 +346,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) (length < operand[1]->integer.value) && (operand[0]->buffer.pointer[length])) { length++; - if (length > ACPI_MAX_STRING_CONVERSION) { - status = AE_AML_STRING_LIMIT; - goto cleanup; - } } /* Allocate a new string object */ @@ -358,8 +356,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - /* Copy the raw buffer data with no transform. NULL terminated already */ - + /* + * Copy the raw buffer data with no transform. + * (NULL terminated already) + */ ACPI_MEMCPY(return_desc->string.pointer, operand[0]->buffer.pointer, length); break; @@ -391,10 +391,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* Object to be indexed is a Package */ if (index >= operand[0]->package.count) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Index value (%X%8.8X) beyond package end (%X)\n", - ACPI_FORMAT_UINT64(index), - operand[0]->package.count)); + ACPI_ERROR((AE_INFO, + "Index value (%X%8.8X) beyond package end (%X)", + ACPI_FORMAT_UINT64(index), + operand[0]->package.count)); status = AE_AML_PACKAGE_LIMIT; goto cleanup; } @@ -407,10 +407,10 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* Object to be indexed is a Buffer/String */ if (index >= operand[0]->buffer.length) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Index value (%X%8.8X) beyond end of buffer (%X)\n", - ACPI_FORMAT_UINT64(index), - operand[0]->buffer.length)); + ACPI_ERROR((AE_INFO, + "Index value (%X%8.8X) beyond end of buffer (%X)", + ACPI_FORMAT_UINT64(index), + operand[0]->buffer.length)); status = AE_AML_BUFFER_LIMIT; goto cleanup; } @@ -442,7 +442,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; break; } @@ -546,7 +547,8 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 483365777670..6a3a883cb8a3 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -119,7 +119,8 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -223,8 +224,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) goto cleanup; } - if (length > 0) { - /* Copy the portion requested */ + if (buffer) { + /* We have a buffer, copy the portion requested */ ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, length); @@ -242,7 +243,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index 5dee77139576..e043d924444f 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -234,8 +234,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) || (operand[3]->integer.value > MAX_MATCH_OPERATOR)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Match operator out of range\n")); + ACPI_ERROR((AE_INFO, "Match operator out of range")); status = AE_AML_OPERAND_VALUE; goto cleanup; } @@ -244,10 +243,10 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) index = operand[5]->integer.value; if (index >= operand[0]->package.count) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Index (%X%8.8X) beyond package end (%X)\n", - ACPI_FORMAT_UINT64(index), - operand[0]->package.count)); + ACPI_ERROR((AE_INFO, + "Index (%X%8.8X) beyond package end (%X)", + ACPI_FORMAT_UINT64(index), + operand[0]->package.count)); status = AE_AML_PACKAGE_LIMIT; goto cleanup; } @@ -316,7 +315,8 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) default: - ACPI_REPORT_ERROR(("acpi_ex_opcode_6A_0T_1R: Unknown opcode %X\n", walk_state->opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", + walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 7476c363e407..7719ae5d4f16 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -274,9 +274,8 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, default: /* Invalid field access type */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown field access type %X\n", access)); - return_VALUE(0); + ACPI_ERROR((AE_INFO, "Unknown field access type %X", access)); + return_UINT32(0); } if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { @@ -289,7 +288,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, } *return_byte_alignment = byte_alignment; - return_VALUE(bit_length); + return_UINT32(bit_length); } /******************************************************************************* @@ -422,15 +421,15 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null region_node\n")); + ACPI_ERROR((AE_INFO, "Null region_node")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } type = acpi_ns_get_type(info->region_node); if (type != ACPI_TYPE_REGION) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed Region, found type %X (%s)\n", - type, acpi_ut_get_type_name(type))); + ACPI_ERROR((AE_INFO, + "Needed Region, found type %X (%s)", + type, acpi_ut_get_type_name(type))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -499,17 +498,17 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* Get the Index and Data registers */ + obj_desc->index_field.index_obj = acpi_ns_get_attached_object(info->register_node); obj_desc->index_field.data_obj = acpi_ns_get_attached_object(info->data_register_node); - obj_desc->index_field.value = (u32) - (info->field_bit_position / - ACPI_MUL_8(obj_desc->field.access_byte_width)); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { - ACPI_REPORT_ERROR(("Null Index Object during field prep\n")); + ACPI_ERROR((AE_INFO, + "Null Index Object during field prep")); acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -519,6 +518,15 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) acpi_ut_add_reference(obj_desc->index_field.data_obj); acpi_ut_add_reference(obj_desc->index_field.index_obj); + /* + * The value written to the Index register is the byte offset of the + * target field + * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position) + */ + obj_desc->index_field.value = (u32) + (info->field_bit_position / + ACPI_MUL_8(obj_desc->field.access_byte_width)); + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 9a2f5bea3afe..6a4cfdff606d 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,7 +77,7 @@ acpi_ex_system_memory_space_handler(u32 function, struct acpi_mem_space_context *mem_info = region_context; u32 length; acpi_size window_size; -#ifndef ACPI_MISALIGNED_TRANSFERS +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED u32 remainder; #endif @@ -103,13 +103,12 @@ acpi_ex_system_memory_space_handler(u32 function, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid system_memory width %d\n", - bit_width)); + ACPI_ERROR((AE_INFO, "Invalid system_memory width %d", + bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } -#ifndef ACPI_MISALIGNED_TRANSFERS +#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. @@ -159,10 +158,10 @@ acpi_ex_system_memory_space_handler(u32 function, (void **)&mem_info-> mapped_logical_address); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not map memory at %8.8X%8.8X, size %X\n", - ACPI_FORMAT_UINT64(address), - (u32) window_size)); + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X%8.8X, size %X", + ACPI_FORMAT_UINT64(address), + (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS(status); } @@ -199,20 +198,20 @@ acpi_ex_system_memory_space_handler(u32 function, *value = 0; switch (bit_width) { case 8: - *value = (acpi_integer) * ((u8 *) logical_addr_ptr); + *value = (acpi_integer) ACPI_GET8(logical_addr_ptr); break; case 16: - *value = (acpi_integer) * ((u16 *) logical_addr_ptr); + *value = (acpi_integer) ACPI_GET16(logical_addr_ptr); break; case 32: - *value = (acpi_integer) * ((u32 *) logical_addr_ptr); + *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); break; #if ACPI_MACHINE_WIDTH != 16 case 64: - *value = (acpi_integer) * ((u64 *) logical_addr_ptr); + *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); break; #endif default: @@ -225,20 +224,20 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: - *(u8 *) logical_addr_ptr = (u8) * value; + ACPI_SET8(logical_addr_ptr) = (u8) * value; break; case 16: - *(u16 *) logical_addr_ptr = (u16) * value; + ACPI_SET16(logical_addr_ptr) = (u16) * value; break; case 32: - *(u32 *) logical_addr_ptr = (u32) * value; + ACPI_SET32(logical_addr_ptr) = (u32) * value; break; #if ACPI_MACHINE_WIDTH != 16 case 64: - *(u64 *) logical_addr_ptr = (u64) * value; + ACPI_SET64(logical_addr_ptr) = (u64) * value; break; #endif diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index ff5d8f97e8eb..01b26c80d22b 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -122,8 +122,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, } if (!source_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No object attached to node %p\n", node)); + ACPI_ERROR((AE_INFO, "No object attached to node %p", node)); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -135,10 +134,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_PACKAGE: if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Object not a Package, type %s\n", - acpi_ut_get_object_type_name - (source_desc))); + ACPI_ERROR((AE_INFO, "Object not a Package, type %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -154,10 +151,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_BUFFER: if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Object not a Buffer, type %s\n", - acpi_ut_get_object_type_name - (source_desc))); + ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -173,10 +168,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_STRING: if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Object not a String, type %s\n", - acpi_ut_get_object_type_name - (source_desc))); + ACPI_ERROR((AE_INFO, "Object not a String, type %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -189,10 +182,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_INTEGER: if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Object not a Integer, type %s\n", - acpi_ut_get_object_type_name - (source_desc))); + ACPI_ERROR((AE_INFO, "Object not a Integer, type %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -236,9 +227,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_ANY: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Untyped entry %p, no attached object!\n", - node)); + ACPI_ERROR((AE_INFO, + "Untyped entry %p, no attached object!", node)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ @@ -257,12 +247,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, default: /* No named references are allowed here */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported Reference opcode %X (%s)\n", - source_desc->reference.opcode, - acpi_ps_get_opcode_name(source_desc-> - reference. - opcode))); + ACPI_ERROR((AE_INFO, + "Unsupported Reference opcode %X (%s)", + source_desc->reference.opcode, + acpi_ps_get_opcode_name(source_desc-> + reference.opcode))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -272,9 +261,9 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* Default case is for unknown types */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Node %p - Unknown object type %X\n", - node, entry_type)); + ACPI_ERROR((AE_INFO, + "Node %p - Unknown object type %X", + node, entry_type)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 97eecbd3242d..1deed492fe88 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,7 +81,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr); if (!stack_ptr || !*stack_ptr) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Internal - null pointer\n")); + ACPI_ERROR((AE_INFO, "Internal - null pointer")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -97,8 +97,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr, } if (!*stack_ptr) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Internal - null pointer\n")); + ACPI_ERROR((AE_INFO, "Internal - null pointer")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } } @@ -228,9 +227,9 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * A NULL object descriptor means an unitialized element of * the package, can't dereference it */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Attempt to deref an Index to NULL pkg element Idx=%p\n", - stack_desc)); + ACPI_ERROR((AE_INFO, + "Attempt to deref an Index to NULL pkg element Idx=%p", + stack_desc)); status = AE_AML_UNINITIALIZED_ELEMENT; } break; @@ -239,7 +238,10 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* Invalid reference object */ - ACPI_REPORT_ERROR(("During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc)); + ACPI_ERROR((AE_INFO, + "Unknown target_type %X in Index/Reference obj %p", + stack_desc->reference.target_type, + stack_desc)); status = AE_AML_INTERNAL; break; } @@ -264,7 +266,10 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, default: - ACPI_REPORT_ERROR(("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name(opcode), stack_desc)); + ACPI_ERROR((AE_INFO, + "Unknown Reference opcode %X (%s) in %p", + opcode, acpi_ps_get_opcode_name(opcode), + stack_desc)); status = AE_AML_INTERNAL; break; } @@ -386,7 +391,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { - ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node))); + ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", + node, + acpi_ut_get_descriptor_name(node))); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -442,7 +449,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { - ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n", node, acpi_ut_get_descriptor_name(node))); + ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", + node, + acpi_ut_get_descriptor_name(node))); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -511,7 +520,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, default: - ACPI_REPORT_ERROR(("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n", obj_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, + "Unknown Reference subtype %X", + obj_desc->reference.opcode)); return_ACPI_STATUS(AE_AML_INTERNAL); } } diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index ff064e79ab90..a1c000f5a415 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,7 @@ #include <acpi/amlcode.h> #include <acpi/acparser.h> #include <acpi/acinterp.h> +#include <acpi/acnamesp.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exresop") @@ -73,7 +74,7 @@ static acpi_status acpi_ex_check_object_type(acpi_object_type type_needed, acpi_object_type this_type, void *object) { - ACPI_FUNCTION_NAME("ex_check_object_type"); + ACPI_FUNCTION_ENTRY(); if (type_needed == ACPI_TYPE_ANY) { /* All types OK, so we don't perform any typechecks */ @@ -95,10 +96,10 @@ acpi_ex_check_object_type(acpi_object_type type_needed, } if (type_needed != this_type) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [%s], found [%s] %p\n", - acpi_ut_get_type_name(type_needed), - acpi_ut_get_type_name(this_type), object)); + ACPI_ERROR((AE_INFO, + "Needed type [%s], found [%s] %p", + acpi_ut_get_type_name(type_needed), + acpi_ut_get_type_name(this_type), object)); return (AE_AML_OPERAND_TYPE); } @@ -151,13 +152,13 @@ acpi_ex_resolve_operands(u16 opcode, arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { - ACPI_REPORT_ERROR(("resolve_operands: %X is not a valid AML opcode\n", opcode)); + ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", opcode)); return_ACPI_STATUS(AE_AML_INTERNAL); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Opcode %X [%s] required_operand_types=%8.8X \n", + "Opcode %X [%s] required_operand_types=%8.8X\n", opcode, op_info->name, arg_types)); /* @@ -169,7 +170,8 @@ acpi_ex_resolve_operands(u16 opcode, */ while (GET_CURRENT_ARG_TYPE(arg_types)) { if (!stack_ptr || !*stack_ptr) { - ACPI_REPORT_ERROR(("resolve_operands: Null stack entry at %p\n", stack_ptr)); + ACPI_ERROR((AE_INFO, "Null stack entry at %p", + stack_ptr)); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -187,6 +189,22 @@ acpi_ex_resolve_operands(u16 opcode, object_type = ((struct acpi_namespace_node *)obj_desc)->type; + + /* + * Resolve an alias object. The construction of these objects + * guarantees that there is only one level of alias indirection; + * thus, the attached object is always the aliased namespace node + */ + if (object_type == ACPI_TYPE_LOCAL_ALIAS) { + obj_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node + *)obj_desc); + *stack_ptr = obj_desc; + object_type = + ((struct acpi_namespace_node *)obj_desc)-> + type; + } break; case ACPI_DESC_TYPE_OPERAND: @@ -198,9 +216,9 @@ acpi_ex_resolve_operands(u16 opcode, /* Check for bad acpi_object_type */ if (!acpi_ut_valid_object_type(object_type)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Bad operand object type [%X]\n", - object_type)); + ACPI_ERROR((AE_INFO, + "Bad operand object type [%X]", + object_type)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -238,13 +256,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Operand is a Reference, Unknown Reference Opcode %X [%s]\n", - obj_desc->reference. - opcode, - (acpi_ps_get_opcode_info - (obj_desc->reference. - opcode))->name)); + ACPI_ERROR((AE_INFO, + "Operand is a Reference, Unknown Reference Opcode: %X", + obj_desc->reference. + opcode)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -255,11 +270,10 @@ acpi_ex_resolve_operands(u16 opcode, /* Invalid descriptor */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid descriptor %p [%s]\n", - obj_desc, - acpi_ut_get_descriptor_name - (obj_desc))); + ACPI_ERROR((AE_INFO, + "Invalid descriptor %p [%s]", + obj_desc, + acpi_ut_get_descriptor_name(obj_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -417,11 +431,10 @@ acpi_ex_resolve_operands(u16 opcode, acpi_ex_convert_to_integer(obj_desc, stack_ptr, 16); if (ACPI_FAILURE(status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Integer/String/Buffer], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), - obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -444,11 +457,10 @@ acpi_ex_resolve_operands(u16 opcode, status = acpi_ex_convert_to_buffer(obj_desc, stack_ptr); if (ACPI_FAILURE(status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Integer/String/Buffer], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), - obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -472,11 +484,10 @@ acpi_ex_resolve_operands(u16 opcode, ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE(status)) { if (status == AE_TYPE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Integer/String/Buffer], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), - obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -502,10 +513,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Integer/String/Buffer], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -539,10 +550,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Integer/String/Buffer], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Integer/String/Buffer], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -566,10 +577,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Buffer/String/Package/Reference], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Buffer/String/Package/Reference], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -588,10 +599,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Buffer/String/Package], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Buffer/String/Package], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -611,10 +622,10 @@ acpi_ex_resolve_operands(u16 opcode, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed [Region/region_field], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed [Region/region_field], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -656,10 +667,10 @@ acpi_ex_resolve_operands(u16 opcode, break; } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n", - acpi_ut_get_object_type_name - (obj_desc), obj_desc)); + ACPI_ERROR((AE_INFO, + "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", + acpi_ut_get_object_type_name + (obj_desc), obj_desc)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -669,9 +680,9 @@ acpi_ex_resolve_operands(u16 opcode, /* Unknown type */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Internal - Unknown ARGI (required operand) type %X\n", - this_arg_type)); + ACPI_ERROR((AE_INFO, + "Internal - Unknown ARGI (required operand) type %X", + this_arg_type)); return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index a7d8eea305c2..3f020c0e2b95 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -250,7 +250,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, /* Validate parameters */ if (!source_desc || !dest_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null parameter\n")); + ACPI_ERROR((AE_INFO, "Null parameter")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -290,10 +290,10 @@ acpi_ex_store(union acpi_operand_object *source_desc, /* Destination is not a Reference object */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Target is not a Reference or Constant object - %s [%p]\n", - acpi_ut_get_object_type_name(dest_desc), - dest_desc)); + ACPI_ERROR((AE_INFO, + "Target is not a Reference or Constant object - %s [%p]", + acpi_ut_get_object_type_name(dest_desc), + dest_desc)); ACPI_DUMP_STACK_ENTRY(source_desc); ACPI_DUMP_STACK_ENTRY(dest_desc); @@ -360,8 +360,8 @@ acpi_ex_store(union acpi_operand_object *source_desc, default: - ACPI_REPORT_ERROR(("ex_store: Unknown Reference opcode %X\n", - ref_desc->reference.opcode)); + ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", + ref_desc->reference.opcode)); ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR); status = AE_AML_INTERNAL; @@ -490,10 +490,9 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, /* All other types are invalid */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Source must be Integer/Buffer/String type, not %s\n", - acpi_ut_get_object_type_name - (source_desc))); + ACPI_ERROR((AE_INFO, + "Source must be Integer/Buffer/String type, not %s", + acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -503,8 +502,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Target is not a Package or buffer_field\n")); + ACPI_ERROR((AE_INFO, + "Target is not a Package or buffer_field")); status = AE_AML_OPERAND_TYPE; break; } diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 382f63c14ea1..42967baf760d 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,11 +123,10 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, && (source_desc->reference.opcode == AML_LOAD_OP))) { /* Conversion successful but still not a valid type */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot assign type %s to %s (must be type Int/Str/Buf)\n", - acpi_ut_get_object_type_name - (source_desc), - acpi_ut_get_type_name(target_type))); + ACPI_ERROR((AE_INFO, + "Cannot assign type %s to %s (must be type Int/Str/Buf)", + acpi_ut_get_object_type_name(source_desc), + acpi_ut_get_type_name(target_type))); status = AE_AML_OPERAND_TYPE; } break; @@ -135,9 +134,11 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: - /* Aliases are resolved by acpi_ex_prep_operands */ - - ACPI_REPORT_ERROR(("Store into Alias - should never happen\n")); + /* + * All aliases should have been resolved earlier, during the + * operand resolution phase. + */ + ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object")); status = AE_AML_INTERNAL; break; @@ -280,9 +281,8 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, /* * All other types come here. */ - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "Store into type %s not implemented\n", - acpi_ut_get_object_type_name(dest_desc))); + ACPI_WARNING((AE_INFO, "Store into type %s not implemented", + acpi_ut_get_object_type_name(dest_desc))); status = AE_NOT_IMPLEMENTED; break; diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index c4ff654a6697..6ab707087750 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +71,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, /* We know that source_desc is a buffer by now */ - buffer = (u8 *) source_desc->buffer.pointer; + buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); length = source_desc->buffer.length; /* @@ -160,7 +160,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, /* We know that source_desc is a string by now */ - buffer = (u8 *) source_desc->string.pointer; + buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); length = source_desc->string.length; /* diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 8a88b841237d..ea9144f42e1f 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -129,8 +129,8 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) * (ACPI specifies 100 usec as max, but this gives some slack in * order to support existing BIOSs) */ - ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n", - how_long)); + ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)", + how_long)); status = AE_AML_OPERAND_VALUE; } else { acpi_os_stall(how_long); diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 1ee79d8c8f88..f73a61aeb7ec 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -91,7 +91,7 @@ acpi_status acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } return_ACPI_STATUS(status); @@ -127,7 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not release interpreter mutex\n")); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -200,13 +200,12 @@ u8 acpi_ex_acquire_global_lock(u32 field_flags) if (ACPI_SUCCESS(status)) { locked = TRUE; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not acquire Global Lock, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire Global Lock")); } } - return_VALUE(locked); + return_UINT8(locked); } /******************************************************************************* @@ -237,7 +236,8 @@ void acpi_ex_release_global_lock(u8 locked_by_me) if (ACPI_FAILURE(status)) { /* Report the error, but there isn't much else we can do */ - ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not release ACPI Global Lock")); } } @@ -268,7 +268,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ if (value == 0) { - return_VALUE(1); + return_UINT32(1); } current_value = value; @@ -282,7 +282,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) num_digits++; } - return_VALUE(num_digits); + return_UINT32(num_digits); } /******************************************************************************* diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index aa993715d644..8daef57b994c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -99,15 +99,15 @@ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) unsigned long *busnr = (unsigned long *)data; struct acpi_resource_address64 address; - if (resource->id != ACPI_RSTYPE_ADDRESS16 && - resource->id != ACPI_RSTYPE_ADDRESS32 && - resource->id != ACPI_RSTYPE_ADDRESS64) + if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS64) return AE_OK; acpi_resource_to_address64(resource, &address); if ((address.address_length > 0) && (address.resource_type == ACPI_BUS_NUMBER_RANGE)) - *busnr = address.min_address_range; + *busnr = address.minimum; return AE_OK; } diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index 1bb3463d7040..ea2f13271ff1 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,8 +68,7 @@ acpi_status acpi_hw_initialize(void) /* We must have the ACPI tables by the time we get here */ if (!acpi_gbl_FADT) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No FADT is present\n")); - + ACPI_ERROR((AE_INFO, "No FADT is present")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -108,7 +107,8 @@ acpi_status acpi_hw_set_mode(u32 mode) * system does not support mode transition. */ if (!acpi_gbl_FADT->smi_cmd) { - ACPI_REPORT_ERROR(("No SMI_CMD in FADT, mode transition failed.\n")); + ACPI_ERROR((AE_INFO, + "No SMI_CMD in FADT, mode transition failed")); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } @@ -120,7 +120,8 @@ acpi_status acpi_hw_set_mode(u32 mode) * transitions are not supported. */ if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) { - ACPI_REPORT_ERROR(("No ACPI mode transition supported in this system (enable/disable both zero)\n")); + ACPI_ERROR((AE_INFO, + "No ACPI mode transition supported in this system (enable/disable both zero)")); return_ACPI_STATUS(AE_OK); } @@ -154,8 +155,8 @@ acpi_status acpi_hw_set_mode(u32 mode) } if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not write mode change, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not write ACPI mode change")); return_ACPI_STATUS(status); } @@ -175,7 +176,7 @@ acpi_status acpi_hw_set_mode(u32 mode) retry--; } - ACPI_REPORT_ERROR(("Hardware never changed modes\n")); + ACPI_ERROR((AE_INFO, "Hardware did not change modes")); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } @@ -204,18 +205,18 @@ u32 acpi_hw_get_mode(void) * system does not support mode transition. */ if (!acpi_gbl_FADT->smi_cmd) { - return_VALUE(ACPI_SYS_MODE_ACPI); + return_UINT32(ACPI_SYS_MODE_ACPI); } status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { - return_VALUE(ACPI_SYS_MODE_LEGACY); + return_UINT32(ACPI_SYS_MODE_LEGACY); } if (value) { - return_VALUE(ACPI_SYS_MODE_ACPI); + return_UINT32(ACPI_SYS_MODE_ACPI); } else { - return_VALUE(ACPI_SYS_MODE_LEGACY); + return_UINT32(ACPI_SYS_MODE_LEGACY); } } diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 5c8e5dfd024e..d84942d22dd5 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 536a7aea80c9..e1fe75498415 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -144,7 +144,8 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) info.parameters = NULL; info.return_object = NULL; - sleep_state_name = (char *)acpi_gbl_sleep_state_names[sleep_state]; + sleep_state_name = + ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); status = acpi_ns_evaluate_by_name(sleep_state_name, &info); if (ACPI_FAILURE(status)) { @@ -159,15 +160,16 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) /* Must have a return object */ if (!info.return_object) { - ACPI_REPORT_ERROR(("No Sleep State object returned from [%s]\n", - sleep_state_name)); + ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", + sleep_state_name)); status = AE_NOT_EXIST; } /* It must be of type Package */ else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) { - ACPI_REPORT_ERROR(("Sleep State return object is not a Package\n")); + ACPI_ERROR((AE_INFO, + "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; } @@ -179,7 +181,8 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) * one per sleep type (A/B). */ else if (info.return_object->package.count < 2) { - ACPI_REPORT_ERROR(("Sleep State return package does not have at least two elements\n")); + ACPI_ERROR((AE_INFO, + "Sleep State return package does not have at least two elements")); status = AE_AML_NO_OPERAND; } @@ -189,7 +192,12 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) != ACPI_TYPE_INTEGER) || (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) { - ACPI_REPORT_ERROR(("Sleep State return package elements are not both Integers (%s, %s)\n", acpi_ut_get_object_type_name(info.return_object->package.elements[0]), acpi_ut_get_object_type_name(info.return_object->package.elements[1]))); + ACPI_ERROR((AE_INFO, + "Sleep State return package elements are not both Integers (%s, %s)", + acpi_ut_get_object_type_name(info.return_object-> + package.elements[0]), + acpi_ut_get_object_type_name(info.return_object-> + package.elements[1]))); status = AE_AML_OPERAND_TYPE; } else { /* Valid _Sx_ package size, type, and value */ @@ -201,12 +209,11 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) } if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%s While evaluating sleep_state [%s], bad Sleep object %p type %s\n", - acpi_format_exception(status), - sleep_state_name, info.return_object, - acpi_ut_get_object_type_name(info. - return_object))); + ACPI_EXCEPTION((AE_INFO, status, + "While evaluating sleep_state [%s], bad Sleep object %p type %s", + sleep_state_name, info.return_object, + acpi_ut_get_object_type_name(info. + return_object))); } acpi_ut_remove_reference(info.return_object); @@ -229,12 +236,11 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data); struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) { - ACPI_FUNCTION_NAME("hw_get_bit_register_info"); + ACPI_FUNCTION_ENTRY(); if (register_id > ACPI_BITREG_MAX) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid bit_register ID: %X\n", - register_id)); + ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X", + register_id)); return (NULL); } @@ -334,8 +340,8 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) bit_reg_info = acpi_hw_get_bit_register_info(register_id); if (!bit_reg_info) { - ACPI_REPORT_ERROR(("Bad ACPI HW register_id: %X\n", - register_id)); + ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X", + register_id)); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -569,8 +575,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown Register ID: %X\n", - register_id)); + ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); status = AE_BAD_PARAMETER; break; } @@ -765,9 +770,9 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported address space: %X\n", - reg->address_space_id)); + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", + reg->address_space_id)); return (AE_BAD_PARAMETER); } @@ -836,9 +841,9 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported address space: %X\n", - reg->address_space_id)); + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", + reg->address_space_id)); return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 34519069050c..89269272fd62 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -199,8 +199,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_REPORT_ERROR(("Method _SST failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "While executing method _SST")); } return_ACPI_STATUS(AE_OK); @@ -232,9 +232,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { - ACPI_REPORT_ERROR(("Sleep values out of range: A=%X B=%X\n", - acpi_gbl_sleep_type_a, - acpi_gbl_sleep_type_b)); + ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", + acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } @@ -533,21 +532,18 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) arg.integer.value = ACPI_SST_WAKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_REPORT_ERROR(("Method _SST failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); } arg.integer.value = sleep_state; status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_REPORT_ERROR(("Method _BFS failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); } status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_REPORT_ERROR(("Method _WAK failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); } /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ @@ -582,8 +578,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) arg.integer.value = ACPI_SST_WORKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_REPORT_ERROR(("Method _SST failed, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index aff6dc141784..fc10b7cb456f 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index e928e8c2c6ec..468244147ec1 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -54,36 +54,36 @@ static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges"); - if (res->id == ACPI_RSTYPE_IO) { + if (res->type == ACPI_RESOURCE_TYPE_IO) { struct acpi_resource_io *io_res = &res->data.io; - if (io_res->min_base_address != io_res->max_base_address) + if (io_res->minimum != io_res->maximum) return_VALUE(AE_OK); if (IS_RESERVED_ADDR - (io_res->min_base_address, io_res->range_length)) { + (io_res->minimum, io_res->address_length)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n", - io_res->min_base_address, - io_res->min_base_address + - io_res->range_length)); + io_res->minimum, + io_res->minimum + + io_res->address_length)); requested_res = - request_region(io_res->min_base_address, - io_res->range_length, "motherboard"); + request_region(io_res->minimum, + io_res->address_length, "motherboard"); } - } else if (res->id == ACPI_RSTYPE_FIXED_IO) { + } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) { struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io; if (IS_RESERVED_ADDR - (fixed_io_res->base_address, fixed_io_res->range_length)) { + (fixed_io_res->address, fixed_io_res->address_length)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n", - fixed_io_res->base_address, - fixed_io_res->base_address + - fixed_io_res->range_length)); + fixed_io_res->address, + fixed_io_res->address + + fixed_io_res->address_length)); requested_res = - request_region(fixed_io_res->base_address, - fixed_io_res->range_length, + request_region(fixed_io_res->address, + fixed_io_res->address_length, "motherboard"); } } else { diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index edfbe34600f5..1149bc18fb35 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,10 +110,9 @@ acpi_status acpi_ns_root_initialize(void) ACPI_NS_NO_UPSEARCH, NULL, &new_node); if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not create predefined name %s, %s\n", - init_val->name, - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not create predefined name %s", + init_val->name)); } /* @@ -124,9 +123,9 @@ acpi_status acpi_ns_root_initialize(void) if (init_val->val) { status = acpi_os_predefined_override(init_val, &val); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not override predefined %s\n", - init_val->name)); + ACPI_ERROR((AE_INFO, + "Could not override predefined %s", + init_val->name)); } if (!val) { @@ -233,7 +232,9 @@ acpi_status acpi_ns_root_initialize(void) default: - ACPI_REPORT_ERROR(("Unsupported initial type value %X\n", init_val->type)); + ACPI_ERROR((AE_INFO, + "Unsupported initial type value %X", + init_val->type)); acpi_ut_remove_reference(obj_desc); obj_desc = NULL; continue; @@ -339,7 +340,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_REPORT_ERROR(("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name(prefix_node))); + ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]", + prefix_node, + acpi_ut_get_descriptor_name(prefix_node))); return_ACPI_STATUS(AE_AML_INTERNAL); } @@ -429,7 +432,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (!this_node) { /* Current scope has no parent scope */ - ACPI_REPORT_ERROR(("ACPI path has too many parent prefixes (^) - reached beyond root node\n")); + ACPI_ERROR((AE_INFO, + "ACPI path has too many parent prefixes (^) - reached beyond root node")); return_ACPI_STATUS(AE_NOT_FOUND); } } @@ -498,7 +502,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Multi Pathname (%d Segments, Flags=%X) \n", + "Multi Pathname (%d Segments, Flags=%X)\n", num_segments, flags)); break; @@ -600,7 +604,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, (this_node->type != type_to_check_for)) { /* Complain about a type mismatch */ - ACPI_REPORT_WARNING(("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n", (char *)&simple_name, acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(type_to_check_for))); + ACPI_WARNING((AE_INFO, + "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)", + ACPI_CAST_PTR(char, &simple_name), + acpi_ut_get_type_name(this_node->type), + acpi_ut_get_type_name + (type_to_check_for))); } /* diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index cc7a85f8cfe6..9b871f38b61b 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -272,9 +272,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) /* Grandchildren should have all been deleted already */ if (child_node->child) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Found a grandchild! P=%p C=%p\n", - parent_node, child_node)); + ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", + parent_node, child_node)); } /* Now we can free this child object */ @@ -302,7 +301,9 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) /* There should be only one reference remaining on this node */ if (child_node->reference_count != 1) { - ACPI_REPORT_WARNING(("Existing references (%d) on node being deleted (%p)\n", child_node->reference_count, child_node)); + ACPI_WARNING((AE_INFO, + "Existing references (%d) on node being deleted (%p)", + child_node->reference_count, child_node)); } /* Now we can delete the node */ diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 9faf1d5c86ed..a2807317a84b 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -198,12 +198,13 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, /* Check the node type and name */ if (type > ACPI_TYPE_LOCAL_MAX) { - ACPI_REPORT_WARNING(("Invalid ACPI Type %08X\n", type)); + ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X", + type)); } if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { - ACPI_REPORT_WARNING(("Invalid ACPI Name %08X\n", - this_node->name.integer)); + ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", + this_node->name.integer)); } acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); @@ -212,7 +213,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, /* * Now we can print out the pertinent information */ - acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node); + acpi_os_printf(" %-12s %p %2.2X ", + acpi_ut_get_type_name(type), this_node, + this_node->owner_id); dbg_level = acpi_dbg_level; acpi_dbg_level = 0; diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index 55de883943d6..aff899a935e3 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 0191c7d92824..19d7b94d40c3 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -373,8 +373,7 @@ acpi_ns_execute_control_method(struct acpi_parameter_info *info) info->obj_desc = acpi_ns_get_attached_object(info->node); if (!info->obj_desc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No attached method object\n")); + ACPI_ERROR((AE_INFO, "No attached method object")); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_NULL_OBJECT); diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 0a08d2f04a06..9f929e479fd8 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,8 +93,7 @@ acpi_status acpi_ns_initialize_objects(void) ACPI_UINT32_MAX, acpi_ns_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -159,12 +158,11 @@ acpi_status acpi_ns_initialize_devices(void) (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "walk_namespace failed! %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n", + "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n", info.device_count, info.num_STA, info.num_INI)); return_ACPI_STATUS(status); @@ -289,12 +287,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, } if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n")); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not execute arguments for [%4.4s] (%s), %s\n", - acpi_ut_get_node_name(node), - acpi_ut_get_type_name(type), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not execute arguments for [%4.4s] (%s)", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(type))); } /* @@ -336,23 +332,22 @@ acpi_ns_init_one_device(acpi_handle obj_handle, struct acpi_parameter_info pinfo; u32 flags; acpi_status status; + struct acpi_namespace_node *ini_node; + struct acpi_namespace_node *device_node; ACPI_FUNCTION_TRACE("ns_init_one_device"); - pinfo.parameters = NULL; - pinfo.parameter_type = ACPI_PARAM_ARGS; - - pinfo.node = acpi_ns_map_handle_to_node(obj_handle); - if (!pinfo.node) { + device_node = acpi_ns_map_handle_to_node(obj_handle); + if (!device_node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * We will run _STA/_INI on Devices, Processors and thermal_zones only */ - if ((pinfo.node->type != ACPI_TYPE_DEVICE) && - (pinfo.node->type != ACPI_TYPE_PROCESSOR) && - (pinfo.node->type != ACPI_TYPE_THERMAL)) { + if ((device_node->type != ACPI_TYPE_DEVICE) && + (device_node->type != ACPI_TYPE_PROCESSOR) && + (device_node->type != ACPI_TYPE_THERMAL)) { return_ACPI_STATUS(AE_OK); } @@ -364,57 +359,69 @@ acpi_ns_init_one_device(acpi_handle obj_handle, info->device_count++; /* - * Run _STA to determine if we can run _INI on the device. + * Check if the _INI method exists for this device - + * if _INI does not exist, there is no need to run _STA + * No _INI means device requires no initialization + */ + status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI), + device_node, ACPI_TYPE_METHOD, &ini_node); + if (ACPI_FAILURE(status)) { + /* No _INI method found - move on to next device */ + + return_ACPI_STATUS(AE_OK); + } + + /* + * Run _STA to determine if we can run _INI on the device - + * the device must be present before _INI can be run. + * However, _STA is not required - assume device present if no _STA */ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, - pinfo.node, + device_node, METHOD_NAME__STA)); - status = acpi_ut_execute_STA(pinfo.node, &flags); + pinfo.node = device_node; + pinfo.parameters = NULL; + pinfo.parameter_type = ACPI_PARAM_ARGS; + + status = acpi_ut_execute_STA(pinfo.node, &flags); if (ACPI_FAILURE(status)) { - if (pinfo.node->type == ACPI_TYPE_DEVICE) { - /* Ignore error and move on to next device */ + /* Ignore error and move on to next device */ - return_ACPI_STATUS(AE_OK); - } + return_ACPI_STATUS(AE_OK); + } - /* _STA is not required for Processor or thermal_zone objects */ - } else { + if (flags != ACPI_UINT32_MAX) { info->num_STA++; + } - if (!(flags & 0x01)) { - /* Don't look at children of a not present device */ + if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + /* Don't look at children of a not present device */ - return_ACPI_STATUS(AE_CTRL_DEPTH); - } + return_ACPI_STATUS(AE_CTRL_DEPTH); } /* - * The device is present. Run _INI. + * The device is present and _INI exists. Run the _INI method. + * (We already have the _INI node from above) */ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, pinfo.node, METHOD_NAME__INI)); - status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo); - if (ACPI_FAILURE(status)) { - /* No _INI (AE_NOT_FOUND) means device requires no initialization */ - if (status != AE_NOT_FOUND) { - /* Ignore error and move on to next device */ + pinfo.node = ini_node; + status = acpi_ns_evaluate_by_handle(&pinfo); + if (ACPI_FAILURE(status)) { + /* Ignore error and move on to next device */ #ifdef ACPI_DEBUG_OUTPUT - char *scope_name = - acpi_ns_get_external_pathname(pinfo.node); + char *scope_name = acpi_ns_get_external_pathname(ini_node); - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n", - scope_name, - acpi_format_exception(status))); + ACPI_WARNING((AE_INFO, "%s._INI failed: %s", + scope_name, acpi_format_exception(status))); - ACPI_MEM_FREE(scope_name); + ACPI_MEM_FREE(scope_name); #endif - } - - status = AE_OK; } else { /* Delete any return object (especially if implicit_return is enabled) */ @@ -434,5 +441,5 @@ acpi_ns_init_one_device(acpi_handle obj_handle, acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); } - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index c28849de465a..4e0b0524c188 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,7 +92,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, /* Check validity of the AML start and length */ if (!table_desc->aml_start) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Null AML pointer\n")); + ACPI_ERROR((AE_INFO, "Null AML pointer")); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -102,8 +102,8 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, /* Ignore table if there is no AML contained within */ if (!table_desc->aml_length) { - ACPI_REPORT_WARNING(("Zero-length AML block in table [%4.4s]\n", - table_desc->pointer->signature)); + ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]", + table_desc->pointer->signature)); return_ACPI_STATUS(AE_OK); } @@ -263,7 +263,7 @@ acpi_status acpi_ns_load_namespace(void) /* There must be at least a DSDT installed */ if (acpi_gbl_DSDT == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "DSDT is not in memory\n")); + ACPI_ERROR((AE_INFO, "DSDT is not in memory")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index d5e8dea61c27..639f653b4b6b 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, acpi_size index; struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_NAME("ns_build_external_path"); + ACPI_FUNCTION_ENTRY(); /* Special case for root */ @@ -110,9 +110,9 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, name_buffer[index] = AML_ROOT_PREFIX; if (index != 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not construct pathname; index=%X, size=%X, Path=%s\n", - (u32) index, (u32) size, &name_buffer[size])); + ACPI_ERROR((AE_INFO, + "Could not construct pathname; index=%X, size=%X, Path=%s", + (u32) index, (u32) size, &name_buffer[size])); } return; @@ -148,7 +148,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) name_buffer = ACPI_MEM_CALLOCATE(size); if (!name_buffer) { - ACPI_REPORT_ERROR(("ns_get_table_pathname: allocation failure\n")); + ACPI_ERROR((AE_INFO, "Allocation failure")); return_PTR(NULL); } @@ -241,7 +241,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, acpi_ns_build_external_path(node, required_size, buffer->pointer); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X] \n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", (char *)buffer->pointer, (u32) required_size)); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index fc9be946ebed..10ae6292bca4 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,22 +84,23 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, if (!node) { /* Invalid handle */ - ACPI_REPORT_ERROR(("ns_attach_object: Null named_obj handle\n")); + ACPI_ERROR((AE_INFO, "Null named_obj handle")); return_ACPI_STATUS(AE_BAD_PARAMETER); } if (!object && (ACPI_TYPE_ANY != type)) { /* Null object */ - ACPI_REPORT_ERROR(("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n")); + ACPI_ERROR((AE_INFO, + "Null object, but type not ACPI_TYPE_ANY")); return_ACPI_STATUS(AE_BAD_PARAMETER); } if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { /* Not a name handle */ - ACPI_REPORT_ERROR(("ns_attach_object: Invalid handle %p [%s]\n", - node, acpi_ut_get_descriptor_name(node))); + ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", + node, acpi_ut_get_descriptor_name(node))); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -254,7 +255,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node); if (!node) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Null Node ptr\n")); + ACPI_WARNING((AE_INFO, "Null Node ptr")); return_PTR(NULL); } diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index 433442a9ec74..232be4303653 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 50a3ca5470ed..d64b78952f24 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -99,8 +99,8 @@ acpi_ns_search_node(u32 target_name, if (scope_name) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, node, - (char *)&target_name, + scope_name, node, ACPI_CAST_PTR(char, + &target_name), acpi_ut_get_type_name(type))); ACPI_MEM_FREE(scope_name); @@ -131,7 +131,7 @@ acpi_ns_search_node(u32 target_name, */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", - (char *)&target_name, + ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(next_node-> type), next_node, @@ -160,7 +160,8 @@ acpi_ns_search_node(u32 target_name, ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", - (char *)&target_name, acpi_ut_get_type_name(type), + ACPI_CAST_PTR(char, &target_name), + acpi_ut_get_type_name(type), acpi_ut_get_node_name(node), node, node->child)); return_ACPI_STATUS(AE_NOT_FOUND); @@ -210,14 +211,14 @@ acpi_ns_search_parent_tree(u32 target_name, */ if (!parent_node) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] has no parent\n", - (char *)&target_name)); + ACPI_CAST_PTR(char, &target_name))); return_ACPI_STATUS(AE_NOT_FOUND); } if (acpi_ns_local(type)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "[%4.4s] type [%s] must be local to this scope (no parent search)\n", - (char *)&target_name, + ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type))); return_ACPI_STATUS(AE_NOT_FOUND); } @@ -227,7 +228,7 @@ acpi_ns_search_parent_tree(u32 target_name, ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching parent [%4.4s] for [%4.4s]\n", acpi_ut_get_node_name(parent_node), - (char *)&target_name)); + ACPI_CAST_PTR(char, &target_name))); /* * Search parents until target is found or we have backed up to the root @@ -297,18 +298,17 @@ acpi_ns_search_and_enter(u32 target_name, /* Parameter validation */ if (!node || !target_name || !return_node) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Null param: Node %p Name %X return_node %p\n", - node, target_name, return_node)); - - ACPI_REPORT_ERROR(("ns_search_and_enter: Null parameter\n")); + ACPI_ERROR((AE_INFO, + "Null param: Node %p Name %X return_node %p", + node, target_name, return_node)); return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Name must consist of printable characters */ if (!acpi_ut_valid_acpi_name(target_name)) { - ACPI_REPORT_ERROR(("ns_search_and_enter: Bad character in ACPI Name: %X\n", target_name)); + ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X", + target_name)); return_ACPI_STATUS(AE_BAD_CHARACTER); } @@ -360,7 +360,7 @@ acpi_ns_search_and_enter(u32 target_name, if (interpreter_mode == ACPI_IMODE_EXECUTE) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s Not found in %p [Not adding]\n", - (char *)&target_name, node)); + ACPI_CAST_PTR(char, &target_name), node)); return_ACPI_STATUS(AE_NOT_FOUND); } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index ebec036423c9..3e7cad549a38 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,7 +63,6 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) * internal_name - Name or path of the namespace node * lookup_status - Exception code from NS lookup * @@ -76,19 +75,17 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); void acpi_ns_report_error(char *module_name, u32 line_number, - u32 component_id, char *internal_name, acpi_status lookup_status) { acpi_status status; char *name = NULL; - acpi_os_printf("%8s-%04d: *** Error: Looking up ", - module_name, line_number); + acpi_ut_report_error(module_name, line_number); if (lookup_status == AE_BAD_CHARACTER) { /* There is a non-ascii character in the name */ - acpi_os_printf("[0x%4.4X] (NON-ASCII)\n", + acpi_os_printf("[0x%4.4X] (NON-ASCII)", *(ACPI_CAST_PTR(u32, internal_name))); } else { /* Convert path to external format */ @@ -109,7 +106,7 @@ acpi_ns_report_error(char *module_name, } } - acpi_os_printf(" in namespace, %s\n", + acpi_os_printf(" Namespace lookup failure, %s\n", acpi_format_exception(lookup_status)); } @@ -119,10 +116,9 @@ acpi_ns_report_error(char *module_name, * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) * Message - Error message to use on failure * prefix_node - Prefix relative to the path - * Path - Path to the node + * Path - Path to the node (optional) * method_status - Execution status * * RETURN: None @@ -134,7 +130,6 @@ acpi_ns_report_error(char *module_name, void acpi_ns_report_method_error(char *module_name, u32 line_number, - u32 component_id, char *message, struct acpi_namespace_node *prefix_node, char *path, acpi_status method_status) @@ -142,17 +137,16 @@ acpi_ns_report_method_error(char *module_name, acpi_status status; struct acpi_namespace_node *node = prefix_node; + acpi_ut_report_error(module_name, line_number); + if (path) { status = acpi_ns_get_node_by_path(path, prefix_node, ACPI_NS_NO_UPSEARCH, &node); if (ACPI_FAILURE(status)) { - acpi_os_printf - ("report_method_error: Could not get node\n"); - return; + acpi_os_printf("[Could not get node by pathname]"); } } - acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number); acpi_ns_print_node_pathname(node, message); acpi_os_printf(", %s\n", acpi_format_exception(method_status)); } @@ -248,11 +242,11 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) ACPI_FUNCTION_TRACE("ns_get_type"); if (!node) { - ACPI_REPORT_WARNING(("ns_get_type: Null Node input pointer\n")); - return_VALUE(ACPI_TYPE_ANY); + ACPI_WARNING((AE_INFO, "Null Node parameter")); + return_UINT32(ACPI_TYPE_ANY); } - return_VALUE((acpi_object_type) node->type); + return_UINT32((acpi_object_type) node->type); } /******************************************************************************* @@ -275,11 +269,11 @@ u32 acpi_ns_local(acpi_object_type type) if (!acpi_ut_valid_object_type(type)) { /* Type code out of range */ - ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n")); - return_VALUE(ACPI_NS_NORMAL); + ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); + return_UINT32(ACPI_NS_NORMAL); } - return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); + return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); } /******************************************************************************* @@ -627,7 +621,7 @@ acpi_ns_externalize_name(u32 internal_name_length, * with internal_name (invalid format). */ if (required_length > internal_name_length) { - ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n")); + ACPI_ERROR((AE_INFO, "Invalid internal name")); return_ACPI_STATUS(AE_BAD_PATHNAME); } @@ -803,12 +797,11 @@ u32 acpi_ns_opens_scope(acpi_object_type type) if (!acpi_ut_valid_object_type(type)) { /* type code out of range */ - ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n", - type)); - return_VALUE(ACPI_NS_NORMAL); + ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); + return_UINT32(ACPI_NS_NORMAL); } - return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); + return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); } /******************************************************************************* diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 5f164c0df33b..fcab1e784b81 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index c07b046659ff..a95f636dc35d 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -112,8 +112,7 @@ acpi_evaluate_object_typed(acpi_handle handle, if (return_buffer->length == 0) { /* Error because caller specifically asked for a return value */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return value\n")); - + ACPI_ERROR((AE_INFO, "No return value")); return_ACPI_STATUS(AE_NULL_OBJECT); } @@ -125,11 +124,11 @@ acpi_evaluate_object_typed(acpi_handle handle, /* Return object type does not match requested type */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Incorrect return type [%s] requested [%s]\n", - acpi_ut_get_type_name(((union acpi_object *) - return_buffer->pointer)->type), - acpi_ut_get_type_name(return_type))); + ACPI_ERROR((AE_INFO, + "Incorrect return type [%s] requested [%s]", + acpi_ut_get_type_name(((union acpi_object *)return_buffer-> + pointer)->type), + acpi_ut_get_type_name(return_type))); if (must_free) { /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ @@ -236,11 +235,11 @@ acpi_evaluate_object(acpi_handle handle, * qualified names above, this is an error */ if (!pathname) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Both Handle and Pathname are NULL\n")); + ACPI_ERROR((AE_INFO, + "Both Handle and Pathname are NULL")); } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Handle is NULL and Pathname is relative\n")); + ACPI_ERROR((AE_INFO, + "Handle is NULL and Pathname is relative")); } status = AE_BAD_PARAMETER; @@ -399,7 +398,7 @@ acpi_walk_namespace(acpi_object_type type, /* Parameter validation */ - if ((type > ACPI_TYPE_EXTERNAL_MAX) || (!max_depth) || (!user_function)) { + if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -473,8 +472,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - if (!(flags & 0x01)) { - /* Don't return at the device or children of the device if not there */ + if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + /* Don't examine children of the device if not present */ return (AE_CTRL_DEPTH); } diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 6b5f8d4481d1..8cd8675a47c0 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -300,8 +300,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) status = acpi_ut_execute_CID(node, &cid_list); if (ACPI_SUCCESS(status)) { - size += ((acpi_size) cid_list->count - 1) * - sizeof(struct acpi_compatible_id); + size += cid_list->size; info->valid |= ACPI_VALID_CID; } diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index 0856d42e6909..a0332595677a 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 20c9a37643c7..ac5bbaedac1b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -838,7 +838,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) static const int quantum_ms = 1000 / HZ; ret = down_trylock(sem); - for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { + for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) { schedule_timeout_interruptible(1); ret = down_trylock(sem); } @@ -1060,13 +1060,11 @@ EXPORT_SYMBOL(max_cstate); * Acquire a spinlock. * * handle is a pointer to the spinlock_t. - * flags is *not* the result of save_flags - it is an ACPI-specific flag variable - * that indicates whether we are at interrupt level. */ -unsigned long acpi_os_acquire_lock(acpi_handle handle) +acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle) { - unsigned long flags; + acpi_cpu_flags flags; spin_lock_irqsave((spinlock_t *) handle, flags); return flags; } @@ -1075,7 +1073,7 @@ unsigned long acpi_os_acquire_lock(acpi_handle handle) * Release a spinlock. See above. */ -void acpi_os_release_lock(acpi_handle handle, unsigned long flags) +void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags) { spin_unlock_irqrestore((spinlock_t *) handle, flags); } diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 5858188f94a6..de573be52718 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,7 @@ #include <acpi/acparser.h> #include <acpi/amlcode.h> #include <acpi/acnamesp.h> +#include <acpi/acdispat.h> #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psargs") @@ -62,61 +63,51 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state * * PARAMETERS: parser_state - Current parser state object * - * RETURN: Decoded package length. On completion, the AML pointer points + * RETURN: Decoded package length. On completion, the AML pointer points * past the length byte or bytes. * - * DESCRIPTION: Decode and return a package length field + * DESCRIPTION: Decode and return a package length field. + * Note: Largest package length is 28 bits, from ACPI specification * ******************************************************************************/ static u32 acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) { - u32 encoded_length; - u32 length = 0; + u8 *aml = parser_state->aml; + u32 package_length = 0; + acpi_native_uint byte_count; + u8 byte_zero_mask = 0x3F; /* Default [0:5] */ ACPI_FUNCTION_TRACE("ps_get_next_package_length"); - encoded_length = (u32) ACPI_GET8(parser_state->aml); - parser_state->aml++; - - switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */ - case 0: /* 1-byte encoding (bits 0-5) */ - - length = (encoded_length & 0x3F); - break; - - case 1: /* 2-byte encoding (next byte + bits 0-3) */ - - length = ((ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml++; - break; - - case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ - - length = ((ACPI_GET8(parser_state->aml + 1) << 12) | - (ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml += 2; - break; + /* + * Byte 0 bits [6:7] contain the number of additional bytes + * used to encode the package length, either 0,1,2, or 3 + */ + byte_count = (aml[0] >> 6); + parser_state->aml += (byte_count + 1); - case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ + /* Get bytes 3, 2, 1 as needed */ - length = ((ACPI_GET8(parser_state->aml + 2) << 20) | - (ACPI_GET8(parser_state->aml + 1) << 12) | - (ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml += 3; - break; - - default: + while (byte_count) { + /* + * Final bit positions for the package length bytes: + * Byte3->[20:27] + * Byte2->[12:19] + * Byte1->[04:11] + * Byte0->[00:03] + */ + package_length |= (aml[byte_count] << ((byte_count << 3) - 4)); - /* Can't get here, only 2 bits / 4 cases */ - break; + byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */ + byte_count--; } - return_VALUE(length); + /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ + + package_length |= (aml[0] & byte_zero_mask); + return_UINT32(package_length); } /******************************************************************************* @@ -135,16 +126,15 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) { u8 *start = parser_state->aml; - acpi_native_uint length; + u32 package_length; ACPI_FUNCTION_TRACE("ps_get_next_package_end"); - /* Function below changes parser_state->Aml */ + /* Function below updates parser_state->Aml */ - length = - (acpi_native_uint) acpi_ps_get_next_package_length(parser_state); + package_length = acpi_ps_get_next_package_length(parser_state); - return_PTR(start + length); /* end of package */ + return_PTR(start + package_length); /* end of package */ } /******************************************************************************* @@ -169,17 +159,15 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) ACPI_FUNCTION_TRACE("ps_get_next_namestring"); - /* Handle multiple prefix characters */ - - while (acpi_ps_is_prefix_char(ACPI_GET8(end))) { - /* Include prefix '\\' or '^' */ + /* Point past any namestring prefix characters (backslash or carat) */ + while (acpi_ps_is_prefix_char(*end)) { end++; } - /* Decode the path */ + /* Decode the path prefix character */ - switch (ACPI_GET8(end)) { + switch (*end) { case 0: /* null_name */ @@ -199,9 +187,9 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) case AML_MULTI_NAME_PREFIX_OP: - /* Multiple name segments, 4 chars each */ + /* Multiple name segments, 4 chars each, count in next byte */ - end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE); + end += 2 + (*(end + 1) * ACPI_NAME_SIZE); break; default: @@ -212,7 +200,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) break; } - parser_state->aml = (u8 *) end; + parser_state->aml = end; return_PTR((char *)start); } @@ -224,7 +212,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) * Arg - Where the namepath will be stored * arg_count - If the namepath points to a control method * the method's argument is returned here. - * method_call - Whether the namepath can possibly be the + * possible_method_call - Whether the namepath can possibly be the * start of a method call * * RETURN: Status @@ -240,11 +228,11 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) acpi_status acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, struct acpi_parse_state *parser_state, - union acpi_parse_object *arg, u8 method_call) + union acpi_parse_object *arg, u8 possible_method_call) { char *path; union acpi_parse_object *name_op; - acpi_status status = AE_OK; + acpi_status status; union acpi_operand_object *method_desc; struct acpi_namespace_node *node; union acpi_generic_state scope_info; @@ -252,115 +240,129 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE("ps_get_next_namepath"); path = acpi_ps_get_next_namestring(parser_state); + acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); - /* Null path case is allowed */ + /* Null path case is allowed, just exit */ - if (path) { - /* - * Lookup the name in the internal namespace - */ - scope_info.scope.node = NULL; - node = parser_state->start_node; - if (node) { - scope_info.scope.node = node; - } + if (!path) { + arg->common.value.name = path; + return_ACPI_STATUS(AE_OK); + } - /* - * Lookup object. We don't want to add anything new to the namespace - * here, however. So we use MODE_EXECUTE. Allow searching of the - * parent tree, but don't open a new scope -- we just want to lookup the - * object (MUST BE mode EXECUTE to perform upsearch) - */ - status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, - ACPI_NS_SEARCH_PARENT | - ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); - if (ACPI_SUCCESS(status) && method_call) { - if (node->type == ACPI_TYPE_METHOD) { - /* This name is actually a control method invocation */ - - method_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Control Method - %p Desc %p Path=%p\n", - node, method_desc, path)); - - name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); - if (!name_op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } + /* Setup search scope info */ - /* Change arg into a METHOD CALL and attach name to it */ + scope_info.scope.node = NULL; + node = parser_state->start_node; + if (node) { + scope_info.scope.node = node; + } - acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); - name_op->common.value.name = path; + /* + * Lookup the name in the internal namespace. We don't want to add + * anything new to the namespace here, however, so we use MODE_EXECUTE. + * Allow searching of the parent tree, but don't open a new scope - + * we just want to lookup the object (must be mode EXECUTE to perform + * the upsearch) + */ + status = + acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &node); - /* Point METHODCALL/NAME to the METHOD Node */ + /* + * If this name is a control method invocation, we must + * setup the method call + */ + if (ACPI_SUCCESS(status) && + possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + /* This name is actually a control method invocation */ - name_op->common.node = node; - acpi_ps_append_arg(arg, name_op); + method_desc = acpi_ns_get_attached_object(node); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Control Method - %p Desc %p Path=%p\n", node, + method_desc, path)); - if (!method_desc) { - ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } + name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + if (!name_op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Control Method - %p Args %X\n", - node, - method_desc->method. - param_count)); + /* Change Arg into a METHOD CALL and attach name to it */ - /* Get the number of arguments to expect */ + acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); + name_op->common.value.name = path; - walk_state->arg_count = - method_desc->method.param_count; - return_ACPI_STATUS(AE_OK); - } + /* Point METHODCALL/NAME to the METHOD Node */ - /* - * Else this is normal named object reference. - * Just init the NAMEPATH object with the pathname. - * (See code below) - */ - } + name_op->common.node = node; + acpi_ps_append_arg(arg, name_op); - if (ACPI_FAILURE(status)) { - /* - * 1) Any error other than NOT_FOUND is always severe - * 2) NOT_FOUND is only important if we are executing a method. - * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok. - */ - if ((((walk_state-> - parse_flags & ACPI_PARSE_MODE_MASK) == - ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND) - && (walk_state->op->common.aml_opcode != - AML_COND_REF_OF_OP)) - || (status != AE_NOT_FOUND)) { - ACPI_REPORT_NSERROR(path, status); - - acpi_os_printf - ("search_node %p start_node %p return_node %p\n", - scope_info.scope.node, - parser_state->start_node, node); - - } else { - /* - * We got a NOT_FOUND during table load or we encountered - * a cond_ref_of(x) where the target does not exist. - * Either case is ok - */ - status = AE_OK; - } + if (!method_desc) { + ACPI_ERROR((AE_INFO, + "Control Method %p has no attached object", + node)); + return_ACPI_STATUS(AE_AML_INTERNAL); } + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Control Method - %p Args %X\n", + node, method_desc->method.param_count)); + + /* Get the number of arguments to expect */ + + walk_state->arg_count = method_desc->method.param_count; + return_ACPI_STATUS(AE_OK); } /* - * Regardless of success/failure above, - * Just initialize the Op with the pathname. + * Special handling if the name was not found during the lookup - + * some not_found cases are allowed */ - acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); - arg->common.value.name = path; + if (status == AE_NOT_FOUND) { + /* 1) not_found is ok during load pass 1/2 (allow forward references) */ + + if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != + ACPI_PARSE_EXECUTE) { + status = AE_OK; + } + + /* 2) not_found during a cond_ref_of(x) is ok by definition */ + + else if (walk_state->op->common.aml_opcode == + AML_COND_REF_OF_OP) { + status = AE_OK; + } + + /* + * 3) not_found while building a Package is ok at this point, we + * may flag as an error later if slack mode is not enabled. + * (Some ASL code depends on allowing this behavior) + */ + else if ((arg->common.parent) && + ((arg->common.parent->common.aml_opcode == + AML_PACKAGE_OP) + || (arg->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP))) { + status = AE_OK; + } + } + + /* Final exception check (may have been changed from code above) */ + if (ACPI_FAILURE(status)) { + ACPI_ERROR_NAMESPACE(path, status); + + if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) { + /* Report a control method execution error */ + + status = acpi_ds_method_error(status, walk_state); + } + } + + /* Save the namepath */ + + arg->common.value.name = path; return_ACPI_STATUS(status); } @@ -382,59 +384,63 @@ void acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, u32 arg_type, union acpi_parse_object *arg) { + u32 length; + u16 opcode; + u8 *aml = parser_state->aml; ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); switch (arg_type) { case ARGP_BYTEDATA: - acpi_ps_init_op(arg, AML_BYTE_OP); - arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml); - parser_state->aml++; + /* Get 1 byte from the AML stream */ + + opcode = AML_BYTE_OP; + arg->common.value.integer = (acpi_integer) * aml; + length = 1; break; case ARGP_WORDDATA: - acpi_ps_init_op(arg, AML_WORD_OP); - /* Get 2 bytes from the AML stream */ - ACPI_MOVE_16_TO_32(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 2; + opcode = AML_WORD_OP; + ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); + length = 2; break; case ARGP_DWORDDATA: - acpi_ps_init_op(arg, AML_DWORD_OP); - /* Get 4 bytes from the AML stream */ - ACPI_MOVE_32_TO_32(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 4; + opcode = AML_DWORD_OP; + ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); + length = 4; break; case ARGP_QWORDDATA: - acpi_ps_init_op(arg, AML_QWORD_OP); - /* Get 8 bytes from the AML stream */ - ACPI_MOVE_64_TO_64(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 8; + opcode = AML_QWORD_OP; + ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); + length = 8; break; case ARGP_CHARLIST: - acpi_ps_init_op(arg, AML_STRING_OP); - arg->common.value.string = (char *)parser_state->aml; + /* Get a pointer to the string, point past the string */ + + opcode = AML_STRING_OP; + arg->common.value.string = ACPI_CAST_PTR(char, aml); - while (ACPI_GET8(parser_state->aml) != '\0') { - parser_state->aml++; + /* Find the null terminator */ + + length = 0; + while (aml[length]) { + length++; } - parser_state->aml++; + length++; break; case ARGP_NAME: @@ -443,14 +449,16 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); arg->common.value.name = acpi_ps_get_next_namestring(parser_state); - break; + return_VOID; default: - ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type)); - break; + ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type)); + return_VOID; } + acpi_ps_init_op(arg, opcode); + parser_state->aml += length; return_VOID; } @@ -540,7 +548,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state * access_type is first operand, access_attribute is second */ field->common.value.integer = - (ACPI_GET8(parser_state->aml) << 8); + (((u32) ACPI_GET8(parser_state->aml) << 8)); parser_state->aml++; field->common.value.integer |= ACPI_GET8(parser_state->aml); parser_state->aml++; @@ -703,7 +711,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, default: - ACPI_REPORT_ERROR(("Invalid arg_type: %X\n", arg_type)); + ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type)); status = AE_AML_OPERAND_TYPE; break; } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 088d33999d90..00b072e15d19 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,16 +123,12 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) && ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { if (status == AE_AML_NO_RETURN_VALUE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invoked method did not return a value, %s\n", - acpi_format_exception - (status))); + ACPI_EXCEPTION((AE_INFO, status, + "Invoked method did not return a value")); } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "get_predicate Failed, %s\n", - acpi_format_exception - (status))); + ACPI_EXCEPTION((AE_INFO, status, + "get_predicate Failed")); return_ACPI_STATUS(status); } @@ -190,11 +186,11 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) /* The opcode is unrecognized. Just skip unknown opcodes */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Found unknown opcode %X at AML address %p offset %X, ignoring\n", - walk_state->opcode, - parser_state->aml, - walk_state->aml_offset)); + ACPI_ERROR((AE_INFO, + "Found unknown opcode %X at AML address %p offset %X, ignoring", + walk_state->opcode, + parser_state->aml, + walk_state->aml_offset)); ACPI_DUMP_BUFFER(parser_state->aml, 128); @@ -281,10 +277,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) walk_state->descending_callback(walk_state, &op); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "During name lookup/catalog, %s\n", - acpi_format_exception - (status))); + ACPI_EXCEPTION((AE_INFO, status, + "During name lookup/catalog")); goto close_this_op; } @@ -704,6 +698,15 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); + + if (op->common.aml_opcode != AML_WHILE_OP) { + status2 = + acpi_ds_result_stack_pop + (walk_state); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } } /* Close this iteration of the While loop */ diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 229ae86afe8b..11d6351ab8b2 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -747,7 +747,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) /* Unknown AML opcode */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Unknown AML opcode [%4.4X]\n", opcode)); return (&acpi_gbl_aml_op_info[_UNK]); diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 76d4d640d83c..a9f3229f4106 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -333,7 +333,6 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, switch (callback_status) { case AE_CTRL_TERMINATE: - /* * A control method was terminated via a RETURN statement. * The walk of this method is complete. @@ -346,13 +345,19 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, parser_state->aml = walk_state->aml_last_while; walk_state->control_state->common.value = FALSE; - status = AE_CTRL_BREAK; + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_SUCCESS(status)) { + status = AE_CTRL_BREAK; + } break; case AE_CTRL_CONTINUE: parser_state->aml = walk_state->aml_last_while; - status = AE_CTRL_CONTINUE; + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_SUCCESS(status)) { + status = AE_CTRL_CONTINUE; + } break; case AE_CTRL_PENDING: @@ -369,16 +374,18 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, #endif case AE_CTRL_TRUE: - /* * Predicate of an IF was true, and we are at the matching ELSE. * Just close out this package */ parser_state->aml = acpi_ps_get_next_package_end(parser_state); + status = acpi_ds_result_stack_pop(walk_state); + if (ACPI_SUCCESS(status)) { + status = AE_CTRL_PENDING; + } break; case AE_CTRL_FALSE: - /* * Either an IF/WHILE Predicate was false or we encountered a BREAK * opcode. In both cases, we do not execute the rest of the @@ -503,22 +510,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) } else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } else if ((status != AE_OK) && (walk_state->method_desc)) { - ACPI_REPORT_METHOD_ERROR("Method execution failed", - walk_state->method_node, NULL, - status); - - /* Ensure proper cleanup */ + /* Either the method parse or actual execution failed */ - walk_state->parse_flags |= ACPI_PARSE_EXECUTE; + ACPI_ERROR_METHOD("Method parse/execution failed", + walk_state->method_node, NULL, + status); /* Check for possible multi-thread reentrancy problem */ if ((status == AE_ALREADY_EXISTS) && (!walk_state->method_desc->method.semaphore)) { /* - * This method is marked not_serialized, but it tried to create + * Method tried to create an object twice. The probable cause is + * that the method cannot handle reentrancy. + * + * The method is marked not_serialized, but it tried to create * a named object, causing the second thread entrance to fail. - * We will workaround this by marking the method permanently + * Workaround this problem by marking the method permanently * as Serialized. */ walk_state->method_desc->method.method_flags |= @@ -536,15 +544,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) acpi_ds_scope_stack_clear(walk_state); /* - * If we just returned from the execution of a control method, - * there's lots of cleanup to do + * If we just returned from the execution of a control method or if we + * encountered an error during the method parse phase, there's lots of + * cleanup to do */ - if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == - ACPI_PARSE_EXECUTE) { + if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { if (walk_state->method_desc) { /* Decrement the thread count on the method parse tree */ - walk_state->method_desc->method.thread_count--; + if (walk_state->method_desc->method. + thread_count) { + walk_state->method_desc->method. + thread_count--; + } else { + ACPI_ERROR((AE_INFO, + "Invalid zero thread count in method")); + } } acpi_ds_terminate_control_method(walk_state); @@ -553,7 +569,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) /* Delete this walk state and all linked control states */ acpi_ps_cleanup_scope(&walk_state->parser_state); - previous_walk_state = walk_state; ACPI_DEBUG_PRINT((ACPI_DB_PARSE, diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index 1c953b6f1af1..bc6047caccd9 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index f0e755884eea..dd6f16726fc4 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,7 +132,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) if (op_info->class == AML_CLASS_UNKNOWN) { /* Invalid opcode */ - ACPI_REPORT_ERROR(("ps_append_arg: Invalid AML Opcode: 0x%2.2X\n", op->common.aml_opcode)); + ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", + op->common.aml_opcode)); return; } diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 2075efbb4324..3e07cb9cb748 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 08f2321b6ded..06f05bfd7612 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 4dcbd443160e..2dd48cbb7c02 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,6 +50,10 @@ ACPI_MODULE_NAME("psxface") /* Local Prototypes */ +static void acpi_ps_start_trace(struct acpi_parameter_info *info); + +static void acpi_ps_stop_trace(struct acpi_parameter_info *info); + static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info); static void @@ -57,6 +61,136 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action); /******************************************************************************* * + * FUNCTION: acpi_debug_trace + * + * PARAMETERS: method_name - Valid ACPI name string + * debug_level - Optional level mask. 0 to use default + * debug_layer - Optional layer mask. 0 to use default + * Flags - bit 1: one shot(1) or persistent(0) + * + * RETURN: Status + * + * DESCRIPTION: External interface to enable debug tracing during control + * method execution + * + ******************************************************************************/ + +acpi_status +acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) +{ + acpi_status status; + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* TBDs: Validate name, allow full path or just nameseg */ + + acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name); + acpi_gbl_trace_flags = flags; + + if (debug_level) { + acpi_gbl_trace_dbg_level = debug_level; + } + if (debug_layer) { + acpi_gbl_trace_dbg_layer = debug_layer; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_start_trace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +static void acpi_ps_start_trace(struct acpi_parameter_info *info) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return; + } + + if ((!acpi_gbl_trace_method_name) || + (acpi_gbl_trace_method_name != info->node->name.integer)) { + goto exit; + } + + acpi_gbl_original_dbg_level = acpi_dbg_level; + acpi_gbl_original_dbg_layer = acpi_dbg_layer; + + acpi_dbg_level = 0x00FFFFFF; + acpi_dbg_layer = ACPI_UINT32_MAX; + + if (acpi_gbl_trace_dbg_level) { + acpi_dbg_level = acpi_gbl_trace_dbg_level; + } + if (acpi_gbl_trace_dbg_layer) { + acpi_dbg_layer = acpi_gbl_trace_dbg_layer; + } + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_stop_trace + * + * PARAMETERS: Info - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +static void acpi_ps_stop_trace(struct acpi_parameter_info *info) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return; + } + + if ((!acpi_gbl_trace_method_name) || + (acpi_gbl_trace_method_name != info->node->name.integer)) { + goto exit; + } + + /* Disable further tracing if type is one-shot */ + + if (acpi_gbl_trace_flags & 1) { + acpi_gbl_trace_method_name = 0; + acpi_gbl_trace_dbg_level = 0; + acpi_gbl_trace_dbg_layer = 0; + } + + acpi_dbg_level = acpi_gbl_original_dbg_level; + acpi_dbg_layer = acpi_gbl_original_dbg_layer; + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +} + +/******************************************************************************* + * * FUNCTION: acpi_ps_execute_method * * PARAMETERS: Info - Method info block, contains: @@ -104,6 +238,10 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) */ acpi_ps_update_parameter_list(info, REF_INCREMENT); + /* Begin tracing if requested */ + + acpi_ps_start_trace(info); + /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace @@ -129,6 +267,10 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) status = acpi_ps_execute_pass(info); cleanup: + /* End optional tracing */ + + acpi_ps_stop_trace(info); + /* Take away the extra reference that we gave the parameters above */ acpi_ps_update_parameter_list(info, REF_DECREMENT); diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index e567c03b238e..65aee79b3971 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -258,7 +258,7 @@ typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **); static int acpi_pci_allocate_irq(struct acpi_prt_entry *entry, - int *edge_level, int *active_high_low, char **link) + int *triggering, int *polarity, char **link) { int irq; @@ -266,8 +266,8 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, if (entry->link.handle) { irq = acpi_pci_link_allocate_irq(entry->link.handle, - entry->link.index, edge_level, - active_high_low, link); + entry->link.index, triggering, + polarity, link); if (irq < 0) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); @@ -275,8 +275,8 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, } } else { irq = entry->link.index; - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; + *triggering = ACPI_LEVEL_SENSITIVE; + *polarity = ACPI_ACTIVE_LOW; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); @@ -285,7 +285,7 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, static int acpi_pci_free_irq(struct acpi_prt_entry *entry, - int *edge_level, int *active_high_low, char **link) + int *triggering, int *polarity, char **link) { int irq; @@ -307,8 +307,8 @@ static int acpi_pci_irq_lookup(struct pci_bus *bus, int device, int pin, - int *edge_level, - int *active_high_low, char **link, irq_lookup_func func) + int *triggering, + int *polarity, char **link, irq_lookup_func func) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); @@ -327,7 +327,7 @@ acpi_pci_irq_lookup(struct pci_bus *bus, return_VALUE(-1); } - ret = func(entry, edge_level, active_high_low, link); + ret = func(entry, triggering, polarity, link); return_VALUE(ret); } @@ -339,8 +339,8 @@ acpi_pci_irq_lookup(struct pci_bus *bus, static int acpi_pci_irq_derive(struct pci_dev *dev, int pin, - int *edge_level, - int *active_high_low, char **link, irq_lookup_func func) + int *triggering, + int *polarity, char **link, irq_lookup_func func) { struct pci_dev *bridge = dev; int irq = -1; @@ -374,7 +374,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low, + pin, triggering, polarity, link, func); } @@ -401,8 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) { int irq = 0; u8 pin = 0; - int edge_level = ACPI_LEVEL_SENSITIVE; - int active_high_low = ACPI_ACTIVE_LOW; + int triggering = ACPI_LEVEL_SENSITIVE; + int polarity = ACPI_ACTIVE_LOW; char *link = NULL; int rc; @@ -431,7 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * values override any BIOS-assigned IRQs set during boot. */ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, &link, + &triggering, &polarity, &link, acpi_pci_allocate_irq); /* @@ -439,8 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * device's parent bridge. */ if (irq < 0) - irq = acpi_pci_irq_derive(dev, pin, &edge_level, - &active_high_low, &link, + irq = acpi_pci_irq_derive(dev, pin, &triggering, + &polarity, &link, acpi_pci_allocate_irq); /* @@ -462,7 +462,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) } } - rc = acpi_register_gsi(irq, edge_level, active_high_low); + rc = acpi_register_gsi(irq, triggering, polarity); if (rc < 0) { printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: failed " "to register GSI\n", pci_name(dev), ('A' + pin)); @@ -477,8 +477,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) printk("Link [%s] -> ", link); printk("GSI %u (%s, %s) -> IRQ %d\n", irq, - (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", - (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); + (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", + (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); return_VALUE(0); } @@ -494,8 +494,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev) { int gsi = 0; u8 pin = 0; - int edge_level = ACPI_LEVEL_SENSITIVE; - int active_high_low = ACPI_ACTIVE_LOW; + int triggering = ACPI_LEVEL_SENSITIVE; + int polarity = ACPI_ACTIVE_LOW; ACPI_FUNCTION_TRACE("acpi_pci_irq_disable"); @@ -511,7 +511,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) * First we check the PCI IRQ routing table (PRT) for an IRQ. */ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, NULL, + &triggering, &polarity, NULL, acpi_pci_free_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the @@ -519,7 +519,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low, NULL, + &triggering, &polarity, NULL, acpi_pci_free_irq); if (gsi < 0) return_VOID; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 78927c0f1551..07bc6dfe662b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -70,8 +70,8 @@ static struct acpi_driver acpi_pci_link_driver = { */ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ - u8 edge_level; /* All IRQs */ - u8 active_high_low; /* All IRQs */ + u8 triggering; /* All IRQs */ + u8 polarity; /* All IRQs */ u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; @@ -108,19 +108,19 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible"); - switch (resource->id) { - case ACPI_RSTYPE_START_DPF: + switch (resource->type) { + case ACPI_RESOURCE_TYPE_START_DEPENDENT: return_ACPI_STATUS(AE_OK); - case ACPI_RSTYPE_IRQ: + case ACPI_RESOURCE_TYPE_IRQ: { struct acpi_resource_irq *p = &resource->data.irq; - if (!p || !p->number_of_interrupts) { + if (!p || !p->interrupt_count) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n")); return_ACPI_STATUS(AE_OK); } for (i = 0; - (i < p->number_of_interrupts + (i < p->interrupt_count && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { if (!p->interrupts[i]) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, @@ -131,22 +131,22 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) link->irq.possible[i] = p->interrupts[i]; link->irq.possible_count++; } - link->irq.edge_level = p->edge_level; - link->irq.active_high_low = p->active_high_low; - link->irq.resource_type = ACPI_RSTYPE_IRQ; + link->irq.triggering = p->triggering; + link->irq.polarity = p->polarity; + link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ; break; } - case ACPI_RSTYPE_EXT_IRQ: + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: { - struct acpi_resource_ext_irq *p = + struct acpi_resource_extended_irq *p = &resource->data.extended_irq; - if (!p || !p->number_of_interrupts) { + if (!p || !p->interrupt_count) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank EXT IRQ resource\n")); return_ACPI_STATUS(AE_OK); } for (i = 0; - (i < p->number_of_interrupts + (i < p->interrupt_count && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { if (!p->interrupts[i]) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, @@ -157,9 +157,9 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) link->irq.possible[i] = p->interrupts[i]; link->irq.possible_count++; } - link->irq.edge_level = p->edge_level; - link->irq.active_high_low = p->active_high_low; - link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ; + link->irq.triggering = p->triggering; + link->irq.polarity = p->polarity; + link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; break; } default: @@ -201,11 +201,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) ACPI_FUNCTION_TRACE("acpi_pci_link_check_current"); - switch (resource->id) { - case ACPI_RSTYPE_IRQ: + switch (resource->type) { + case ACPI_RESOURCE_TYPE_IRQ: { struct acpi_resource_irq *p = &resource->data.irq; - if (!p || !p->number_of_interrupts) { + if (!p || !p->interrupt_count) { /* * IRQ descriptors may have no IRQ# bits set, * particularly those those w/ _STA disabled @@ -217,11 +217,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) *irq = p->interrupts[0]; break; } - case ACPI_RSTYPE_EXT_IRQ: + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: { - struct acpi_resource_ext_irq *p = + struct acpi_resource_extended_irq *p = &resource->data.extended_irq; - if (!p || !p->number_of_interrupts) { + if (!p || !p->interrupt_count) { /* * extended IRQ descriptors must * return at least 1 IRQ @@ -233,8 +233,10 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) *irq = p->interrupts[0]; break; } + break; default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n")); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource %d isn't an IRQ\n", resource->type)); + case ACPI_RESOURCE_TYPE_END_TAG: return_ACPI_STATUS(AE_OK); } return_ACPI_STATUS(AE_CTRL_TERMINATE); @@ -325,36 +327,36 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) buffer.pointer = resource; switch (link->irq.resource_type) { - case ACPI_RSTYPE_IRQ: - resource->res.id = ACPI_RSTYPE_IRQ; + case ACPI_RESOURCE_TYPE_IRQ: + resource->res.type = ACPI_RESOURCE_TYPE_IRQ; resource->res.length = sizeof(struct acpi_resource); - resource->res.data.irq.edge_level = link->irq.edge_level; - resource->res.data.irq.active_high_low = - link->irq.active_high_low; - if (link->irq.edge_level == ACPI_EDGE_SENSITIVE) - resource->res.data.irq.shared_exclusive = + resource->res.data.irq.triggering = link->irq.triggering; + resource->res.data.irq.polarity = + link->irq.polarity; + if (link->irq.triggering == ACPI_EDGE_SENSITIVE) + resource->res.data.irq.sharable = ACPI_EXCLUSIVE; else - resource->res.data.irq.shared_exclusive = ACPI_SHARED; - resource->res.data.irq.number_of_interrupts = 1; + resource->res.data.irq.sharable = ACPI_SHARED; + resource->res.data.irq.interrupt_count = 1; resource->res.data.irq.interrupts[0] = irq; break; - case ACPI_RSTYPE_EXT_IRQ: - resource->res.id = ACPI_RSTYPE_EXT_IRQ; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; resource->res.length = sizeof(struct acpi_resource); resource->res.data.extended_irq.producer_consumer = ACPI_CONSUMER; - resource->res.data.extended_irq.edge_level = - link->irq.edge_level; - resource->res.data.extended_irq.active_high_low = - link->irq.active_high_low; - if (link->irq.edge_level == ACPI_EDGE_SENSITIVE) - resource->res.data.irq.shared_exclusive = + resource->res.data.extended_irq.triggering = + link->irq.triggering; + resource->res.data.extended_irq.polarity = + link->irq.polarity; + if (link->irq.triggering == ACPI_EDGE_SENSITIVE) + resource->res.data.irq.sharable = ACPI_EXCLUSIVE; else - resource->res.data.irq.shared_exclusive = ACPI_SHARED; - resource->res.data.extended_irq.number_of_interrupts = 1; + resource->res.data.irq.sharable = ACPI_SHARED; + resource->res.data.extended_irq.interrupt_count = 1; resource->res.data.extended_irq.interrupts[0] = irq; /* ignore resource_source, it's optional */ break; @@ -364,7 +366,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) goto end; } - resource->end.id = ACPI_RSTYPE_END_TAG; + resource->end.type = ACPI_RESOURCE_TYPE_END_TAG; /* Attempt to set the resource */ status = acpi_set_current_resources(link->handle, &buffer); @@ -613,7 +615,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) int acpi_pci_link_allocate_irq(acpi_handle handle, int index, - int *edge_level, int *active_high_low, char **name) + int *triggering, int *polarity, char **name) { int result = 0; struct acpi_device *device = NULL; @@ -653,10 +655,10 @@ acpi_pci_link_allocate_irq(acpi_handle handle, link->refcnt++; up(&acpi_link_lock); - if (edge_level) - *edge_level = link->irq.edge_level; - if (active_high_low) - *active_high_low = link->irq.active_high_low; + if (triggering) + *triggering = link->irq.triggering; + if (polarity) + *polarity = link->irq.polarity; if (name) *name = acpi_device_bid(link->device); ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0fd9988c283d..4c313eab6313 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -122,15 +122,15 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) int *busnr = (int *)data; struct acpi_resource_address64 address; - if (resource->id != ACPI_RSTYPE_ADDRESS16 && - resource->id != ACPI_RSTYPE_ADDRESS32 && - resource->id != ACPI_RSTYPE_ADDRESS64) + if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS64) return AE_OK; acpi_resource_to_address64(resource, &address); if ((address.address_length > 0) && (address.resource_type == ACPI_BUS_NUMBER_RANGE)) - *busnr = address.min_address_range; + *busnr = address.minimum; return AE_OK; } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 1278aca96fe3..99a3a28594da 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -253,31 +253,21 @@ static int acpi_processor_errata(struct acpi_processor *pr) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ - -int acpi_processor_set_pdc(struct acpi_processor *pr, - struct acpi_object_list *pdc_in) +static int acpi_processor_set_pdc(struct acpi_processor *pr) { + struct acpi_object_list *pdc_in = pr->pdc; acpi_status status = AE_OK; - u32 arg0_buf[3]; - union acpi_object arg0 = { ACPI_TYPE_BUFFER }; - struct acpi_object_list no_object = { 1, &arg0 }; - struct acpi_object_list *pdc; ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0] = ACPI_PDC_REVISION_ID; - arg0_buf[1] = 0; - arg0_buf[2] = 0; - - pdc = (pdc_in) ? pdc_in : &no_object; + if (!pdc_in) + return_VALUE(status); - status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); + status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); - if ((ACPI_FAILURE(status)) && (pdc_in)) + if (ACPI_FAILURE(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Error evaluating _PDC, using legacy perf. control...\n")); + "Could not evaluate _PDC, using legacy perf. control...\n")); return_VALUE(status); } @@ -357,7 +347,6 @@ static int acpi_processor_add_fs(struct acpi_device *device) ACPI_PROCESSOR_FILE_THROTTLING)); else { entry->proc_fops = &acpi_processor_throttling_fops; - entry->proc_fops->write = acpi_processor_write_throttling; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -372,7 +361,6 @@ static int acpi_processor_add_fs(struct acpi_device *device) ACPI_PROCESSOR_FILE_LIMIT)); else { entry->proc_fops = &acpi_processor_limit_fops; - entry->proc_fops->write = acpi_processor_write_limit; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -589,6 +577,10 @@ static int acpi_processor_start(struct acpi_device *device) "Error installing device notify handler\n")); } + /* _PDC call should be done before doing anything else (if reqd.). */ + arch_acpi_processor_init_pdc(pr); + acpi_processor_set_pdc(pr); + acpi_processor_power_init(pr, device); if (pr->flags.throttling) { diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index cc049338e418..eb730a80952c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -94,23 +94,60 @@ static int set_max_cstate(struct dmi_system_id *id) return 0; } -static struct dmi_system_id __initdata processor_power_dmi_table[] = { - {set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR, - "IBM"), - DMI_MATCH(DMI_BIOS_VERSION, - "1SET60WW")}, - (void *)1}, - {set_max_cstate, "Medion 41700", { - DMI_MATCH(DMI_BIOS_VENDOR, - "Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION, - "R01-A1J")}, (void *)1}, - {set_max_cstate, "Clevo 5600D", { - DMI_MATCH(DMI_BIOS_VENDOR, - "Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION, - "SHE845M0.86C.0013.D.0302131307")}, +/* Actually this shouldn't be __cpuinitdata, would be better to fix the + callers to only run once -AK */ +static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1}, + { set_max_cstate, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1}, + { set_max_cstate, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), + DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1}, + { set_max_cstate, "Clevo 5600D", { + DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), + DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, (void *)2}, {}, }; @@ -550,18 +587,10 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) if (!pr->pblk) return_VALUE(-ENODEV); - memset(pr->power.states, 0, sizeof(pr->power.states)); - /* if info is obtained from pblk/fadt, type equals state */ - pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; - /* the C0 state only exists as a filler in our array, - * and all processors need to support C1 */ - pr->power.states[ACPI_STATE_C0].valid = 1; - pr->power.states[ACPI_STATE_C1].valid = 1; - #ifndef CONFIG_HOTPLUG_CPU /* * Check for P_LVL2_UP flag before entering C2 and above on @@ -591,12 +620,11 @@ static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) { ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); + /* Zero initialize all the C-states info. */ memset(pr->power.states, 0, sizeof(pr->power.states)); - /* if info is obtained from pblk/fadt, type equals state */ + /* set the first C-State to C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; - pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; - pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; /* the C0 state only exists as a filler in our array, * and all processors need to support C1 */ @@ -610,6 +638,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { acpi_status status = 0; acpi_integer count; + int current_count; int i; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *cst; @@ -619,10 +648,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) if (nocst) return_VALUE(-ENODEV); - pr->power.count = 0; - for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(&(pr->power.states[i]), 0, - sizeof(struct acpi_processor_cx)); + current_count = 1; + + /* Zero initialize C2 onwards and prepare for fresh CST lookup */ + for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++) + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -650,16 +681,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) goto end; } - /* We support up to ACPI_PROCESSOR_MAX_POWER. */ - if (count > ACPI_PROCESSOR_MAX_POWER) { - printk(KERN_WARNING - "Limiting number of power states to max (%d)\n", - ACPI_PROCESSOR_MAX_POWER); - printk(KERN_WARNING - "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); - count = ACPI_PROCESSOR_MAX_POWER; - } - /* Tell driver that at least _CST is supported. */ pr->flags.has_cst = 1; @@ -703,7 +724,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) continue; - if ((cx.type < ACPI_STATE_C1) || (cx.type > ACPI_STATE_C3)) + if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) continue; obj = (union acpi_object *)&(element->package.elements[2]); @@ -718,15 +739,28 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.power = obj->integer.value; - (pr->power.count)++; - memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx)); + current_count++; + memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); + + /* + * We support total ACPI_PROCESSOR_MAX_POWER - 1 + * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1) + */ + if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) { + printk(KERN_WARNING + "Limiting number of power states to max (%d)\n", + ACPI_PROCESSOR_MAX_POWER); + printk(KERN_WARNING + "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); + break; + } } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", - pr->power.count)); + current_count)); /* Validate number of power states discovered */ - if (pr->power.count < 2) + if (current_count < 2) status = -EFAULT; end: @@ -867,7 +901,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); #ifdef ARCH_APICTIMER_STOPS_ON_C3 - if (c->x86_vendor == X86_VENDOR_INTEL) { + if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) { on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); } @@ -892,12 +926,13 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) /* NOTE: the idle thread may not be running while calling * this function */ + /* Adding C1 state */ + acpi_processor_get_power_info_default_c1(pr); result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) - result = acpi_processor_get_power_info_fadt(pr); + acpi_processor_get_power_info_fadt(pr); - if ((result) || (acpi_processor_power_verify(pr) < 2)) - result = acpi_processor_get_power_info_default_c1(pr); + pr->power.count = acpi_processor_power_verify(pr); /* * Set Default Policy @@ -1066,8 +1101,6 @@ int acpi_processor_power_init(struct acpi_processor *pr, } } - acpi_processor_power_init_pdc(&(pr->power), pr->id); - acpi_processor_set_pdc(pr, pr->power.pdc); acpi_processor_get_power_info(pr); /* diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 22c7bb66c200..abbdb37a7f5f 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -315,8 +315,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) if (!pr || !pr->performance || !pr->handle) return_VALUE(-EINVAL); - acpi_processor_set_pdc(pr, pr->performance->pdc); - status = acpi_get_handle(pr->handle, "_PCT", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -520,8 +518,8 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr) "Unable to create '%s' fs entry\n", ACPI_PROCESSOR_FILE_PERFORMANCE)); else { + acpi_processor_perf_fops.write = acpi_processor_write_performance; entry->proc_fops = &acpi_processor_perf_fops; - entry->proc_fops->write = acpi_processor_write_performance; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index dc9817cfb882..f99ad05cd6a2 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -348,9 +348,9 @@ static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) PDE(inode)->data); } -ssize_t acpi_processor_write_limit(struct file * file, - const char __user * buffer, - size_t count, loff_t * data) +static ssize_t acpi_processor_write_limit(struct file * file, + const char __user * buffer, + size_t count, loff_t * data) { int result = 0; struct seq_file *m = (struct seq_file *)file->private_data; @@ -394,6 +394,7 @@ ssize_t acpi_processor_write_limit(struct file * file, struct file_operations acpi_processor_limit_fops = { .open = acpi_processor_limit_open_fs, .read = seq_read, + .write = acpi_processor_write_limit, .llseek = seq_lseek, .release = single_release, }; diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 74a52d4e79ae..b966549ec000 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -306,9 +306,9 @@ static int acpi_processor_throttling_open_fs(struct inode *inode, PDE(inode)->data); } -ssize_t acpi_processor_write_throttling(struct file * file, - const char __user * buffer, - size_t count, loff_t * data) +static ssize_t acpi_processor_write_throttling(struct file * file, + const char __user * buffer, + size_t count, loff_t * data) { int result = 0; struct seq_file *m = (struct seq_file *)file->private_data; @@ -337,6 +337,7 @@ ssize_t acpi_processor_write_throttling(struct file * file, struct file_operations acpi_processor_throttling_fops = { .open = acpi_processor_throttling_open_fs, .read = seq_read, + .write = acpi_processor_write_throttling, .llseek = seq_lseek, .release = single_release, }; diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile index 2130b74170c3..8de4f69dfa09 100644 --- a/drivers/acpi/resources/Makefile +++ b/drivers/acpi/resources/Makefile @@ -2,7 +2,7 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := rsaddr.o rscreate.o rsio.o rslist.o rsmisc.o rsxface.o \ +obj-y := rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \ rscalc.o rsirq.o rsmemory.o rsutils.o obj-$(ACPI_FUTURE_USAGE) += rsdump.o diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c index 23b54baa0cb2..8fa3213ce000 100644 --- a/drivers/acpi/resources/rsaddr.c +++ b/drivers/acpi/resources/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,1072 +47,334 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsaddr") -/* Local prototypes */ -static void -acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags); - -static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource); - -static void -acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags); - -static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource); - /******************************************************************************* * - * FUNCTION: acpi_rs_decode_general_flags - * - * PARAMETERS: Resource - Address resource data struct - * Flags - Actual flag byte - * - * RETURN: Decoded flag bits in resource struct - * - * DESCRIPTION: Decode a general flag byte to an address resource struct + * acpi_rs_convert_address16 - All WORD (16-bit) address resources * ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_convert_address16[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16, + ACPI_RS_SIZE(struct acpi_resource_address16), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)}, -static void -acpi_rs_decode_general_flags(union acpi_resource_data *resource, u8 flags) -{ - ACPI_FUNCTION_ENTRY(); - - /* Producer / Consumer - flag bit[0] */ - - resource->address.producer_consumer = (u32) (flags & 0x01); + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16, + sizeof(struct aml_resource_address16), + 0}, - /* Decode (_DEC) - flag bit[1] */ + /* Resource Type, General Flags, and Type-Specific Flags */ - resource->address.decode = (u32) ((flags >> 1) & 0x01); + {ACPI_RSC_ADDRESS, 0, 0, 0}, - /* Min Address Fixed (_MIF) - flag bit[2] */ + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity), + AML_OFFSET(address16.granularity), + 5}, - resource->address.min_address_fixed = (u32) ((flags >> 2) & 0x01); + /* Optional resource_source (Index and String) */ - /* Max Address Fixed (_MAF) - flag bit[3] */ - - resource->address.max_address_fixed = (u32) ((flags >> 3) & 0x01); -} + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source), + 0, + sizeof(struct aml_resource_address16)} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_encode_general_flags - * - * PARAMETERS: Resource - Address resource data struct - * - * RETURN: Encoded general flag byte - * - * DESCRIPTION: Construct a general flag byte from an address resource struct + * acpi_rs_convert_address32 - All DWORD (32-bit) address resources * ******************************************************************************/ -static u8 acpi_rs_encode_general_flags(union acpi_resource_data *resource) -{ - u8 flags; - - ACPI_FUNCTION_ENTRY(); - - /* Producer / Consumer - flag bit[0] */ - - flags = (u8) (resource->address.producer_consumer & 0x01); - - /* Decode (_DEC) - flag bit[1] */ - - flags |= (u8) ((resource->address.decode & 0x01) << 1); - - /* Min Address Fixed (_MIF) - flag bit[2] */ - - flags |= (u8) ((resource->address.min_address_fixed & 0x01) << 2); +struct acpi_rsconvert_info acpi_rs_convert_address32[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32, + ACPI_RS_SIZE(struct acpi_resource_address32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)}, - /* Max Address Fixed (_MAF) - flag bit[3] */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32, + sizeof(struct aml_resource_address32), + 0}, - flags |= (u8) ((resource->address.max_address_fixed & 0x01) << 3); + /* Resource Type, General Flags, and Type-Specific Flags */ - return (flags); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_decode_specific_flags - * - * PARAMETERS: Resource - Address resource data struct - * Flags - Actual flag byte - * - * RETURN: Decoded flag bits in attribute struct - * - * DESCRIPTION: Decode a type-specific flag byte to an attribute struct. - * Type-specific flags are only defined for the Memory and IO - * resource types. - * - ******************************************************************************/ + {ACPI_RSC_ADDRESS, 0, 0, 0}, -static void -acpi_rs_decode_specific_flags(union acpi_resource_data *resource, u8 flags) -{ - ACPI_FUNCTION_ENTRY(); - - if (resource->address.resource_type == ACPI_MEMORY_RANGE) { - /* Write Status (_RW) - flag bit[0] */ - - resource->address.attribute.memory.read_write_attribute = - (u16) (flags & 0x01); - - /* Memory Attributes (_MEM) - flag bits[2:1] */ - - resource->address.attribute.memory.cache_attribute = - (u16) ((flags >> 1) & 0x03); - } else if (resource->address.resource_type == ACPI_IO_RANGE) { - /* Ranges (_RNG) - flag bits[1:0] */ - - resource->address.attribute.io.range_attribute = - (u16) (flags & 0x03); + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity), + AML_OFFSET(address32.granularity), + 5}, - /* Translations (_TTP and _TRS) - flag bits[5:4] */ + /* Optional resource_source (Index and String) */ - resource->address.attribute.io.translation_attribute = - (u16) ((flags >> 4) & 0x03); - } -} + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source), + 0, + sizeof(struct aml_resource_address32)} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_encode_specific_flags - * - * PARAMETERS: Resource - Address resource data struct - * - * RETURN: Encoded type-specific flag byte - * - * DESCRIPTION: Construct a type-specific flag byte from an attribute struct. - * Type-specific flags are only defined for the Memory and IO - * resource types. + * acpi_rs_convert_address64 - All QWORD (64-bit) address resources * ******************************************************************************/ -static u8 acpi_rs_encode_specific_flags(union acpi_resource_data *resource) -{ - u8 flags = 0; - - ACPI_FUNCTION_ENTRY(); - - if (resource->address.resource_type == ACPI_MEMORY_RANGE) { - /* Write Status (_RW) - flag bit[0] */ +struct acpi_rsconvert_info acpi_rs_convert_address64[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64, + ACPI_RS_SIZE(struct acpi_resource_address64), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)}, - flags = (u8) - (resource->address.attribute.memory. - read_write_attribute & 0x01); + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64, + sizeof(struct aml_resource_address64), + 0}, - /* Memory Attributes (_MEM) - flag bits[2:1] */ + /* Resource Type, General Flags, and Type-Specific Flags */ - flags |= (u8) - ((resource->address.attribute.memory. - cache_attribute & 0x03) << 1); - } else if (resource->address.resource_type == ACPI_IO_RANGE) { - /* Ranges (_RNG) - flag bits[1:0] */ + {ACPI_RSC_ADDRESS, 0, 0, 0}, - flags = (u8) - (resource->address.attribute.io.range_attribute & 0x03); + /* + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + */ + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity), + AML_OFFSET(address64.granularity), + 5}, - /* Translations (_TTP and _TRS) - flag bits[5:4] */ + /* Optional resource_source (Index and String) */ - flags |= (u8) - ((resource->address.attribute.io. - translation_attribute & 0x03) << 4); - } - - return (flags); -} + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source), + 0, + sizeof(struct aml_resource_address64)} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_address16_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources * ******************************************************************************/ -acpi_status -acpi_rs_address16_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u32 index; - u16 temp16; - u8 temp8; - u8 *temp_ptr; - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16); - - ACPI_FUNCTION_TRACE("rs_address16_resource"); - - /* Get the Descriptor Length field */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - /* Validate minimum descriptor length */ - - if (temp16 < 13) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); - } - - *bytes_consumed = temp16 + 3; - output_struct->id = ACPI_RSTYPE_ADDRESS16; - - /* Get the Resource Type (Byte3) */ +struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, + ACPI_RS_SIZE(struct acpi_resource_extended_address64), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)}, - buffer += 2; - temp8 = *buffer; + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64, + sizeof(struct aml_resource_extended_address64), + 0}, - /* Values 0-2 and 0xC0-0xFF are valid */ + /* Resource Type, General Flags, and Type-Specific Flags */ - if ((temp8 > 2) && (temp8 < 0xC0)) { - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); - } - - output_struct->data.address16.resource_type = temp8; - - /* Get the General Flags (Byte4) */ - - buffer += 1; - acpi_rs_decode_general_flags(&output_struct->data, *buffer); - - /* Get the Type Specific Flags (Byte5) */ - - buffer += 1; - acpi_rs_decode_specific_flags(&output_struct->data, *buffer); - - /* Get Granularity (Bytes 6-7) */ - - buffer += 1; - ACPI_MOVE_16_TO_32(&output_struct->data.address16.granularity, buffer); - - /* Get min_address_range (Bytes 8-9) */ + {ACPI_RSC_ADDRESS, 0, 0, 0}, - buffer += 2; - ACPI_MOVE_16_TO_32(&output_struct->data.address16.min_address_range, - buffer); - - /* Get max_address_range (Bytes 10-11) */ - - buffer += 2; - ACPI_MOVE_16_TO_32(&output_struct->data.address16.max_address_range, - buffer); - - /* Get address_translation_offset (Bytes 12-13) */ - - buffer += 2; - ACPI_MOVE_16_TO_32(&output_struct->data.address16. - address_translation_offset, buffer); - - /* Get address_length (Bytes 14-15) */ - - buffer += 2; - ACPI_MOVE_16_TO_32(&output_struct->data.address16.address_length, - buffer); - - /* Resource Source Index (if present) */ - - buffer += 2; + /* Revision ID */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_iD), + AML_OFFSET(ext_address64.revision_iD), + 1}, /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. + * These fields are contiguous in both the source and destination: + * Address Granularity + * Address Range Minimum + * Address Range Maximum + * Address Translation Offset + * Address Length + * Type-Specific Attribute */ - if (*bytes_consumed > (16 + 1)) { - /* Dereference the Index */ - - output_struct->data.address16.resource_source.index = - (u32) * buffer; - - /* Point to the String */ - - buffer += 1; - - /* Point the String pointer to the end of this structure */ - - output_struct->data.address16.resource_source.string_ptr = - (char *)((u8 *) output_struct + struct_size); - - temp_ptr = (u8 *) - output_struct->data.address16.resource_source.string_ptr; - - /* Copy the resource_source string into the buffer */ - - index = 0; - while (*buffer) { - *temp_ptr = *buffer; - - temp_ptr++; - buffer++; - index++; - } - - /* Add the terminating null and set the string length */ - - *temp_ptr = 0; - output_struct->data.address16.resource_source.string_length = - index + 1; - - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS(temp8); - } else { - output_struct->data.address16.resource_source.index = 0; - output_struct->data.address16.resource_source.string_length = 0; - output_struct->data.address16.resource_source.string_ptr = NULL; - } - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity), + AML_OFFSET(ext_address64.granularity), + 6} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_address16_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_general_flags - Flags common to all address descriptors * ******************************************************************************/ -acpi_status -acpi_rs_address16_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u8 *length_field; - acpi_size actual_bytes; - - ACPI_FUNCTION_TRACE("rs_address16_stream"); - - /* Set the Descriptor Type field */ - - *buffer = ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE; - buffer += 1; - - /* Save a pointer to the Length field - to be filled in later */ - - length_field = buffer; - buffer += 2; - - /* Set the Resource Type (Memory, Io, bus_number) */ - - *buffer = (u8) (linked_list->data.address16.resource_type & 0x03); - buffer += 1; - - /* Set the general flags */ - - *buffer = acpi_rs_encode_general_flags(&linked_list->data); - buffer += 1; - - /* Set the type specific flags */ - - *buffer = acpi_rs_encode_specific_flags(&linked_list->data); - buffer += 1; - - /* Set the address space granularity */ - - ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.granularity); - buffer += 2; - - /* Set the address range minimum */ +static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)}, - ACPI_MOVE_32_TO_16(buffer, - &linked_list->data.address16.min_address_range); - buffer += 2; + /* Resource Type (Memory, Io, bus_number, etc.) */ - /* Set the address range maximum */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type), + AML_OFFSET(address.resource_type), + 1}, - ACPI_MOVE_32_TO_16(buffer, - &linked_list->data.address16.max_address_range); - buffer += 2; + /* General Flags - Consume, Decode, min_fixed, max_fixed */ - /* Set the address translation offset */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer), + AML_OFFSET(address.flags), + 0}, - ACPI_MOVE_32_TO_16(buffer, - &linked_list->data.address16. - address_translation_offset); - buffer += 2; + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode), + AML_OFFSET(address.flags), + 1}, - /* Set the address length */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed), + AML_OFFSET(address.flags), + 2}, - ACPI_MOVE_32_TO_16(buffer, &linked_list->data.address16.address_length); - buffer += 2; - - /* Resource Source Index and Resource Source are optional */ - - if (linked_list->data.address16.resource_source.string_length) { - *buffer = - (u8) linked_list->data.address16.resource_source.index; - buffer += 1; - - /* Copy the resource_source string */ - - ACPI_STRCPY((char *)buffer, - linked_list->data.address16.resource_source. - string_ptr); - - /* - * Buffer needs to be set to the length of the string + one for the - * terminating null - */ - buffer += - (acpi_size) (ACPI_STRLEN - (linked_list->data.address16.resource_source. - string_ptr) + 1); - } - - /* Return the number of bytes consumed in this operation */ - - actual_bytes = ACPI_PTR_DIFF(buffer, *output_buffer); - *bytes_consumed = actual_bytes; - - /* - * Set the length field to the number of bytes consumed - * minus the header size (3 bytes) - */ - actual_bytes -= 3; - ACPI_MOVE_SIZE_TO_16(length_field, &actual_bytes); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed), + AML_OFFSET(address.flags), + 3} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_address32_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors * ******************************************************************************/ -acpi_status -acpi_rs_address32_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u16 temp16; - u8 temp8; - u8 *temp_ptr; - u32 index; - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32); +static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)}, - ACPI_FUNCTION_TRACE("rs_address32_resource"); + /* Memory-specific flags */ - /* Get the Descriptor Length field */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect), + AML_OFFSET(address.specific_flags), + 0}, - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching), + AML_OFFSET(address.specific_flags), + 1}, - /* Validate minimum descriptor length */ + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type), + AML_OFFSET(address.specific_flags), + 3}, - if (temp16 < 23) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); - } - - *bytes_consumed = temp16 + 3; - output_struct->id = ACPI_RSTYPE_ADDRESS32; - - /* Get the Resource Type (Byte3) */ - - buffer += 2; - temp8 = *buffer; - - /* Values 0-2 and 0xC0-0xFF are valid */ - - if ((temp8 > 2) && (temp8 < 0xC0)) { - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); - } - - output_struct->data.address32.resource_type = temp8; - - /* Get the General Flags (Byte4) */ - - buffer += 1; - acpi_rs_decode_general_flags(&output_struct->data, *buffer); - - /* Get the Type Specific Flags (Byte5) */ - - buffer += 1; - acpi_rs_decode_specific_flags(&output_struct->data, *buffer); - - /* Get Granularity (Bytes 6-9) */ - - buffer += 1; - ACPI_MOVE_32_TO_32(&output_struct->data.address32.granularity, buffer); - - /* Get min_address_range (Bytes 10-13) */ - - buffer += 4; - ACPI_MOVE_32_TO_32(&output_struct->data.address32.min_address_range, - buffer); - - /* Get max_address_range (Bytes 14-17) */ - - buffer += 4; - ACPI_MOVE_32_TO_32(&output_struct->data.address32.max_address_range, - buffer); - - /* Get address_translation_offset (Bytes 18-21) */ - - buffer += 4; - ACPI_MOVE_32_TO_32(&output_struct->data.address32. - address_translation_offset, buffer); - - /* Get address_length (Bytes 22-25) */ - - buffer += 4; - ACPI_MOVE_32_TO_32(&output_struct->data.address32.address_length, - buffer); - - /* Resource Source Index (if present) */ - - buffer += 4; - - /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. - */ - if (*bytes_consumed > (26 + 1)) { - /* Dereference the Index */ - - output_struct->data.address32.resource_source.index = - (u32) * buffer; - - /* Point to the String */ - - buffer += 1; - - /* Point the String pointer to the end of this structure */ - - output_struct->data.address32.resource_source.string_ptr = - (char *)((u8 *) output_struct + struct_size); - - temp_ptr = (u8 *) - output_struct->data.address32.resource_source.string_ptr; - - /* Copy the resource_source string into the buffer */ - - index = 0; - while (*buffer) { - *temp_ptr = *buffer; - - temp_ptr++; - buffer++; - index++; - } - - /* Add the terminating null and set the string length */ - - *temp_ptr = 0; - output_struct->data.address32.resource_source.string_length = - index + 1; - - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS(temp8); - } else { - output_struct->data.address32.resource_source.index = 0; - output_struct->data.address32.resource_source.string_length = 0; - output_struct->data.address32.resource_source.string_ptr = NULL; - } - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation), + AML_OFFSET(address.specific_flags), + 5} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_address32_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_io_flags - Flags common to I/O address descriptors * ******************************************************************************/ -acpi_status -acpi_rs_address32_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer; - u16 *length_field; - - ACPI_FUNCTION_TRACE("rs_address32_stream"); - - buffer = *output_buffer; - - /* Set the Descriptor Type field */ - - *buffer = ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE; - buffer += 1; - - /* Save a pointer to the Length field - to be filled in later */ - - length_field = ACPI_CAST_PTR(u16, buffer); - buffer += 2; - - /* Set the Resource Type (Memory, Io, bus_number) */ - - *buffer = (u8) (linked_list->data.address32.resource_type & 0x03); - buffer += 1; - - /* Set the general flags */ - - *buffer = acpi_rs_encode_general_flags(&linked_list->data); - buffer += 1; - - /* Set the type specific flags */ - - *buffer = acpi_rs_encode_specific_flags(&linked_list->data); - buffer += 1; - - /* Set the address space granularity */ - - ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.granularity); - buffer += 4; - - /* Set the address range minimum */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.address32.min_address_range); - buffer += 4; - - /* Set the address range maximum */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.address32.max_address_range); - buffer += 4; - - /* Set the address translation offset */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.address32. - address_translation_offset); - buffer += 4; - - /* Set the address length */ - - ACPI_MOVE_32_TO_32(buffer, &linked_list->data.address32.address_length); - buffer += 4; +static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = { + {ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)}, - /* Resource Source Index and Resource Source are optional */ + /* I/O-specific flags */ - if (linked_list->data.address32.resource_source.string_length) { - *buffer = - (u8) linked_list->data.address32.resource_source.index; - buffer += 1; + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type), + AML_OFFSET(address.specific_flags), + 0}, - /* Copy the resource_source string */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation), + AML_OFFSET(address.specific_flags), + 4}, - ACPI_STRCPY((char *)buffer, - linked_list->data.address32.resource_source. - string_ptr); - - /* - * Buffer needs to be set to the length of the string + one for the - * terminating null - */ - buffer += - (acpi_size) (ACPI_STRLEN - (linked_list->data.address32.resource_source. - string_ptr) + 1); - } - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - - /* - * Set the length field to the number of bytes consumed - * minus the header size (3 bytes) - */ - *length_field = (u16) (*bytes_consumed - 3); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, + ACPI_RS_OFFSET(data.address.info.io.translation_type), + AML_OFFSET(address.specific_flags), + 5} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_address64_resource + * FUNCTION: acpi_rs_get_address_common * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned + * PARAMETERS: Resource - Pointer to the internal resource struct + * Aml - Pointer to the AML resource descriptor * - * RETURN: Status + * RETURN: TRUE if the resource_type field is OK, FALSE otherwise * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor + * to an internal resource descriptor * ******************************************************************************/ -acpi_status -acpi_rs_address64_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) +u8 +acpi_rs_get_address_common(struct acpi_resource *resource, + union aml_resource *aml) { - u16 temp16; - u8 temp8; - u8 resource_type; - u8 *temp_ptr; - u32 index; - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64); - - ACPI_FUNCTION_TRACE("rs_address64_resource"); - - /* Get the Descriptor Type */ - - resource_type = *buffer; - - /* Get the Descriptor Length field */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - /* Validate minimum descriptor length */ - - if (temp16 < 43) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); - } - - *bytes_consumed = temp16 + 3; - output_struct->id = ACPI_RSTYPE_ADDRESS64; - - /* Get the Resource Type (Byte3) */ - - buffer += 2; - temp8 = *buffer; - - /* Values 0-2 and 0xC0-0xFF are valid */ - - if ((temp8 > 2) && (temp8 < 0xC0)) { - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); - } - - output_struct->data.address64.resource_type = temp8; - - /* Get the General Flags (Byte4) */ - - buffer += 1; - acpi_rs_decode_general_flags(&output_struct->data, *buffer); - - /* Get the Type Specific Flags (Byte5) */ - - buffer += 1; - acpi_rs_decode_specific_flags(&output_struct->data, *buffer); + ACPI_FUNCTION_ENTRY(); - if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { - /* Move past revision_id and Reserved byte */ + /* Validate the Resource Type */ - buffer += 2; + if ((aml->address.resource_type > 2) + && (aml->address.resource_type < 0xC0)) { + return (FALSE); } - /* Get Granularity (Bytes 6-13) or (Bytes 8-15) */ - - buffer += 1; - ACPI_MOVE_64_TO_64(&output_struct->data.address64.granularity, buffer); - - /* Get min_address_range (Bytes 14-21) or (Bytes 16-23) */ - - buffer += 8; - ACPI_MOVE_64_TO_64(&output_struct->data.address64.min_address_range, - buffer); - - /* Get max_address_range (Bytes 22-29) or (Bytes 24-31) */ - - buffer += 8; - ACPI_MOVE_64_TO_64(&output_struct->data.address64.max_address_range, - buffer); - - /* Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) */ - - buffer += 8; - ACPI_MOVE_64_TO_64(&output_struct->data.address64. - address_translation_offset, buffer); + /* Get the Resource Type and General Flags */ - /* Get address_length (Bytes 38-45) or (Bytes 40-47) */ + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_general_flags); - buffer += 8; - ACPI_MOVE_64_TO_64(&output_struct->data.address64.address_length, - buffer); + /* Get the Type-Specific Flags (Memory and I/O descriptors only) */ - output_struct->data.address64.resource_source.index = 0; - output_struct->data.address64.resource_source.string_length = 0; - output_struct->data.address64.resource_source.string_ptr = NULL; - - if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { - /* Get type_specific_attribute (Bytes 48-55) */ - - buffer += 8; - ACPI_MOVE_64_TO_64(&output_struct->data.address64. - type_specific_attributes, buffer); + if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_mem_flags); + } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { + (void)acpi_rs_convert_aml_to_resource(resource, aml, + acpi_rs_convert_io_flags); } else { - output_struct->data.address64.type_specific_attributes = 0; - - /* Resource Source Index (if present) */ - - buffer += 8; - - /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. - */ - if (*bytes_consumed > (46 + 1)) { - /* Dereference the Index */ - - output_struct->data.address64.resource_source.index = - (u32) * buffer; - - /* Point to the String */ - - buffer += 1; - - /* Point the String pointer to the end of this structure */ - - output_struct->data.address64.resource_source. - string_ptr = - (char *)((u8 *) output_struct + struct_size); - - temp_ptr = (u8 *) - output_struct->data.address64.resource_source. - string_ptr; - - /* Copy the resource_source string into the buffer */ - - index = 0; - while (*buffer) { - *temp_ptr = *buffer; - - temp_ptr++; - buffer++; - index++; - } - - /* - * Add the terminating null and set the string length - */ - *temp_ptr = 0; - output_struct->data.address64.resource_source. - string_length = index + 1; - - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS(temp8); - } - } - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; + /* Generic resource type, just grab the type_specific byte */ - /* Return the final size of the structure */ + resource->data.address.info.type_specific = + aml->address.specific_flags; + } - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); + return (TRUE); } /******************************************************************************* * - * FUNCTION: acpi_rs_address64_stream + * FUNCTION: acpi_rs_set_address_common * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned + * PARAMETERS: Aml - Pointer to the AML resource descriptor + * Resource - Pointer to the internal resource struct * - * RETURN: Status + * RETURN: None * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * DESCRIPTION: Convert common flag fields from a resource descriptor to an + * AML descriptor * ******************************************************************************/ -acpi_status -acpi_rs_address64_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) +void +acpi_rs_set_address_common(union aml_resource *aml, + struct acpi_resource *resource) { - u8 *buffer; - u16 *length_field; - - ACPI_FUNCTION_TRACE("rs_address64_stream"); - - buffer = *output_buffer; - - /* Set the Descriptor Type field */ - - *buffer = ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE; - buffer += 1; - - /* Save a pointer to the Length field - to be filled in later */ - - length_field = ACPI_CAST_PTR(u16, buffer); - buffer += 2; - - /* Set the Resource Type (Memory, Io, bus_number) */ - - *buffer = (u8) (linked_list->data.address64.resource_type & 0x03); - buffer += 1; - - /* Set the general flags */ - - *buffer = acpi_rs_encode_general_flags(&linked_list->data); - buffer += 1; - - /* Set the type specific flags */ - - *buffer = acpi_rs_encode_specific_flags(&linked_list->data); - buffer += 1; - - /* Set the address space granularity */ - - ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.granularity); - buffer += 8; - - /* Set the address range minimum */ - - ACPI_MOVE_64_TO_64(buffer, - &linked_list->data.address64.min_address_range); - buffer += 8; - - /* Set the address range maximum */ - - ACPI_MOVE_64_TO_64(buffer, - &linked_list->data.address64.max_address_range); - buffer += 8; - - /* Set the address translation offset */ - - ACPI_MOVE_64_TO_64(buffer, - &linked_list->data.address64. - address_translation_offset); - buffer += 8; - - /* Set the address length */ - - ACPI_MOVE_64_TO_64(buffer, &linked_list->data.address64.address_length); - buffer += 8; + ACPI_FUNCTION_ENTRY(); - /* Resource Source Index and Resource Source are optional */ + /* Set the Resource Type and General Flags */ - if (linked_list->data.address64.resource_source.string_length) { - *buffer = - (u8) linked_list->data.address64.resource_source.index; - buffer += 1; + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_general_flags); - /* Copy the resource_source string */ + /* Set the Type-Specific Flags (Memory and I/O descriptors only) */ - ACPI_STRCPY((char *)buffer, - linked_list->data.address64.resource_source. - string_ptr); + if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) { + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_mem_flags); + } else if (resource->data.address.resource_type == ACPI_IO_RANGE) { + (void)acpi_rs_convert_resource_to_aml(resource, aml, + acpi_rs_convert_io_flags); + } else { + /* Generic resource type, just copy the type_specific byte */ - /* - * Buffer needs to be set to the length of the string + one for the - * terminating null - */ - buffer += - (acpi_size) (ACPI_STRLEN - (linked_list->data.address64.resource_source. - string_ptr) + 1); + aml->address.specific_flags = + resource->data.address.info.type_specific; } - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - - /* - * Set the length field to the number of bytes consumed - * minus the header size (3 bytes) - */ - *length_field = (u16) (*bytes_consumed - 3); - return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 378f58390fc1..7d6481d9fbec 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,652 +49,433 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rscalc") +/* Local prototypes */ +static u8 acpi_rs_count_set_bits(u16 bit_field); + +static acpi_rs_length +acpi_rs_struct_option_length(struct acpi_resource_source *resource_source); + +static u32 +acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); + /******************************************************************************* * - * FUNCTION: acpi_rs_get_byte_stream_length + * FUNCTION: acpi_rs_count_set_bits * - * PARAMETERS: linked_list - Pointer to the resource linked list - * size_needed - u32 pointer of the size buffer needed - * to properly return the parsed data + * PARAMETERS: bit_field - Field in which to count bits * - * RETURN: Status + * RETURN: Number of bits set within the field * - * DESCRIPTION: Takes the resource byte stream and parses it once, calculating - * the size buffer needed to hold the linked list that conveys - * the resource data. + * DESCRIPTION: Count the number of bits set in a resource field. Used for + * (Short descriptor) interrupt and DMA lists. * ******************************************************************************/ -acpi_status -acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list, - acpi_size * size_needed) -{ - acpi_size byte_stream_size_needed = 0; - acpi_size segment_size; - u8 done = FALSE; - - ACPI_FUNCTION_TRACE("rs_get_byte_stream_length"); - - while (!done) { - /* Init the variable that will hold the size to add to the total. */ - - segment_size = 0; - - switch (linked_list->id) { - case ACPI_RSTYPE_IRQ: - /* - * IRQ Resource - * For an IRQ Resource, Byte 3, although optional, will always be - * created - it holds IRQ information. - */ - segment_size = 4; - break; - - case ACPI_RSTYPE_DMA: - /* - * DMA Resource - * For this resource the size is static - */ - segment_size = 3; - break; - - case ACPI_RSTYPE_START_DPF: - /* - * Start Dependent Functions Resource - * For a start_dependent_functions Resource, Byte 1, although - * optional, will always be created. - */ - segment_size = 2; - break; - - case ACPI_RSTYPE_END_DPF: - /* - * End Dependent Functions Resource - * For this resource the size is static - */ - segment_size = 1; - break; - - case ACPI_RSTYPE_IO: - /* - * IO Port Resource - * For this resource the size is static - */ - segment_size = 8; - break; - case ACPI_RSTYPE_FIXED_IO: - /* - * Fixed IO Port Resource - * For this resource the size is static - */ - segment_size = 4; - break; - - case ACPI_RSTYPE_VENDOR: - /* - * Vendor Defined Resource - * For a Vendor Specific resource, if the Length is between 1 and 7 - * it will be created as a Small Resource data type, otherwise it - * is a Large Resource data type. - */ - if (linked_list->data.vendor_specific.length > 7) { - segment_size = 3; - } else { - segment_size = 1; - } - segment_size += - linked_list->data.vendor_specific.length; - break; - - case ACPI_RSTYPE_END_TAG: - /* - * End Tag - * For this resource the size is static - */ - segment_size = 2; - done = TRUE; - break; - - case ACPI_RSTYPE_MEM24: - /* - * 24-Bit Memory Resource - * For this resource the size is static - */ - segment_size = 12; - break; +static u8 acpi_rs_count_set_bits(u16 bit_field) +{ + u8 bits_set; - case ACPI_RSTYPE_MEM32: - /* - * 32-Bit Memory Range Resource - * For this resource the size is static - */ - segment_size = 20; - break; + ACPI_FUNCTION_ENTRY(); - case ACPI_RSTYPE_FIXED_MEM32: - /* - * 32-Bit Fixed Memory Resource - * For this resource the size is static - */ - segment_size = 12; - break; + for (bits_set = 0; bit_field; bits_set++) { + /* Zero the least significant bit that is set */ - case ACPI_RSTYPE_ADDRESS16: - /* - * 16-Bit Address Resource - * The base size of this byte stream is 16. If a Resource Source - * string is not NULL, add 1 for the Index + the length of the null - * terminated string Resource Source + 1 for the null. - */ - segment_size = 16; - - if (linked_list->data.address16.resource_source. - string_ptr) { - segment_size += - linked_list->data.address16.resource_source. - string_length; - segment_size++; - } - break; + bit_field &= (bit_field - 1); + } - case ACPI_RSTYPE_ADDRESS32: - /* - * 32-Bit Address Resource - * The base size of this byte stream is 26. If a Resource - * Source string is not NULL, add 1 for the Index + the - * length of the null terminated string Resource Source + - * 1 for the null. - */ - segment_size = 26; - - if (linked_list->data.address32.resource_source. - string_ptr) { - segment_size += - linked_list->data.address32.resource_source. - string_length; - segment_size++; - } - break; + return (bits_set); +} - case ACPI_RSTYPE_ADDRESS64: - /* - * 64-Bit Address Resource - * The base size of this byte stream is 46. If a resource_source - * string is not NULL, add 1 for the Index + the length of the null - * terminated string Resource Source + 1 for the null. - */ - segment_size = 46; - - if (linked_list->data.address64.resource_source. - string_ptr) { - segment_size += - linked_list->data.address64.resource_source. - string_length; - segment_size++; - } - break; +/******************************************************************************* + * + * FUNCTION: acpi_rs_struct_option_length + * + * PARAMETERS: resource_source - Pointer to optional descriptor field + * + * RETURN: Status + * + * DESCRIPTION: Common code to handle optional resource_source_index and + * resource_source fields in some Large descriptors. Used during + * list-to-stream conversion + * + ******************************************************************************/ - case ACPI_RSTYPE_EXT_IRQ: - /* - * Extended IRQ Resource - * The base size of this byte stream is 9. This is for an Interrupt - * table length of 1. For each additional interrupt, add 4. - * If a Resource Source string is not NULL, add 1 for the - * Index + the length of the null terminated string - * Resource Source + 1 for the null. - */ - segment_size = 9 + (((acpi_size) - linked_list->data.extended_irq. - number_of_interrupts - 1) * 4); - - if (linked_list->data.extended_irq.resource_source. - string_ptr) { - segment_size += - linked_list->data.extended_irq. - resource_source.string_length; - segment_size++; - } - break; +static acpi_rs_length +acpi_rs_struct_option_length(struct acpi_resource_source *resource_source) +{ + ACPI_FUNCTION_ENTRY(); - default: + /* + * If the resource_source string is valid, return the size of the string + * (string_length includes the NULL terminator) plus the size of the + * resource_source_index (1). + */ + if (resource_source->string_ptr) { + return ((acpi_rs_length) (resource_source->string_length + 1)); + } - /* If we get here, everything is out of sync, exit with error */ + return (0); +} - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); +/******************************************************************************* + * + * FUNCTION: acpi_rs_stream_option_length + * + * PARAMETERS: resource_length - Length from the resource header + * minimum_total_length - Minimum length of this resource, before + * any optional fields. Includes header size + * + * RETURN: Length of optional string (0 if no string present) + * + * DESCRIPTION: Common code to handle optional resource_source_index and + * resource_source fields in some Large descriptors. Used during + * stream-to-list conversion + * + ******************************************************************************/ - } /* switch (linked_list->Id) */ +static u32 +acpi_rs_stream_option_length(u32 resource_length, + u32 minimum_aml_resource_length) +{ + u32 string_length = 0; - /* Update the total */ + ACPI_FUNCTION_ENTRY(); - byte_stream_size_needed += segment_size; + /* + * The resource_source_index and resource_source are optional elements of some + * Large-type resource descriptors. + */ - /* Point to the next object */ + /* + * If the length of the actual resource descriptor is greater than the ACPI + * spec-defined minimum length, it means that a resource_source_index exists + * and is followed by a (required) null terminated string. The string length + * (including the null terminator) is the resource length minus the minimum + * length, minus one byte for the resource_source_index itself. + */ + if (resource_length > minimum_aml_resource_length) { + /* Compute the length of the optional string */ - linked_list = ACPI_PTR_ADD(struct acpi_resource, - linked_list, linked_list->length); + string_length = + resource_length - minimum_aml_resource_length - 1; } - /* This is the data the caller needs */ + /* Round up length to 32 bits for internal structure alignment */ - *size_needed = byte_stream_size_needed; - return_ACPI_STATUS(AE_OK); + return (ACPI_ROUND_UP_to_32_bITS(string_length)); } /******************************************************************************* * - * FUNCTION: acpi_rs_get_list_length + * FUNCTION: acpi_rs_get_aml_length * - * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream - * byte_stream_buffer_length - Size of byte_stream_buffer - * size_needed - u32 pointer of the size buffer - * needed to properly return the - * parsed data + * PARAMETERS: Resource - Pointer to the resource linked list + * size_needed - Where the required size is returned * * RETURN: Status * - * DESCRIPTION: Takes the resource byte stream and parses it once, calculating - * the size buffer needed to hold the linked list that conveys - * the resource data. + * DESCRIPTION: Takes a linked list of internal resource descriptors and + * calculates the size buffer needed to hold the corresponding + * external resource byte stream. * ******************************************************************************/ acpi_status -acpi_rs_get_list_length(u8 * byte_stream_buffer, - u32 byte_stream_buffer_length, acpi_size * size_needed) +acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) { - u32 buffer_size = 0; - u32 bytes_parsed = 0; - u8 number_of_interrupts = 0; - u8 number_of_channels = 0; - u8 resource_type; - u32 structure_size; - u32 bytes_consumed; - u8 *buffer; - u8 temp8; - u16 temp16; - u8 index; - u8 additional_bytes; - - ACPI_FUNCTION_TRACE("rs_get_list_length"); + acpi_size aml_size_needed = 0; + acpi_rs_length total_size; - while (bytes_parsed < byte_stream_buffer_length) { - /* The next byte in the stream is the resource type */ + ACPI_FUNCTION_TRACE("rs_get_aml_length"); - resource_type = acpi_rs_get_resource_type(*byte_stream_buffer); + /* Traverse entire list of internal resource descriptors */ - switch (resource_type) { - case ACPI_RDESC_TYPE_MEMORY_24: - /* - * 24-Bit Memory Resource - */ - bytes_consumed = 12; - - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24); - break; + while (resource) { + /* Validate the descriptor type */ - case ACPI_RDESC_TYPE_LARGE_VENDOR: - /* - * Vendor Defined Resource - */ - buffer = byte_stream_buffer; - ++buffer; - - ACPI_MOVE_16_TO_16(&temp16, buffer); - bytes_consumed = temp16 + 3; - - /* Ensure a 32-bit boundary for the structure */ + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); + } - temp16 = (u16) ACPI_ROUND_UP_to_32_bITS(temp16); + /* Get the base size of the (external stream) resource descriptor */ - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) + - (temp16 * sizeof(u8)); - break; + total_size = acpi_gbl_aml_resource_sizes[resource->type]; - case ACPI_RDESC_TYPE_MEMORY_32: + /* + * Augment the base size for descriptors with optional and/or + * variable-length fields + */ + switch (resource->type) { + case ACPI_RESOURCE_TYPE_VENDOR: /* - * 32-Bit Memory Range Resource + * Vendor Defined Resource: + * For a Vendor Specific resource, if the Length is between 1 and 7 + * it will be created as a Small Resource data type, otherwise it + * is a Large Resource data type. */ - bytes_consumed = 20; + if (resource->data.vendor.byte_length > 7) { + /* Base size of a Large resource descriptor */ - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32); - break; + total_size = + sizeof(struct aml_resource_large_header); + } - case ACPI_RDESC_TYPE_FIXED_MEMORY_32: - /* - * 32-Bit Fixed Memory Resource - */ - bytes_consumed = 12; + /* Add the size of the vendor-specific data */ - structure_size = - ACPI_SIZEOF_RESOURCE(struct - acpi_resource_fixed_mem32); + total_size = (acpi_rs_length) + (total_size + resource->data.vendor.byte_length); break; - case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: + case ACPI_RESOURCE_TYPE_END_TAG: /* - * 64-Bit Address Resource + * End Tag: + * We are done -- return the accumulated total size. */ - buffer = byte_stream_buffer; + *size_needed = aml_size_needed + total_size; - ++buffer; - ACPI_MOVE_16_TO_16(&temp16, buffer); + /* Normal exit */ - bytes_consumed = temp16 + 3; - structure_size = - ACPI_SIZEOF_RESOURCE(struct - acpi_resource_address64); - break; + return_ACPI_STATUS(AE_OK); - case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: + case ACPI_RESOURCE_TYPE_ADDRESS16: /* - * 64-Bit Address Resource + * 16-Bit Address Resource: + * Add the size of the optional resource_source info */ - buffer = byte_stream_buffer; - - ++buffer; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - bytes_consumed = temp16 + 3; + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address16. + resource_source)); + break; + case ACPI_RESOURCE_TYPE_ADDRESS32: /* - * Resource Source Index and Resource Source are optional elements. - * Check the length of the Bytestream. If it is greater than 43, - * that means that an Index exists and is followed by a null - * terminated string. Therefore, set the temp variable to the - * length minus the minimum byte stream length plus the byte for - * the Index to determine the size of the NULL terminated string. + * 32-Bit Address Resource: + * Add the size of the optional resource_source info */ - if (43 < temp16) { - temp8 = (u8) (temp16 - 44); - } else { - temp8 = 0; - } - - /* Ensure a 64-bit boundary for the structure */ - - temp8 = (u8) ACPI_ROUND_UP_to_64_bITS(temp8); - - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64) - + (temp8 * sizeof(u8)); + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address32. + resource_source)); break; - case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: + case ACPI_RESOURCE_TYPE_ADDRESS64: /* - * 32-Bit Address Resource + * 64-Bit Address Resource: + * Add the size of the optional resource_source info */ - buffer = byte_stream_buffer; - - ++buffer; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - bytes_consumed = temp16 + 3; + total_size = (acpi_rs_length) + (total_size + + acpi_rs_struct_option_length(&resource->data. + address64. + resource_source)); + break; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: /* - * Resource Source Index and Resource Source are optional elements. - * Check the length of the Bytestream. If it is greater than 23, - * that means that an Index exists and is followed by a null - * terminated string. Therefore, set the temp variable to the - * length minus the minimum byte stream length plus the byte for - * the Index to determine the size of the NULL terminated string. + * Extended IRQ Resource: + * Add the size of each additional optional interrupt beyond the + * required 1 (4 bytes for each u32 interrupt number) */ - if (23 < temp16) { - temp8 = (u8) (temp16 - 24); - } else { - temp8 = 0; - } - - /* Ensure a 32-bit boundary for the structure */ - - temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); + total_size = (acpi_rs_length) + (total_size + + ((resource->data.extended_irq.interrupt_count - + 1) * 4) + + /* Add the size of the optional resource_source info */ + acpi_rs_struct_option_length(&resource->data. + extended_irq. + resource_source)); + break; - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32) - + (temp8 * sizeof(u8)); + default: break; + } - case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: - /* - * 16-Bit Address Resource - */ - buffer = byte_stream_buffer; + /* Update the total */ - ++buffer; - ACPI_MOVE_16_TO_16(&temp16, buffer); + aml_size_needed += total_size; - bytes_consumed = temp16 + 3; + /* Point to the next object */ - /* - * Resource Source Index and Resource Source are optional elements. - * Check the length of the Bytestream. If it is greater than 13, - * that means that an Index exists and is followed by a null - * terminated string. Therefore, set the temp variable to the - * length minus the minimum byte stream length plus the byte for - * the Index to determine the size of the NULL terminated string. - */ - if (13 < temp16) { - temp8 = (u8) (temp16 - 14); - } else { - temp8 = 0; - } + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } - /* Ensure a 32-bit boundary for the structure */ + /* Did not find an end_tag resource descriptor */ - temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); +} - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16) - + (temp8 * sizeof(u8)); - break; +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_list_length + * + * PARAMETERS: aml_buffer - Pointer to the resource byte stream + * aml_buffer_length - Size of aml_buffer + * size_needed - Where the size needed is returned + * + * RETURN: Status + * + * DESCRIPTION: Takes an external resource byte stream and calculates the size + * buffer needed to hold the corresponding internal resource + * descriptor linked list. + * + ******************************************************************************/ - case ACPI_RDESC_TYPE_EXTENDED_XRUPT: - /* - * Extended IRQ - */ - buffer = byte_stream_buffer; +acpi_status +acpi_rs_get_list_length(u8 * aml_buffer, + u32 aml_buffer_length, acpi_size * size_needed) +{ + acpi_status status; + u8 *end_aml; + u8 *buffer; + u32 buffer_size = 0; + u16 temp16; + u16 resource_length; + u32 extra_struct_bytes; + u8 resource_index; + u8 minimum_aml_resource_length; - ++buffer; - ACPI_MOVE_16_TO_16(&temp16, buffer); + ACPI_FUNCTION_TRACE("rs_get_list_length"); - bytes_consumed = temp16 + 3; + end_aml = aml_buffer + aml_buffer_length; - /* - * Point past the length field and the Interrupt vector flags to - * save off the Interrupt table length to the Temp8 variable. - */ - buffer += 3; - temp8 = *buffer; + /* Walk the list of AML resource descriptors */ - /* - * To compensate for multiple interrupt numbers, add 4 bytes for - * each additional interrupts greater than 1 - */ - additional_bytes = (u8) ((temp8 - 1) * 4); + while (aml_buffer < end_aml) { + /* Validate the Resource Type and Resource Length */ - /* - * Resource Source Index and Resource Source are optional elements. - * Check the length of the Bytestream. If it is greater than 9, - * that means that an Index exists and is followed by a null - * terminated string. Therefore, set the temp variable to the - * length minus the minimum byte stream length plus the byte for - * the Index to determine the size of the NULL terminated string. - */ - if (9 + additional_bytes < temp16) { - temp8 = (u8) (temp16 - (9 + additional_bytes)); - } else { - temp8 = 0; - } + status = acpi_ut_validate_resource(aml_buffer, &resource_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* Ensure a 32-bit boundary for the structure */ + /* Get the resource length and base (minimum) AML size */ - temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); + resource_length = acpi_ut_get_resource_length(aml_buffer); + minimum_aml_resource_length = + acpi_gbl_resource_aml_sizes[resource_index]; - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq) + - (additional_bytes * sizeof(u8)) + - (temp8 * sizeof(u8)); - break; + /* + * Augment the size for descriptors with optional + * and/or variable length fields + */ + extra_struct_bytes = 0; + buffer = + aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); - case ACPI_RDESC_TYPE_IRQ_FORMAT: + switch (acpi_ut_get_resource_type(aml_buffer)) { + case ACPI_RESOURCE_NAME_IRQ: /* - * IRQ Resource. - * Determine if it there are two or three trailing bytes + * IRQ Resource: + * Get the number of bits set in the 16-bit IRQ mask */ - buffer = byte_stream_buffer; - temp8 = *buffer; - - if (temp8 & 0x01) { - bytes_consumed = 4; - } else { - bytes_consumed = 3; - } - - /* Point past the descriptor */ - - ++buffer; - - /* Look at the number of bits set */ - ACPI_MOVE_16_TO_16(&temp16, buffer); - - for (index = 0; index < 16; index++) { - if (temp16 & 0x1) { - ++number_of_interrupts; - } - - temp16 >>= 1; - } - - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_io) + - (number_of_interrupts * sizeof(u32)); + extra_struct_bytes = acpi_rs_count_set_bits(temp16); break; - case ACPI_RDESC_TYPE_DMA_FORMAT: + case ACPI_RESOURCE_NAME_DMA: /* - * DMA Resource + * DMA Resource: + * Get the number of bits set in the 8-bit DMA mask */ - buffer = byte_stream_buffer; - bytes_consumed = 3; - - /* Point past the descriptor */ - - ++buffer; - - /* Look at the number of bits set */ - - temp8 = *buffer; - - for (index = 0; index < 8; index++) { - if (temp8 & 0x1) { - ++number_of_channels; - } - - temp8 >>= 1; - } - - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma) + - (number_of_channels * sizeof(u32)); + extra_struct_bytes = acpi_rs_count_set_bits(*buffer); break; - case ACPI_RDESC_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_NAME_VENDOR_SMALL: /* - * Start Dependent Functions Resource - * Determine if it there are two or three trailing bytes + * Vendor Resource: + * Ensure a 32-bit boundary for the structure */ - buffer = byte_stream_buffer; - temp8 = *buffer; - - if (temp8 & 0x01) { - bytes_consumed = 2; - } else { - bytes_consumed = 1; - } - - structure_size = - ACPI_SIZEOF_RESOURCE(struct - acpi_resource_start_dpf); + extra_struct_bytes = + ACPI_ROUND_UP_to_32_bITS(resource_length) - + resource_length; break; - case ACPI_RDESC_TYPE_END_DEPENDENT: + case ACPI_RESOURCE_NAME_END_TAG: /* - * End Dependent Functions Resource + * End Tag: This is the normal exit, add size of end_tag */ - bytes_consumed = 1; - structure_size = ACPI_RESOURCE_LENGTH; - break; + *size_needed = buffer_size + ACPI_RS_SIZE_MIN; + return_ACPI_STATUS(AE_OK); - case ACPI_RDESC_TYPE_IO_PORT: + case ACPI_RESOURCE_NAME_VENDOR_LARGE: /* - * IO Port Resource + * Vendor Resource: + * Add vendor data and ensure a 32-bit boundary for the structure */ - bytes_consumed = 8; - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_io); + extra_struct_bytes = + ACPI_ROUND_UP_to_32_bITS(resource_length) - + resource_length; break; - case ACPI_RDESC_TYPE_FIXED_IO_PORT: + case ACPI_RESOURCE_NAME_ADDRESS32: + case ACPI_RESOURCE_NAME_ADDRESS16: /* - * Fixed IO Port Resource + * 32-Bit or 16-bit Address Resource: + * Add the size of any optional data (resource_source) */ - bytes_consumed = 4; - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io); + extra_struct_bytes = + acpi_rs_stream_option_length(resource_length, + minimum_aml_resource_length); break; - case ACPI_RDESC_TYPE_SMALL_VENDOR: + case ACPI_RESOURCE_NAME_EXTENDED_IRQ: /* - * Vendor Specific Resource + * Extended IRQ: + * Point past the interrupt_vector_flags to get the + * interrupt_table_length. */ - buffer = byte_stream_buffer; + buffer++; - temp8 = *buffer; - temp8 = (u8) (temp8 & 0x7); - bytes_consumed = temp8 + 1; - - /* Ensure a 32-bit boundary for the structure */ - - temp8 = (u8) ACPI_ROUND_UP_to_32_bITS(temp8); - structure_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor) + - (temp8 * sizeof(u8)); + extra_struct_bytes = + /* + * Add 4 bytes for each additional interrupt. Note: at + * least one interrupt is required and is included in + * the minimum descriptor size + */ + ((*buffer - 1) * sizeof(u32)) + + /* Add the size of any optional data (resource_source) */ + acpi_rs_stream_option_length(resource_length - + extra_struct_bytes, + minimum_aml_resource_length); break; - case ACPI_RDESC_TYPE_END_TAG: + case ACPI_RESOURCE_NAME_ADDRESS64: /* - * End Tag + * 64-Bit Address Resource: + * Add the size of any optional data (resource_source) + * Ensure a 64-bit boundary for the structure */ - bytes_consumed = 2; - structure_size = ACPI_RESOURCE_LENGTH; - byte_stream_buffer_length = bytes_parsed; + extra_struct_bytes = + ACPI_ROUND_UP_to_64_bITS + (acpi_rs_stream_option_length + (resource_length, minimum_aml_resource_length)); break; default: - /* - * If we get here, everything is out of sync, - * exit with an error - */ - return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); + break; } - /* Update the return value and counter */ - - buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(structure_size); - bytes_parsed += bytes_consumed; + /* Update the required buffer size for the internal descriptor structs */ - /* Set the byte stream to point to the next resource */ + temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] + + extra_struct_bytes); + buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16); - byte_stream_buffer += bytes_consumed; + /* + * Point to the next resource within the stream + * using the size of the header plus the length contained in the header + */ + aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); } - /* This is the data the caller needs */ + /* Did not find an end_tag resource descriptor */ - *size_needed = buffer_size; - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); } /******************************************************************************* @@ -760,13 +541,13 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, for (table_index = 0; table_index < 4 && !name_found; table_index++) { - if ((ACPI_TYPE_STRING == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) - || - ((ACPI_TYPE_LOCAL_REFERENCE == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) - && ((*sub_object_list)->reference.opcode == - AML_INT_NAMEPATH_OP))) { + if (*sub_object_list && /* Null object allowed */ + ((ACPI_TYPE_STRING == + ACPI_GET_OBJECT_TYPE(*sub_object_list)) || + ((ACPI_TYPE_LOCAL_REFERENCE == + ACPI_GET_OBJECT_TYPE(*sub_object_list)) && + ((*sub_object_list)->reference.opcode == + AML_INT_NAMEPATH_OP)))) { name_found = TRUE; } else { /* Look at the next element */ diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 0911526b7ad8..8c128dea3252 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,10 +53,10 @@ ACPI_MODULE_NAME("rscreate") * * FUNCTION: acpi_rs_create_resource_list * - * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream - * output_buffer - Pointer to the user's buffer + * PARAMETERS: aml_buffer - Pointer to the resource byte stream + * output_buffer - Pointer to the user's buffer * - * RETURN: Status - AE_OK if okay, else a valid acpi_status code + * RETURN: Status: AE_OK if okay, else a valid acpi_status code * If output_buffer is not large enough, output_buffer_length * indicates how large output_buffer should be, else it * indicates how may u8 elements of output_buffer are valid. @@ -67,33 +67,30 @@ ACPI_MODULE_NAME("rscreate") * ******************************************************************************/ acpi_status -acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer, +acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, struct acpi_buffer *output_buffer) { acpi_status status; - u8 *byte_stream_start; + u8 *aml_start; acpi_size list_size_needed = 0; - u32 byte_stream_buffer_length; + u32 aml_buffer_length; ACPI_FUNCTION_TRACE("rs_create_resource_list"); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_buffer = %p\n", - byte_stream_buffer)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer)); /* Params already validated, so we don't re-validate here */ - byte_stream_buffer_length = byte_stream_buffer->buffer.length; - byte_stream_start = byte_stream_buffer->buffer.pointer; + aml_buffer_length = aml_buffer->buffer.length; + aml_start = aml_buffer->buffer.pointer; /* - * Pass the byte_stream_buffer into a module that can calculate + * Pass the aml_buffer into a module that can calculate * the buffer size needed for the linked list */ - status = - acpi_rs_get_list_length(byte_stream_start, - byte_stream_buffer_length, - &list_size_needed); + status = acpi_rs_get_list_length(aml_start, aml_buffer_length, + &list_size_needed); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n", status, (u32) list_size_needed)); @@ -110,10 +107,8 @@ acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer, /* Do the conversion */ - status = - acpi_rs_byte_stream_to_list(byte_stream_start, - byte_stream_buffer_length, - output_buffer->pointer); + status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length, + output_buffer->pointer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -212,21 +207,20 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* Each element of the top-level package must also be a package */ if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X]) Need sub-package, found %s\n", - index, - acpi_ut_get_object_type_name - (*top_object_list))); + ACPI_ERROR((AE_INFO, + "(PRT[%X]) Need sub-package, found %s", + index, + acpi_ut_get_object_type_name + (*top_object_list))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* Each sub-package must be of length 4 */ if ((*top_object_list)->package.count != 4) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X]) Need package of length 4, found length %d\n", - index, - (*top_object_list)->package.count)); + ACPI_ERROR((AE_INFO, + "(PRT[%X]) Need package of length 4, found length %d", + index, (*top_object_list)->package.count)); return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT); } @@ -243,11 +237,10 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { user_prt->address = obj_desc->integer.value; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X].Address) Need Integer, found %s\n", - index, - acpi_ut_get_object_type_name - (obj_desc))); + ACPI_ERROR((AE_INFO, + "(PRT[%X].Address) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); } @@ -257,76 +250,83 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { user_prt->pin = (u32) obj_desc->integer.value; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X].Pin) Need Integer, found %s\n", - index, - acpi_ut_get_object_type_name - (obj_desc))); + ACPI_ERROR((AE_INFO, + "(PRT[%X].Pin) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); } - /* 3) Third subobject: Dereference the PRT.source_name */ - + /* + * 3) Third subobject: Dereference the PRT.source_name + * The name may be unresolved (slack mode), so allow a null object + */ obj_desc = sub_object_list[2]; - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_LOCAL_REFERENCE: - - if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X].Source) Need name, found reference op %X\n", - index, - obj_desc->reference.opcode)); + if (obj_desc) { + switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + + if (obj_desc->reference.opcode != + AML_INT_NAMEPATH_OP) { + ACPI_ERROR((AE_INFO, + "(PRT[%X].Source) Need name, found reference op %X", + index, + obj_desc->reference. + opcode)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + node = obj_desc->reference.node; + + /* Use *remaining* length of the buffer as max for pathname */ + + path_buffer.length = output_buffer->length - + (u32) ((u8 *) user_prt->source - + (u8 *) output_buffer->pointer); + path_buffer.pointer = user_prt->source; + + status = + acpi_ns_handle_to_pathname((acpi_handle) + node, + &path_buffer); + + /* +1 to include null terminator */ + + user_prt->length += + (u32) ACPI_STRLEN(user_prt->source) + 1; + break; + + case ACPI_TYPE_STRING: + + ACPI_STRCPY(user_prt->source, + obj_desc->string.pointer); + + /* + * Add to the Length field the length of the string + * (add 1 for terminator) + */ + user_prt->length += obj_desc->string.length + 1; + break; + + case ACPI_TYPE_INTEGER: + /* + * If this is a number, then the Source Name is NULL, since the + * entire buffer was zeroed out, we can leave this alone. + * + * Add to the Length field the length of the u32 NULL + */ + user_prt->length += sizeof(u32); + break; + + default: + + ACPI_ERROR((AE_INFO, + "(PRT[%X].Source) Need Ref/String/Integer, found %s", + index, + acpi_ut_get_object_type_name + (obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); } - - node = obj_desc->reference.node; - - /* Use *remaining* length of the buffer as max for pathname */ - - path_buffer.length = output_buffer->length - - (u32) ((u8 *) user_prt->source - - (u8 *) output_buffer->pointer); - path_buffer.pointer = user_prt->source; - - status = - acpi_ns_handle_to_pathname((acpi_handle) node, - &path_buffer); - - /* +1 to include null terminator */ - - user_prt->length += - (u32) ACPI_STRLEN(user_prt->source) + 1; - break; - - case ACPI_TYPE_STRING: - - ACPI_STRCPY(user_prt->source, obj_desc->string.pointer); - - /* - * Add to the Length field the length of the string - * (add 1 for terminator) - */ - user_prt->length += obj_desc->string.length + 1; - break; - - case ACPI_TYPE_INTEGER: - /* - * If this is a number, then the Source Name is NULL, since the - * entire buffer was zeroed out, we can leave this alone. - * - * Add to the Length field the length of the u32 NULL - */ - user_prt->length += sizeof(u32); - break; - - default: - - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X].Source) Need Ref/String/Integer, found %s\n", - index, - acpi_ut_get_object_type_name - (obj_desc))); - return_ACPI_STATUS(AE_BAD_DATA); } /* Now align the current length */ @@ -340,11 +340,10 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { user_prt->source_index = (u32) obj_desc->integer.value; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "(PRT[%X].source_index) Need Integer, found %s\n", - index, - acpi_ut_get_object_type_name - (obj_desc))); + ACPI_ERROR((AE_INFO, + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); } @@ -360,7 +359,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /******************************************************************************* * - * FUNCTION: acpi_rs_create_byte_stream + * FUNCTION: acpi_rs_create_aml_resources * * PARAMETERS: linked_list_buffer - Pointer to the resource linked list * output_buffer - Pointer to the user's buffer @@ -377,13 +376,13 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, ******************************************************************************/ acpi_status -acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer, - struct acpi_buffer *output_buffer) +acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, + struct acpi_buffer *output_buffer) { acpi_status status; - acpi_size byte_stream_size_needed = 0; + acpi_size aml_size_needed = 0; - ACPI_FUNCTION_TRACE("rs_create_byte_stream"); + ACPI_FUNCTION_TRACE("rs_create_aml_resources"); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n", linked_list_buffer)); @@ -394,11 +393,10 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer, * Pass the linked_list_buffer into a module that calculates * the buffer size needed for the byte stream. */ - status = acpi_rs_get_byte_stream_length(linked_list_buffer, - &byte_stream_size_needed); + status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n", - (u32) byte_stream_size_needed, + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n", + (u32) aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -406,8 +404,7 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer, /* Validate/Allocate/Clear caller buffer */ - status = - acpi_ut_initialize_buffer(output_buffer, byte_stream_size_needed); + status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -415,9 +412,9 @@ acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer, /* Do the conversion */ status = - acpi_rs_list_to_byte_stream(linked_list_buffer, - byte_stream_size_needed, - output_buffer->pointer); + acpi_rs_convert_resources_to_aml(linked_list_buffer, + aml_size_needed, + output_buffer->pointer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index 75bd34d1783f..e7de061cf883 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,1063 +49,720 @@ ACPI_MODULE_NAME("rsdump") #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* Local prototypes */ -static void acpi_rs_dump_irq(union acpi_resource_data *data); +static void acpi_rs_out_string(char *title, char *value); -static void acpi_rs_dump_address16(union acpi_resource_data *data); +static void acpi_rs_out_integer8(char *title, u8 value); -static void acpi_rs_dump_address32(union acpi_resource_data *data); +static void acpi_rs_out_integer16(char *title, u16 value); -static void acpi_rs_dump_address64(union acpi_resource_data *data); +static void acpi_rs_out_integer32(char *title, u32 value); -static void acpi_rs_dump_dma(union acpi_resource_data *data); +static void acpi_rs_out_integer64(char *title, u64 value); -static void acpi_rs_dump_io(union acpi_resource_data *data); +static void acpi_rs_out_title(char *title); -static void acpi_rs_dump_extended_irq(union acpi_resource_data *data); +static void acpi_rs_dump_byte_list(u16 length, u8 * data); -static void acpi_rs_dump_fixed_io(union acpi_resource_data *data); +static void acpi_rs_dump_dword_list(u8 length, u32 * data); -static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data); +static void acpi_rs_dump_short_byte_list(u8 length, u8 * data); -static void acpi_rs_dump_memory24(union acpi_resource_data *data); +static void +acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source); -static void acpi_rs_dump_memory32(union acpi_resource_data *data); +static void acpi_rs_dump_address_common(union acpi_resource_data *resource); -static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data); +static void +acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); -static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data); +#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) +#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) /******************************************************************************* * - * FUNCTION: acpi_rs_dump_irq + * Resource Descriptor info tables * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) * ******************************************************************************/ -static void acpi_rs_dump_irq(union acpi_resource_data *data) -{ - struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *)data; - u8 index = 0; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("IRQ Resource\n"); +struct acpi_rsdump_info acpi_rs_dump_irq[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", + acpi_gbl_HEdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", + acpi_gbl_LLdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", + acpi_gbl_SHRdecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_dma[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", + acpi_gbl_TYPdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", + acpi_gbl_BMdecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", + acpi_gbl_SIZdecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", + NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), + "Start-Dependent-Functions", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), + "Compatibility Priority", acpi_gbl_config_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), + "Performance/Robustness", acpi_gbl_config_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), + "End-Dependent-Functions", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_io[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", + acpi_gbl_io_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), + "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), + "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), + "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), + "Write Protect", acpi_gbl_RWdecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), + "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), + "Write Protect", acpi_gbl_RWdecode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), + "32-Bit Fixed Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), + "Write Protect", acpi_gbl_RWdecode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address16[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), + "16-Bit WORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address32[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), + "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), + "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), + "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), + "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), + "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), + "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), + "Type-Specific Attribute", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), + "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), + "Type", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), + "Triggering", acpi_gbl_HEdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", + acpi_gbl_LLdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", + acpi_gbl_SHRdecode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), + "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), + "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} +}; - acpi_os_printf(" %s Triggered\n", - ACPI_LEVEL_SENSITIVE == - irq_data->edge_level ? "Level" : "Edge"); - - acpi_os_printf(" Active %s\n", - ACPI_ACTIVE_LOW == - irq_data->active_high_low ? "Low" : "High"); - - acpi_os_printf(" %s\n", - ACPI_SHARED == - irq_data->shared_exclusive ? "Shared" : "Exclusive"); - - acpi_os_printf(" %X Interrupts ( ", irq_data->number_of_interrupts); - - for (index = 0; index < irq_data->number_of_interrupts; index++) { - acpi_os_printf("%X ", irq_data->interrupts[index]); - } +/* + * Tables used for common address descriptor flag fields + */ +static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, + NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), + "Consumer/Producer", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", + acpi_gbl_DECdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), + "Min Relocatability", acpi_gbl_min_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), + "Max Relocatability", acpi_gbl_max_decode} +}; + +static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), + "Resource Type", (void *)"Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), + "Write Protect", acpi_gbl_RWdecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), + "Caching", acpi_gbl_MEMdecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), + "Range Type", acpi_gbl_MTPdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), + "Translation", acpi_gbl_TTPdecode} +}; + +static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), + "Resource Type", (void *)"I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), + "Range Type", acpi_gbl_RNGdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), + "Translation", acpi_gbl_TTPdecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), + "Translation Type", acpi_gbl_TRSdecode} +}; - acpi_os_printf(")\n"); - return; -} +/* + * Table used to dump _PRT contents + */ +static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_dump_dma + * FUNCTION: acpi_rs_dump_descriptor * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: Resource * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: * ******************************************************************************/ -static void acpi_rs_dump_dma(union acpi_resource_data *data) +static void +acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) { - struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *)data; - u8 index = 0; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("DMA Resource\n"); - - switch (dma_data->type) { - case ACPI_COMPATIBILITY: - acpi_os_printf(" Compatibility mode\n"); - break; - - case ACPI_TYPE_A: - acpi_os_printf(" Type A\n"); - break; - - case ACPI_TYPE_B: - acpi_os_printf(" Type B\n"); - break; - - case ACPI_TYPE_F: - acpi_os_printf(" Type F\n"); - break; - - default: - acpi_os_printf(" Invalid DMA type\n"); - break; - } - - acpi_os_printf(" %sBus Master\n", - ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a "); - - switch (dma_data->transfer) { - case ACPI_TRANSFER_8: - acpi_os_printf(" 8-bit only transfer\n"); - break; + u8 *target = NULL; + u8 *previous_target; + char *name; + u8 count; + + /* First table entry must contain the table length (# of table entries) */ + + count = table->offset; + + while (count) { + previous_target = target; + target = ACPI_ADD_PTR(u8, resource, table->offset); + name = table->name; + + switch (table->opcode) { + case ACPI_RSD_TITLE: + /* + * Optional resource title + */ + if (table->name) { + acpi_os_printf("%s Resource\n", name); + } + break; - case ACPI_TRANSFER_8_16: - acpi_os_printf(" 8 and 16-bit transfer\n"); - break; + /* Strings */ - case ACPI_TRANSFER_16: - acpi_os_printf(" 16 bit only transfer\n"); - break; + case ACPI_RSD_LITERAL: + acpi_rs_out_string(name, + ACPI_CAST_PTR(char, table->pointer)); + break; - default: - acpi_os_printf(" Invalid transfer preference\n"); - break; - } + case ACPI_RSD_STRING: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); + break; - acpi_os_printf(" Number of Channels: %X ( ", - dma_data->number_of_channels); + /* Data items, 8/16/32/64 bit */ - for (index = 0; index < dma_data->number_of_channels; index++) { - acpi_os_printf("%X ", dma_data->channels[index]); - } + case ACPI_RSD_UINT8: + acpi_rs_out_integer8(name, ACPI_GET8(target)); + break; - acpi_os_printf(")\n"); - return; -} + case ACPI_RSD_UINT16: + acpi_rs_out_integer16(name, ACPI_GET16(target)); + break; -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_start_depend_fns - * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ + case ACPI_RSD_UINT32: + acpi_rs_out_integer32(name, ACPI_GET32(target)); + break; -static void acpi_rs_dump_start_depend_fns(union acpi_resource_data *data) -{ - struct acpi_resource_start_dpf *sdf_data = - (struct acpi_resource_start_dpf *)data; + case ACPI_RSD_UINT64: + acpi_rs_out_integer64(name, ACPI_GET64(target)); + break; - ACPI_FUNCTION_ENTRY(); + /* Flags: 1-bit and 2-bit flags supported */ - acpi_os_printf("Start Dependent Functions Resource\n"); + case ACPI_RSD_1BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, + table-> + pointer[*target & + 0x01])); + break; - switch (sdf_data->compatibility_priority) { - case ACPI_GOOD_CONFIGURATION: - acpi_os_printf(" Good configuration\n"); - break; + case ACPI_RSD_2BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, + table-> + pointer[*target & + 0x03])); + break; - case ACPI_ACCEPTABLE_CONFIGURATION: - acpi_os_printf(" Acceptable configuration\n"); - break; + case ACPI_RSD_SHORTLIST: + /* + * Short byte list (single line output) for DMA and IRQ resources + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_out_title(name); + acpi_rs_dump_short_byte_list(*previous_target, + target); + } + break; - case ACPI_SUB_OPTIMAL_CONFIGURATION: - acpi_os_printf(" Sub-optimal configuration\n"); - break; + case ACPI_RSD_LONGLIST: + /* + * Long byte list for Vendor resource data + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_dump_byte_list(ACPI_GET16 + (previous_target), + target); + } + break; - default: - acpi_os_printf(" Invalid compatibility priority\n"); - break; - } + case ACPI_RSD_DWORDLIST: + /* + * Dword list for Extended Interrupt resources + * Note: The list length is obtained from the previous table entry + */ + if (previous_target) { + acpi_rs_dump_dword_list(*previous_target, + ACPI_CAST_PTR(u32, + target)); + } + break; - switch (sdf_data->performance_robustness) { - case ACPI_GOOD_CONFIGURATION: - acpi_os_printf(" Good configuration\n"); - break; + case ACPI_RSD_ADDRESS: + /* + * Common flags for all Address resources + */ + acpi_rs_dump_address_common(ACPI_CAST_PTR + (union acpi_resource_data, + target)); + break; - case ACPI_ACCEPTABLE_CONFIGURATION: - acpi_os_printf(" Acceptable configuration\n"); - break; + case ACPI_RSD_SOURCE: + /* + * Optional resource_source for Address resources + */ + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct + acpi_resource_source, + target)); + break; - case ACPI_SUB_OPTIMAL_CONFIGURATION: - acpi_os_printf(" Sub-optimal configuration\n"); - break; + default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", + table->opcode); + return; + } - default: - acpi_os_printf(" Invalid performance robustness preference\n"); - break; + table++; + count--; } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_io - * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ - -static void acpi_rs_dump_io(union acpi_resource_data *data) -{ - struct acpi_resource_io *io_data = (struct acpi_resource_io *)data; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("Io Resource\n"); - - acpi_os_printf(" %d bit decode\n", - ACPI_DECODE_16 == io_data->io_decode ? 16 : 10); - - acpi_os_printf(" Range minimum base: %08X\n", - io_data->min_base_address); - - acpi_os_printf(" Range maximum base: %08X\n", - io_data->max_base_address); - - acpi_os_printf(" Alignment: %08X\n", io_data->alignment); - - acpi_os_printf(" Range Length: %08X\n", io_data->range_length); - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_fixed_io - * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ - -static void acpi_rs_dump_fixed_io(union acpi_resource_data *data) -{ - struct acpi_resource_fixed_io *fixed_io_data = - (struct acpi_resource_fixed_io *)data; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("Fixed Io Resource\n"); - acpi_os_printf(" Range base address: %08X", - fixed_io_data->base_address); - - acpi_os_printf(" Range length: %08X", fixed_io_data->range_length); - - return; } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_vendor_specific + * FUNCTION: acpi_rs_dump_resource_source * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: resource_source - Pointer to a Resource Source struct * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: Common routine for dumping the optional resource_source and the + * corresponding resource_source_index. * ******************************************************************************/ -static void acpi_rs_dump_vendor_specific(union acpi_resource_data *data) +static void +acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source) { - struct acpi_resource_vendor *vendor_data = - (struct acpi_resource_vendor *)data; - u16 index = 0; - ACPI_FUNCTION_ENTRY(); - acpi_os_printf("Vendor Specific Resource\n"); - - acpi_os_printf(" Length: %08X\n", vendor_data->length); - - for (index = 0; index < vendor_data->length; index++) { - acpi_os_printf(" Byte %X: %08X\n", - index, vendor_data->reserved[index]); + if (resource_source->index == 0xFF) { + return; } - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_memory24 - * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ - -static void acpi_rs_dump_memory24(union acpi_resource_data *data) -{ - struct acpi_resource_mem24 *memory24_data = - (struct acpi_resource_mem24 *)data; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("24-Bit Memory Range Resource\n"); - - acpi_os_printf(" Read%s\n", - ACPI_READ_WRITE_MEMORY == - memory24_data->read_write_attribute ? - "/Write" : " only"); - - acpi_os_printf(" Range minimum base: %08X\n", - memory24_data->min_base_address); - - acpi_os_printf(" Range maximum base: %08X\n", - memory24_data->max_base_address); - - acpi_os_printf(" Alignment: %08X\n", memory24_data->alignment); - - acpi_os_printf(" Range length: %08X\n", memory24_data->range_length); - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_memory32 - * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ - -static void acpi_rs_dump_memory32(union acpi_resource_data *data) -{ - struct acpi_resource_mem32 *memory32_data = - (struct acpi_resource_mem32 *)data; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("32-Bit Memory Range Resource\n"); - - acpi_os_printf(" Read%s\n", - ACPI_READ_WRITE_MEMORY == - memory32_data->read_write_attribute ? - "/Write" : " only"); - - acpi_os_printf(" Range minimum base: %08X\n", - memory32_data->min_base_address); - - acpi_os_printf(" Range maximum base: %08X\n", - memory32_data->max_base_address); - - acpi_os_printf(" Alignment: %08X\n", memory32_data->alignment); - - acpi_os_printf(" Range length: %08X\n", memory32_data->range_length); + acpi_rs_out_integer8("Resource Source Index", resource_source->index); - return; + acpi_rs_out_string("Resource Source", + resource_source->string_ptr ? + resource_source->string_ptr : "[Not Specified]"); } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_fixed_memory32 + * FUNCTION: acpi_rs_dump_address_common * - * PARAMETERS: Data - pointer to the resource structure to dump. - * - * RETURN: - * - * DESCRIPTION: Prints out the various members of the Data structure type. - * - ******************************************************************************/ - -static void acpi_rs_dump_fixed_memory32(union acpi_resource_data *data) -{ - struct acpi_resource_fixed_mem32 *fixed_memory32_data = - (struct acpi_resource_fixed_mem32 *)data; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("32-Bit Fixed Location Memory Range Resource\n"); - - acpi_os_printf(" Read%s\n", - ACPI_READ_WRITE_MEMORY == - fixed_memory32_data-> - read_write_attribute ? "/Write" : " Only"); - - acpi_os_printf(" Range base address: %08X\n", - fixed_memory32_data->range_base_address); - - acpi_os_printf(" Range length: %08X\n", - fixed_memory32_data->range_length); - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_address16 - * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: Resource - Pointer to an internal resource descriptor * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: Dump the fields that are common to all Address resource + * descriptors * ******************************************************************************/ -static void acpi_rs_dump_address16(union acpi_resource_data *data) +static void acpi_rs_dump_address_common(union acpi_resource_data *resource) { - struct acpi_resource_address16 *address16_data = - (struct acpi_resource_address16 *)data; - ACPI_FUNCTION_ENTRY(); - acpi_os_printf("16-Bit Address Space Resource\n"); - acpi_os_printf(" Resource Type: "); + /* Decode the type-specific flags */ - switch (address16_data->resource_type) { + switch (resource->address.resource_type) { case ACPI_MEMORY_RANGE: - acpi_os_printf("Memory Range\n"); - - switch (address16_data->attribute.memory.cache_attribute) { - case ACPI_NON_CACHEABLE_MEMORY: - acpi_os_printf - (" Type Specific: Noncacheable memory\n"); - break; - - case ACPI_CACHABLE_MEMORY: - acpi_os_printf(" Type Specific: Cacheable memory\n"); - break; - - case ACPI_WRITE_COMBINING_MEMORY: - acpi_os_printf - (" Type Specific: Write-combining memory\n"); - break; - - case ACPI_PREFETCHABLE_MEMORY: - acpi_os_printf - (" Type Specific: Prefetchable memory\n"); - break; - - default: - acpi_os_printf - (" Type Specific: Invalid cache attribute\n"); - break; - } - - acpi_os_printf(" Type Specific: Read%s\n", - ACPI_READ_WRITE_MEMORY == - address16_data->attribute.memory. - read_write_attribute ? "/Write" : " Only"); + acpi_rs_dump_descriptor(resource, acpi_rs_dump_memory_flags); break; case ACPI_IO_RANGE: - acpi_os_printf("I/O Range\n"); - - switch (address16_data->attribute.io.range_attribute) { - case ACPI_NON_ISA_ONLY_RANGES: - acpi_os_printf - (" Type Specific: Non-ISA Io Addresses\n"); - break; - - case ACPI_ISA_ONLY_RANGES: - acpi_os_printf(" Type Specific: ISA Io Addresses\n"); - break; - - case ACPI_ENTIRE_RANGE: - acpi_os_printf - (" Type Specific: ISA and non-ISA Io Addresses\n"); - break; - - default: - acpi_os_printf - (" Type Specific: Invalid range attribute\n"); - break; - } - - acpi_os_printf(" Type Specific: %s Translation\n", - ACPI_SPARSE_TRANSLATION == - address16_data->attribute.io. - translation_attribute ? "Sparse" : "Dense"); + acpi_rs_dump_descriptor(resource, acpi_rs_dump_io_flags); break; case ACPI_BUS_NUMBER_RANGE: - acpi_os_printf("Bus Number Range\n"); + acpi_rs_out_string("Resource Type", "Bus Number Range"); break; default: - acpi_os_printf("0x%2.2X\n", address16_data->resource_type); + acpi_rs_out_integer8("Resource Type", + (u8) resource->address.resource_type); break; } - acpi_os_printf(" Resource %s\n", - ACPI_CONSUMER == address16_data->producer_consumer ? - "Consumer" : "Producer"); - - acpi_os_printf(" %s decode\n", - ACPI_SUB_DECODE == address16_data->decode ? - "Subtractive" : "Positive"); + /* Decode the general flags */ - acpi_os_printf(" Min address is %s fixed\n", - ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ? - "" : "not"); - - acpi_os_printf(" Max address is %s fixed\n", - ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ? - "" : "not"); - - acpi_os_printf(" Granularity: %08X\n", address16_data->granularity); - - acpi_os_printf(" Address range min: %08X\n", - address16_data->min_address_range); - - acpi_os_printf(" Address range max: %08X\n", - address16_data->max_address_range); - - acpi_os_printf(" Address translation offset: %08X\n", - address16_data->address_translation_offset); - - acpi_os_printf(" Address Length: %08X\n", - address16_data->address_length); - - if (0xFF != address16_data->resource_source.index) { - acpi_os_printf(" Resource Source Index: %X\n", - address16_data->resource_source.index); - - acpi_os_printf(" Resource Source: %s\n", - address16_data->resource_source.string_ptr); - } - - return; + acpi_rs_dump_descriptor(resource, acpi_rs_dump_general_flags); } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_address32 + * FUNCTION: acpi_rs_dump_resource_list * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: resource_list - Pointer to a resource descriptor list * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: Dispatches the structure to the correct dump routine. * ******************************************************************************/ -static void acpi_rs_dump_address32(union acpi_resource_data *data) +void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) { - struct acpi_resource_address32 *address32_data = - (struct acpi_resource_address32 *)data; + u32 count = 0; + u32 type; ACPI_FUNCTION_ENTRY(); - acpi_os_printf("32-Bit Address Space Resource\n"); - - switch (address32_data->resource_type) { - case ACPI_MEMORY_RANGE: - - acpi_os_printf(" Resource Type: Memory Range\n"); - - switch (address32_data->attribute.memory.cache_attribute) { - case ACPI_NON_CACHEABLE_MEMORY: - acpi_os_printf - (" Type Specific: Noncacheable memory\n"); - break; - - case ACPI_CACHABLE_MEMORY: - acpi_os_printf(" Type Specific: Cacheable memory\n"); - break; - - case ACPI_WRITE_COMBINING_MEMORY: - acpi_os_printf - (" Type Specific: Write-combining memory\n"); - break; - - case ACPI_PREFETCHABLE_MEMORY: - acpi_os_printf - (" Type Specific: Prefetchable memory\n"); - break; - - default: - acpi_os_printf - (" Type Specific: Invalid cache attribute\n"); - break; - } - - acpi_os_printf(" Type Specific: Read%s\n", - ACPI_READ_WRITE_MEMORY == - address32_data->attribute.memory. - read_write_attribute ? "/Write" : " Only"); - break; - - case ACPI_IO_RANGE: - - acpi_os_printf(" Resource Type: Io Range\n"); + if (!(acpi_dbg_level & ACPI_LV_RESOURCES) + || !(_COMPONENT & acpi_dbg_layer)) { + return; + } - switch (address32_data->attribute.io.range_attribute) { - case ACPI_NON_ISA_ONLY_RANGES: - acpi_os_printf - (" Type Specific: Non-ISA Io Addresses\n"); - break; + /* Walk list and dump all resource descriptors (END_TAG terminates) */ - case ACPI_ISA_ONLY_RANGES: - acpi_os_printf(" Type Specific: ISA Io Addresses\n"); - break; + do { + acpi_os_printf("\n[%02X] ", count); + count++; - case ACPI_ENTIRE_RANGE: - acpi_os_printf - (" Type Specific: ISA and non-ISA Io Addresses\n"); - break; + /* Validate Type before dispatch */ - default: + type = resource_list->type; + if (type > ACPI_RESOURCE_TYPE_MAX) { acpi_os_printf - (" Type Specific: Invalid Range attribute"); - break; + ("Invalid descriptor type (%X) in resource list\n", + resource_list->type); + return; } - acpi_os_printf(" Type Specific: %s Translation\n", - ACPI_SPARSE_TRANSLATION == - address32_data->attribute.io. - translation_attribute ? "Sparse" : "Dense"); - break; - - case ACPI_BUS_NUMBER_RANGE: - - acpi_os_printf(" Resource Type: Bus Number Range\n"); - break; - - default: - - acpi_os_printf(" Resource Type: 0x%2.2X\n", - address32_data->resource_type); - break; - } - - acpi_os_printf(" Resource %s\n", - ACPI_CONSUMER == address32_data->producer_consumer ? - "Consumer" : "Producer"); - - acpi_os_printf(" %s decode\n", - ACPI_SUB_DECODE == address32_data->decode ? - "Subtractive" : "Positive"); - - acpi_os_printf(" Min address is %s fixed\n", - ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ? - "" : "not "); - - acpi_os_printf(" Max address is %s fixed\n", - ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ? - "" : "not "); + /* Dump the resource descriptor */ - acpi_os_printf(" Granularity: %08X\n", address32_data->granularity); + acpi_rs_dump_descriptor(&resource_list->data, + acpi_gbl_dump_resource_dispatch[type]); - acpi_os_printf(" Address range min: %08X\n", - address32_data->min_address_range); + /* Point to the next resource structure */ - acpi_os_printf(" Address range max: %08X\n", - address32_data->max_address_range); + resource_list = + ACPI_ADD_PTR(struct acpi_resource, resource_list, + resource_list->length); - acpi_os_printf(" Address translation offset: %08X\n", - address32_data->address_translation_offset); + /* Exit when END_TAG descriptor is reached */ - acpi_os_printf(" Address Length: %08X\n", - address32_data->address_length); - - if (0xFF != address32_data->resource_source.index) { - acpi_os_printf(" Resource Source Index: %X\n", - address32_data->resource_source.index); - - acpi_os_printf(" Resource Source: %s\n", - address32_data->resource_source.string_ptr); - } - - return; + } while (type != ACPI_RESOURCE_TYPE_END_TAG); } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_address64 + * FUNCTION: acpi_rs_dump_irq_list * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: route_table - Pointer to the routing table to dump. * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: Print IRQ routing table * ******************************************************************************/ -static void acpi_rs_dump_address64(union acpi_resource_data *data) +void acpi_rs_dump_irq_list(u8 * route_table) { - struct acpi_resource_address64 *address64_data = - (struct acpi_resource_address64 *)data; + struct acpi_pci_routing_table *prt_element; + u8 count; ACPI_FUNCTION_ENTRY(); - acpi_os_printf("64-Bit Address Space Resource\n"); - - switch (address64_data->resource_type) { - case ACPI_MEMORY_RANGE: - - acpi_os_printf(" Resource Type: Memory Range\n"); - - switch (address64_data->attribute.memory.cache_attribute) { - case ACPI_NON_CACHEABLE_MEMORY: - acpi_os_printf - (" Type Specific: Noncacheable memory\n"); - break; - - case ACPI_CACHABLE_MEMORY: - acpi_os_printf(" Type Specific: Cacheable memory\n"); - break; - - case ACPI_WRITE_COMBINING_MEMORY: - acpi_os_printf - (" Type Specific: Write-combining memory\n"); - break; - - case ACPI_PREFETCHABLE_MEMORY: - acpi_os_printf - (" Type Specific: Prefetchable memory\n"); - break; - - default: - acpi_os_printf - (" Type Specific: Invalid cache attribute\n"); - break; - } - - acpi_os_printf(" Type Specific: Read%s\n", - ACPI_READ_WRITE_MEMORY == - address64_data->attribute.memory. - read_write_attribute ? "/Write" : " Only"); - break; - - case ACPI_IO_RANGE: - - acpi_os_printf(" Resource Type: Io Range\n"); - - switch (address64_data->attribute.io.range_attribute) { - case ACPI_NON_ISA_ONLY_RANGES: - acpi_os_printf - (" Type Specific: Non-ISA Io Addresses\n"); - break; - - case ACPI_ISA_ONLY_RANGES: - acpi_os_printf(" Type Specific: ISA Io Addresses\n"); - break; - - case ACPI_ENTIRE_RANGE: - acpi_os_printf - (" Type Specific: ISA and non-ISA Io Addresses\n"); - break; - - default: - acpi_os_printf - (" Type Specific: Invalid Range attribute"); - break; - } - - acpi_os_printf(" Type Specific: %s Translation\n", - ACPI_SPARSE_TRANSLATION == - address64_data->attribute.io. - translation_attribute ? "Sparse" : "Dense"); - break; - - case ACPI_BUS_NUMBER_RANGE: - - acpi_os_printf(" Resource Type: Bus Number Range\n"); - break; - - default: - - acpi_os_printf(" Resource Type: 0x%2.2X\n", - address64_data->resource_type); - break; + if (!(acpi_dbg_level & ACPI_LV_RESOURCES) + || !(_COMPONENT & acpi_dbg_layer)) { + return; } - acpi_os_printf(" Resource %s\n", - ACPI_CONSUMER == address64_data->producer_consumer ? - "Consumer" : "Producer"); - - acpi_os_printf(" %s decode\n", - ACPI_SUB_DECODE == address64_data->decode ? - "Subtractive" : "Positive"); - - acpi_os_printf(" Min address is %s fixed\n", - ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ? - "" : "not "); - - acpi_os_printf(" Max address is %s fixed\n", - ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ? - "" : "not "); + prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, route_table); - acpi_os_printf(" Granularity: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data->granularity)); + /* Dump all table elements, Exit on zero length element */ - acpi_os_printf(" Address range min: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data->min_address_range)); + for (count = 0; prt_element->length; count++) { + acpi_os_printf("\n[%02X] PCI IRQ Routing Table Package\n", + count); + acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt); - acpi_os_printf(" Address range max: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data->max_address_range)); - - acpi_os_printf(" Address translation offset: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data-> - address_translation_offset)); - - acpi_os_printf(" Address Length: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data->address_length)); - - acpi_os_printf(" Type Specific Attributes: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(address64_data-> - type_specific_attributes)); - - if (0xFF != address64_data->resource_source.index) { - acpi_os_printf(" Resource Source Index: %X\n", - address64_data->resource_source.index); - - acpi_os_printf(" Resource Source: %s\n", - address64_data->resource_source.string_ptr); + prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table, + prt_element, prt_element->length); } - - return; } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_extended_irq + * FUNCTION: acpi_rs_out* * - * PARAMETERS: Data - pointer to the resource structure to dump. + * PARAMETERS: Title - Name of the resource field + * Value - Value of the resource field * * RETURN: None * - * DESCRIPTION: Prints out the various members of the Data structure type. + * DESCRIPTION: Miscellaneous helper functions to consistently format the + * output of the resource dump routines * ******************************************************************************/ -static void acpi_rs_dump_extended_irq(union acpi_resource_data *data) +static void acpi_rs_out_string(char *title, char *value) { - struct acpi_resource_ext_irq *ext_irq_data = - (struct acpi_resource_ext_irq *)data; - u8 index = 0; - - ACPI_FUNCTION_ENTRY(); - - acpi_os_printf("Extended IRQ Resource\n"); - - acpi_os_printf(" Resource %s\n", - ACPI_CONSUMER == ext_irq_data->producer_consumer ? - "Consumer" : "Producer"); - - acpi_os_printf(" %s\n", - ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ? - "Level" : "Edge"); - - acpi_os_printf(" Active %s\n", - ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ? - "low" : "high"); - - acpi_os_printf(" %s\n", - ACPI_SHARED == ext_irq_data->shared_exclusive ? - "Shared" : "Exclusive"); - - acpi_os_printf(" Interrupts : %X ( ", - ext_irq_data->number_of_interrupts); - - for (index = 0; index < ext_irq_data->number_of_interrupts; index++) { - acpi_os_printf("%X ", ext_irq_data->interrupts[index]); - } - - acpi_os_printf(")\n"); - - if (0xFF != ext_irq_data->resource_source.index) { - acpi_os_printf(" Resource Source Index: %X", - ext_irq_data->resource_source.index); - - acpi_os_printf(" Resource Source: %s", - ext_irq_data->resource_source.string_ptr); + acpi_os_printf("%27s : %s", title, value); + if (!*value) { + acpi_os_printf("[NULL NAMESTRING]"); } - - return; + acpi_os_printf("\n"); } -/******************************************************************************* - * - * FUNCTION: acpi_rs_dump_resource_list - * - * PARAMETERS: Resource - pointer to the resource structure to dump. - * - * RETURN: None - * - * DESCRIPTION: Dispatches the structure to the correct dump routine. - * - ******************************************************************************/ - -void acpi_rs_dump_resource_list(struct acpi_resource *resource) +static void acpi_rs_out_integer8(char *title, u8 value) { - u8 count = 0; - u8 done = FALSE; - - ACPI_FUNCTION_ENTRY(); - - if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { - while (!done) { - acpi_os_printf("Resource structure %X.\n", count++); - - switch (resource->id) { - case ACPI_RSTYPE_IRQ: - acpi_rs_dump_irq(&resource->data); - break; - - case ACPI_RSTYPE_DMA: - acpi_rs_dump_dma(&resource->data); - break; - - case ACPI_RSTYPE_START_DPF: - acpi_rs_dump_start_depend_fns(&resource->data); - break; - - case ACPI_RSTYPE_END_DPF: - acpi_os_printf - ("end_dependent_functions Resource\n"); - /* acpi_rs_dump_end_dependent_functions (Resource->Data); */ - break; - - case ACPI_RSTYPE_IO: - acpi_rs_dump_io(&resource->data); - break; - - case ACPI_RSTYPE_FIXED_IO: - acpi_rs_dump_fixed_io(&resource->data); - break; - - case ACPI_RSTYPE_VENDOR: - acpi_rs_dump_vendor_specific(&resource->data); - break; - - case ACPI_RSTYPE_END_TAG: - /*rs_dump_end_tag (Resource->Data); */ - acpi_os_printf("end_tag Resource\n"); - done = TRUE; - break; - - case ACPI_RSTYPE_MEM24: - acpi_rs_dump_memory24(&resource->data); - break; - - case ACPI_RSTYPE_MEM32: - acpi_rs_dump_memory32(&resource->data); - break; - - case ACPI_RSTYPE_FIXED_MEM32: - acpi_rs_dump_fixed_memory32(&resource->data); - break; - - case ACPI_RSTYPE_ADDRESS16: - acpi_rs_dump_address16(&resource->data); - break; - - case ACPI_RSTYPE_ADDRESS32: - acpi_rs_dump_address32(&resource->data); - break; - - case ACPI_RSTYPE_ADDRESS64: - acpi_rs_dump_address64(&resource->data); - break; - - case ACPI_RSTYPE_EXT_IRQ: - acpi_rs_dump_extended_irq(&resource->data); - break; + acpi_os_printf("%27s : %2.2X\n", title, value); +} - default: - acpi_os_printf("Invalid resource type\n"); - break; +static void acpi_rs_out_integer16(char *title, u16 value) +{ + acpi_os_printf("%27s : %4.4X\n", title, value); +} - } +static void acpi_rs_out_integer32(char *title, u32 value) +{ + acpi_os_printf("%27s : %8.8X\n", title, value); +} - resource = - ACPI_PTR_ADD(struct acpi_resource, resource, - resource->length); - } - } +static void acpi_rs_out_integer64(char *title, u64 value) +{ + acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value)); +} - return; +static void acpi_rs_out_title(char *title) +{ + acpi_os_printf("%27s : ", title); } /******************************************************************************* * - * FUNCTION: acpi_rs_dump_irq_list + * FUNCTION: acpi_rs_dump*List * - * PARAMETERS: route_table - pointer to the routing table to dump. + * PARAMETERS: Length - Number of elements in the list + * Data - Start of the list * * RETURN: None * - * DESCRIPTION: Dispatches the structures to the correct dump routine. + * DESCRIPTION: Miscellaneous functions to dump lists of raw data * ******************************************************************************/ -void acpi_rs_dump_irq_list(u8 * route_table) +static void acpi_rs_dump_byte_list(u16 length, u8 * data) { - u8 *buffer = route_table; - u8 count = 0; - u8 done = FALSE; - struct acpi_pci_routing_table *prt_element; + u8 i; - ACPI_FUNCTION_ENTRY(); - - if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { - prt_element = - ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer); - - while (!done) { - acpi_os_printf("PCI IRQ Routing Table structure %X.\n", - count++); - - acpi_os_printf(" Address: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(prt_element-> - address)); + for (i = 0; i < length; i++) { + acpi_os_printf("%25s%2.2X : %2.2X\n", "Byte", i, data[i]); + } +} - acpi_os_printf(" Pin: %X\n", prt_element->pin); +static void acpi_rs_dump_short_byte_list(u8 length, u8 * data) +{ + u8 i; - acpi_os_printf(" Source: %s\n", prt_element->source); + for (i = 0; i < length; i++) { + acpi_os_printf("%X ", data[i]); + } + acpi_os_printf("\n"); +} - acpi_os_printf(" source_index: %X\n", - prt_element->source_index); +static void acpi_rs_dump_dword_list(u8 length, u32 * data) +{ + u8 i; - buffer += prt_element->length; - prt_element = - ACPI_CAST_PTR(struct acpi_pci_routing_table, - buffer); - if (0 == prt_element->length) { - done = TRUE; - } - } + for (i = 0; i < length; i++) { + acpi_os_printf("%25s%2.2X : %8.8X\n", "Dword", i, data[i]); } - - return; } #endif diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c new file mode 100644 index 000000000000..d9ae64b77bd9 --- /dev/null +++ b/drivers/acpi/resources/rsinfo.c @@ -0,0 +1,204 @@ +/******************************************************************************* + * + * Module Name: rsinfo - Dispatch and Info tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include <acpi/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsinfo") + +/* + * Resource dispatch and information tables. Any new resource types (either + * Large or Small) must be reflected in each of these tables, so they are here + * in one place. + * + * The tables for Large descriptors are indexed by bits 6:0 of the AML + * descriptor type byte. The tables for Small descriptors are indexed by + * bits 6:3 of the descriptor byte. The tables for internal resource + * descriptors are indexed by the acpi_resource_type field. + */ +/* Dispatch table for resource-to-AML (Set Resource) conversion functions */ +struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = { + acpi_rs_set_irq, /* 0x00, ACPI_RESOURCE_TYPE_IRQ */ + acpi_rs_convert_dma, /* 0x01, ACPI_RESOURCE_TYPE_DMA */ + acpi_rs_set_start_dpf, /* 0x02, ACPI_RESOURCE_TYPE_START_DEPENDENT */ + acpi_rs_convert_end_dpf, /* 0x03, ACPI_RESOURCE_TYPE_END_DEPENDENT */ + acpi_rs_convert_io, /* 0x04, ACPI_RESOURCE_TYPE_IO */ + acpi_rs_convert_fixed_io, /* 0x05, ACPI_RESOURCE_TYPE_FIXED_IO */ + acpi_rs_set_vendor, /* 0x06, ACPI_RESOURCE_TYPE_VENDOR */ + acpi_rs_convert_end_tag, /* 0x07, ACPI_RESOURCE_TYPE_END_TAG */ + acpi_rs_convert_memory24, /* 0x08, ACPI_RESOURCE_TYPE_MEMORY24 */ + acpi_rs_convert_memory32, /* 0x09, ACPI_RESOURCE_TYPE_MEMORY32 */ + acpi_rs_convert_fixed_memory32, /* 0x0A, ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + acpi_rs_convert_address16, /* 0x0B, ACPI_RESOURCE_TYPE_ADDRESS16 */ + acpi_rs_convert_address32, /* 0x0C, ACPI_RESOURCE_TYPE_ADDRESS32 */ + acpi_rs_convert_address64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */ + acpi_rs_convert_ext_address64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + acpi_rs_convert_ext_irq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + acpi_rs_convert_generic_reg /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; + +/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */ + +struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = { + /* Small descriptors */ + + NULL, /* 0x00, Reserved */ + NULL, /* 0x01, Reserved */ + NULL, /* 0x02, Reserved */ + NULL, /* 0x03, Reserved */ + acpi_rs_get_irq, /* 0x04, ACPI_RESOURCE_NAME_IRQ */ + acpi_rs_convert_dma, /* 0x05, ACPI_RESOURCE_NAME_DMA */ + acpi_rs_get_start_dpf, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ + acpi_rs_convert_end_dpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ + acpi_rs_convert_io, /* 0x08, ACPI_RESOURCE_NAME_IO */ + acpi_rs_convert_fixed_io, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */ + NULL, /* 0x0A, Reserved */ + NULL, /* 0x0B, Reserved */ + NULL, /* 0x0C, Reserved */ + NULL, /* 0x0D, Reserved */ + acpi_rs_get_vendor_small, /* 0x0E, ACPI_RESOURCE_NAME_VENDOR_SMALL */ + acpi_rs_convert_end_tag, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG */ + + /* Large descriptors */ + + NULL, /* 0x00, Reserved */ + acpi_rs_convert_memory24, /* 0x01, ACPI_RESOURCE_NAME_MEMORY24 */ + acpi_rs_convert_generic_reg, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ + NULL, /* 0x03, Reserved */ + acpi_rs_get_vendor_large, /* 0x04, ACPI_RESOURCE_NAME_VENDOR_LARGE */ + acpi_rs_convert_memory32, /* 0x05, ACPI_RESOURCE_NAME_MEMORY32 */ + acpi_rs_convert_fixed_memory32, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY32 */ + acpi_rs_convert_address32, /* 0x07, ACPI_RESOURCE_NAME_ADDRESS32 */ + acpi_rs_convert_address16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */ + acpi_rs_convert_ext_irq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */ + acpi_rs_convert_address64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */ + acpi_rs_convert_ext_address64 /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */ +}; + +#ifdef ACPI_FUTURE_USAGE +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Dispatch table for resource dump functions */ + +struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { + acpi_rs_dump_irq, /* ACPI_RESOURCE_TYPE_IRQ */ + acpi_rs_dump_dma, /* ACPI_RESOURCE_TYPE_DMA */ + acpi_rs_dump_start_dpf, /* ACPI_RESOURCE_TYPE_START_DEPENDENT */ + acpi_rs_dump_end_dpf, /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + acpi_rs_dump_io, /* ACPI_RESOURCE_TYPE_IO */ + acpi_rs_dump_fixed_io, /* ACPI_RESOURCE_TYPE_FIXED_IO */ + acpi_rs_dump_vendor, /* ACPI_RESOURCE_TYPE_VENDOR */ + acpi_rs_dump_end_tag, /* ACPI_RESOURCE_TYPE_END_TAG */ + acpi_rs_dump_memory24, /* ACPI_RESOURCE_TYPE_MEMORY24 */ + acpi_rs_dump_memory32, /* ACPI_RESOURCE_TYPE_MEMORY32 */ + acpi_rs_dump_fixed_memory32, /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + acpi_rs_dump_address16, /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + acpi_rs_dump_address32, /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + acpi_rs_dump_address64, /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + acpi_rs_dump_ext_address64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + acpi_rs_dump_ext_irq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; +#endif +#endif /* ACPI_FUTURE_USAGE */ +/* + * Base sizes for external AML resource descriptors, indexed by internal type. + * Includes size of the descriptor header (1 byte for small descriptors, + * 3 bytes for large descriptors) + */ +const u8 acpi_gbl_aml_resource_sizes[] = { + sizeof(struct aml_resource_irq), /* ACPI_RESOURCE_TYPE_IRQ (optional Byte 3 always created) */ + sizeof(struct aml_resource_dma), /* ACPI_RESOURCE_TYPE_DMA */ + sizeof(struct aml_resource_start_dependent), /* ACPI_RESOURCE_TYPE_START_DEPENDENT (optional Byte 1 always created) */ + sizeof(struct aml_resource_end_dependent), /* ACPI_RESOURCE_TYPE_END_DEPENDENT */ + sizeof(struct aml_resource_io), /* ACPI_RESOURCE_TYPE_IO */ + sizeof(struct aml_resource_fixed_io), /* ACPI_RESOURCE_TYPE_FIXED_IO */ + sizeof(struct aml_resource_vendor_small), /* ACPI_RESOURCE_TYPE_VENDOR */ + sizeof(struct aml_resource_end_tag), /* ACPI_RESOURCE_TYPE_END_TAG */ + sizeof(struct aml_resource_memory24), /* ACPI_RESOURCE_TYPE_MEMORY24 */ + sizeof(struct aml_resource_memory32), /* ACPI_RESOURCE_TYPE_MEMORY32 */ + sizeof(struct aml_resource_fixed_memory32), /* ACPI_RESOURCE_TYPE_FIXED_MEMORY32 */ + sizeof(struct aml_resource_address16), /* ACPI_RESOURCE_TYPE_ADDRESS16 */ + sizeof(struct aml_resource_address32), /* ACPI_RESOURCE_TYPE_ADDRESS32 */ + sizeof(struct aml_resource_address64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */ + sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */ + sizeof(struct aml_resource_extended_irq), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */ + sizeof(struct aml_resource_generic_register) /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ +}; + +const u8 acpi_gbl_resource_struct_sizes[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_RS_SIZE(struct acpi_resource_irq), + ACPI_RS_SIZE(struct acpi_resource_dma), + ACPI_RS_SIZE(struct acpi_resource_start_dependent), + ACPI_RS_SIZE_MIN, + ACPI_RS_SIZE(struct acpi_resource_io), + ACPI_RS_SIZE(struct acpi_resource_fixed_io), + 0, + 0, + 0, + 0, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RS_SIZE_MIN, + + /* Large descriptors */ + + 0, + ACPI_RS_SIZE(struct acpi_resource_memory24), + ACPI_RS_SIZE(struct acpi_resource_generic_register), + 0, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RS_SIZE(struct acpi_resource_memory32), + ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), + ACPI_RS_SIZE(struct acpi_resource_address32), + ACPI_RS_SIZE(struct acpi_resource_address16), + ACPI_RS_SIZE(struct acpi_resource_extended_irq), + ACPI_RS_SIZE(struct acpi_resource_address64), + ACPI_RS_SIZE(struct acpi_resource_extended_address64) +}; diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index d53bbe89e851..ea567167c4f2 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,428 +49,206 @@ ACPI_MODULE_NAME("rsio") /******************************************************************************* * - * FUNCTION: acpi_rs_io_resource + * acpi_rs_convert_io * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status + ******************************************************************************/ +struct acpi_rsconvert_info acpi_rs_convert_io[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IO, + ACPI_RS_SIZE(struct acpi_resource_io), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IO, + sizeof(struct aml_resource_io), + 0}, + + /* Decode flag */ + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.io.io_decode), + AML_OFFSET(io.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Alignment + * Length + * Minimum Base Address + * Maximum Base Address + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.io.alignment), + AML_OFFSET(io.alignment), + 2}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.io.minimum), + AML_OFFSET(io.minimum), + 2} +}; + +/******************************************************************************* * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_fixed_io * ******************************************************************************/ -acpi_status -acpi_rs_io_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_io); - - ACPI_FUNCTION_TRACE("rs_io_resource"); - - /* The number of bytes consumed are Constant */ - - *bytes_consumed = 8; - - output_struct->id = ACPI_RSTYPE_IO; - - /* Check Decode */ - - buffer += 1; - temp8 = *buffer; - - output_struct->data.io.io_decode = temp8 & 0x01; - - /* Check min_base Address */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - output_struct->data.io.min_base_address = temp16; - - /* Check max_base Address */ - buffer += 2; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - output_struct->data.io.max_base_address = temp16; - - /* Check Base alignment */ - - buffer += 2; - temp8 = *buffer; - - output_struct->data.io.alignment = temp8; - - /* Check range_length */ - - buffer += 1; - temp8 = *buffer; - - output_struct->data.io.range_length = temp8; - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} +struct acpi_rsconvert_info acpi_rs_convert_fixed_io[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_IO, + ACPI_RS_SIZE(struct acpi_resource_fixed_io), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_io)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_IO, + sizeof(struct aml_resource_fixed_io), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Base Address + * Length + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_io.address_length), + AML_OFFSET(fixed_io.address_length), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_io.address), + AML_OFFSET(fixed_io.address), + 1} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_fixed_io_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_generic_reg * ******************************************************************************/ -acpi_status -acpi_rs_fixed_io_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io); - - ACPI_FUNCTION_TRACE("rs_fixed_io_resource"); - - /* The number of bytes consumed are Constant */ - - *bytes_consumed = 4; - - output_struct->id = ACPI_RSTYPE_FIXED_IO; - - /* Check Range Base Address */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - output_struct->data.fixed_io.base_address = temp16; - - /* Check range_length */ - - buffer += 2; - temp8 = *buffer; - - output_struct->data.fixed_io.range_length = temp8; - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} +struct acpi_rsconvert_info acpi_rs_convert_generic_reg[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GENERIC_REGISTER, + ACPI_RS_SIZE(struct acpi_resource_generic_register), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_generic_reg)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GENERIC_REGISTER, + sizeof(struct aml_resource_generic_register), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Address Space ID + * Register Bit Width + * Register Bit Offset + * Access Size + */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.generic_reg.space_id), + AML_OFFSET(generic_reg.address_space_id), + 4}, + + /* Get the Register Address */ + + {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.generic_reg.address), + AML_OFFSET(generic_reg.address), + 1} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_io_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_end_dpf * ******************************************************************************/ -acpi_status -acpi_rs_io_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_io_stream"); - - /* The descriptor field is static */ - - *buffer = 0x47; - buffer += 1; - - /* Io Information Byte */ - - temp8 = (u8) (linked_list->data.io.io_decode & 0x01); - - *buffer = temp8; - buffer += 1; - - /* Set the Range minimum base address */ - - temp16 = (u16) linked_list->data.io.min_base_address; - - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the Range maximum base address */ - - temp16 = (u16) linked_list->data.io.max_base_address; +struct acpi_rsconvert_info acpi_rs_convert_end_dpf[2] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_DEPENDENT, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_dpf)}, - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the base alignment */ - - temp8 = (u8) linked_list->data.io.alignment; - - *buffer = temp8; - buffer += 1; - - /* Set the range length */ - - temp8 = (u8) linked_list->data.io.range_length; - - *buffer = temp8; - buffer += 1; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_DEPENDENT, + sizeof(struct aml_resource_end_dependent), + 0} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_fixed_io_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_end_tag * ******************************************************************************/ -acpi_status -acpi_rs_fixed_io_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_fixed_io_stream"); - - /* The descriptor field is static */ - - *buffer = 0x4B; - - buffer += 1; - - /* Set the Range base address */ - - temp16 = (u16) linked_list->data.fixed_io.base_address; - - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the range length */ - - temp8 = (u8) linked_list->data.fixed_io.range_length; - - *buffer = temp8; - buffer += 1; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} +struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_END_TAG, + ACPI_RS_SIZE_MIN, + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_end_tag)}, + + /* + * Note: The checksum field is set to zero, meaning that the resource + * data is treated as if the checksum operation succeeded. + * (ACPI Spec 1.0b Section 6.4.2.8) + */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_END_TAG, + sizeof(struct aml_resource_end_tag), + 0} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_dma_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_get_start_dpf * ******************************************************************************/ -acpi_status -acpi_rs_dma_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u8 temp8 = 0; - u8 index; - u8 i; - acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma); - - ACPI_FUNCTION_TRACE("rs_dma_resource"); - - /* The number of bytes consumed are Constant */ +struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, + ACPI_RS_SIZE(struct acpi_resource_start_dependent), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, - *bytes_consumed = 3; - output_struct->id = ACPI_RSTYPE_DMA; + /* Defaults for Compatibility and Performance priorities */ - /* Point to the 8-bits of Byte 1 */ + {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + ACPI_ACCEPTABLE_CONFIGURATION, + 2}, - buffer += 1; - temp8 = *buffer; + /* All done if there is no flag byte present in the descriptor */ - /* Decode the DMA channel bits */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, - for (i = 0, index = 0; index < 8; index++) { - if ((temp8 >> index) & 0x01) { - output_struct->data.dma.channels[i] = index; - i++; - } - } + /* Flag byte is present, get the flags */ - /* Zero DMA channels is valid */ + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + AML_OFFSET(start_dpf.flags), + 0}, - output_struct->data.dma.number_of_channels = i; - if (i > 0) { - /* Calculate the structure size based upon the number of interrupts */ - - struct_size += ((acpi_size) i - 1) * 4; - } - - /* Point to Byte 2 */ - - buffer += 1; - temp8 = *buffer; - - /* Check for transfer preference (Bits[1:0]) */ - - output_struct->data.dma.transfer = temp8 & 0x03; - - if (0x03 == output_struct->data.dma.transfer) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid DMA.Transfer preference (3)\n")); - return_ACPI_STATUS(AE_BAD_DATA); - } - - /* Get bus master preference (Bit[2]) */ - - output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01; - - /* Get channel speed support (Bits[6:5]) */ - - output_struct->data.dma.type = (temp8 >> 5) & 0x03; - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + AML_OFFSET(start_dpf.flags), + 2} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_dma_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_set_start_dpf * ******************************************************************************/ -acpi_status -acpi_rs_dma_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - u8 index; - - ACPI_FUNCTION_TRACE("rs_dma_stream"); - - /* The descriptor field is static */ - - *buffer = 0x2A; - buffer += 1; - temp8 = 0; - - /* Loop through all of the Channels and set the mask bits */ - - for (index = 0; - index < linked_list->data.dma.number_of_channels; index++) { - temp16 = (u16) linked_list->data.dma.channels[index]; - temp8 |= 0x1 << temp16; - } - - *buffer = temp8; - buffer += 1; - - /* Set the DMA Info */ - - temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5); - temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2); - temp8 |= (linked_list->data.dma.transfer & 0x03); - - *buffer = temp8; - buffer += 1; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} +struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, + sizeof(struct aml_resource_start_dependent), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, + + /* Set the default flag values */ + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + AML_OFFSET(start_dpf.flags), + 0}, + + {ACPI_RSC_2BITFLAG, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + AML_OFFSET(start_dpf.flags), + 2}, + /* + * All done if flags byte is necessary -- if either priority value + * is not ACPI_ACCEPTABLE_CONFIGURATION + */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.compatibility_priority), + ACPI_ACCEPTABLE_CONFIGURATION}, + + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.start_dpf.performance_robustness), + ACPI_ACCEPTABLE_CONFIGURATION}, + + /* Flag byte is not necessary */ + + {ACPI_RSC_LENGTH, 0, 0, + sizeof(struct aml_resource_start_dependent_noprio)} +}; diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 56043fee96cb..1fa63bc2e36f 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,504 +49,182 @@ ACPI_MODULE_NAME("rsirq") /******************************************************************************* * - * FUNCTION: acpi_rs_irq_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_get_irq * ******************************************************************************/ -acpi_status -acpi_rs_irq_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - u8 index; - u8 i; - acpi_size struct_size = ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq); - - ACPI_FUNCTION_TRACE("rs_irq_resource"); - - /* - * The number of bytes consumed are contained in the descriptor - * (Bits:0-1) - */ - temp8 = *buffer; - *bytes_consumed = (temp8 & 0x03) + 1; - output_struct->id = ACPI_RSTYPE_IRQ; - - /* Point to the 16-bits of Bytes 1 and 2 */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - output_struct->data.irq.number_of_interrupts = 0; - - /* Decode the IRQ bits */ - - for (i = 0, index = 0; index < 16; index++) { - if ((temp16 >> index) & 0x01) { - output_struct->data.irq.interrupts[i] = index; - i++; - } - } +struct acpi_rsconvert_info acpi_rs_get_irq[7] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, + ACPI_RS_SIZE(struct acpi_resource_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, - /* Zero interrupts is valid */ + /* Get the IRQ mask (bytes 1:2) */ - output_struct->data.irq.number_of_interrupts = i; - if (i > 0) { - /* Calculate the structure size based upon the number of interrupts */ + {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), + AML_OFFSET(irq.irq_mask), + ACPI_RS_OFFSET(data.irq.interrupt_count)}, - struct_size += ((acpi_size) i - 1) * 4; - } + /* Set default flags (others are zero) */ - /* Point to Byte 3 if it is used */ + {ACPI_RSC_SET8, ACPI_RS_OFFSET(data.irq.triggering), + ACPI_EDGE_SENSITIVE, + 1}, - if (4 == *bytes_consumed) { - buffer += 2; - temp8 = *buffer; + /* All done if no flag byte present in descriptor */ - /* Check for HE, LL interrupts */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, - switch (temp8 & 0x09) { - case 0x01: /* HE */ - output_struct->data.irq.edge_level = - ACPI_EDGE_SENSITIVE; - output_struct->data.irq.active_high_low = - ACPI_ACTIVE_HIGH; - break; + /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ - case 0x08: /* LL */ - output_struct->data.irq.edge_level = - ACPI_LEVEL_SENSITIVE; - output_struct->data.irq.active_high_low = - ACPI_ACTIVE_LOW; - break; + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), + AML_OFFSET(irq.flags), + 0}, - default: - /* - * Only _LL and _HE polarity/trigger interrupts - * are allowed (ACPI spec, section "IRQ Format") - * so 0x00 and 0x09 are illegal. - */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid interrupt polarity/trigger in resource list, %X\n", - temp8)); - return_ACPI_STATUS(AE_BAD_DATA); - } + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), + AML_OFFSET(irq.flags), + 3}, - /* Check for sharable */ - - output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01; - } else { - /* - * Assume Edge Sensitive, Active High, Non-Sharable - * per ACPI Specification - */ - output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE; - output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH; - output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE; - } - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), + AML_OFFSET(irq.flags), + 4} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_irq_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_set_irq * ******************************************************************************/ -acpi_status -acpi_rs_irq_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - u8 index; - u8 IRqinfo_byte_needed; - - ACPI_FUNCTION_TRACE("rs_irq_stream"); - - /* - * The descriptor field is set based upon whether a third byte is - * needed to contain the IRQ Information. - */ - if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level && - ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low && - ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) { - *buffer = 0x22; - IRqinfo_byte_needed = FALSE; - } else { - *buffer = 0x23; - IRqinfo_byte_needed = TRUE; - } - - buffer += 1; - temp16 = 0; - - /* Loop through all of the interrupts and set the mask bits */ - - for (index = 0; - index < linked_list->data.irq.number_of_interrupts; index++) { - temp8 = (u8) linked_list->data.irq.interrupts[index]; - temp16 |= 0x1 << temp8; - } - - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the IRQ Info byte if needed. */ - - if (IRqinfo_byte_needed) { - temp8 = 0; - temp8 = (u8) ((linked_list->data.irq.shared_exclusive & - 0x01) << 4); - - if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level && - ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) { - temp8 |= 0x08; - } else { - temp8 |= 0x01; - } - - *buffer = temp8; - buffer += 1; - } - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_extended_irq_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. - * - ******************************************************************************/ - -acpi_status -acpi_rs_extended_irq_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - u8 *temp_ptr; - u8 index; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq); - - ACPI_FUNCTION_TRACE("rs_extended_irq_resource"); - - /* Get the Descriptor Length field */ - - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); - - /* Validate minimum descriptor length */ - - if (temp16 < 6) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); - } - - *bytes_consumed = temp16 + 3; - output_struct->id = ACPI_RSTYPE_EXT_IRQ; - - /* Point to the Byte3 */ - - buffer += 2; - temp8 = *buffer; - - output_struct->data.extended_irq.producer_consumer = temp8 & 0x01; +struct acpi_rsconvert_info acpi_rs_set_irq[9] = { + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, + sizeof(struct aml_resource_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, - /* - * Check for Interrupt Mode - * - * The definition of an Extended IRQ changed between ACPI spec v1.0b - * and ACPI spec 2.0 (section 6.4.3.6 in both). - * - * - Edge/Level are defined opposite in the table vs the headers - */ - output_struct->data.extended_irq.edge_level = - (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; - - /* Check Interrupt Polarity */ - - output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1; - - /* Check for sharable */ - - output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01; + /* Convert interrupt list to 16-bit IRQ bitmask */ - /* Point to Byte4 (IRQ Table length) */ + {ACPI_RSC_BITMASK16, ACPI_RS_OFFSET(data.irq.interrupts[0]), + AML_OFFSET(irq.irq_mask), + ACPI_RS_OFFSET(data.irq.interrupt_count)}, - buffer += 1; - temp8 = *buffer; + /* Set the flags byte by default */ - /* Must have at least one IRQ */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), + AML_OFFSET(irq.flags), + 0}, - if (temp8 < 1) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); - } - - output_struct->data.extended_irq.number_of_interrupts = temp8; + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.polarity), + AML_OFFSET(irq.flags), + 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), + AML_OFFSET(irq.flags), + 4}, /* - * Add any additional structure size to properly calculate - * the next pointer at the end of this function + * Check if the flags byte is necessary. Not needed if the flags are: + * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE */ - struct_size += (temp8 - 1) * 4; - - /* Point to Byte5 (First IRQ Number) */ - - buffer += 1; - - /* Cycle through every IRQ in the table */ - - for (index = 0; index < temp8; index++) { - ACPI_MOVE_32_TO_32(&output_struct->data.extended_irq. - interrupts[index], buffer); - - /* Point to the next IRQ */ - - buffer += 4; - } - - /* - * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. - * - * Note: Some resource descriptors will have an additional null, so - * we add 1 to the length. - */ - if (*bytes_consumed > - ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * - 4) + (5 + 1)) { - /* Dereference the Index */ - - temp8 = *buffer; - output_struct->data.extended_irq.resource_source.index = - (u32) temp8; - - /* Point to the String */ - - buffer += 1; - - /* Point the String pointer to the end of this structure. */ - - output_struct->data.extended_irq.resource_source.string_ptr = - (char *)((char *)output_struct + struct_size); + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.triggering), + ACPI_EDGE_SENSITIVE}, - temp_ptr = (u8 *) - output_struct->data.extended_irq.resource_source.string_ptr; + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.polarity), + ACPI_ACTIVE_HIGH}, - /* Copy the string into the buffer */ + {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_VALUE, + ACPI_RS_OFFSET(data.irq.sharable), + ACPI_EXCLUSIVE}, - index = 0; - while (*buffer) { - *temp_ptr = *buffer; + /* irq_no_flags() descriptor can be used */ - temp_ptr += 1; - buffer += 1; - index += 1; - } - - /* Add the terminating null */ - - *temp_ptr = 0; - output_struct->data.extended_irq.resource_source.string_length = - index + 1; - - /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the string and expand the - * struct_size to the next 32-bit boundary. - */ - temp8 = (u8) (index + 1); - struct_size += ACPI_ROUND_UP_to_32_bITS(temp8); - } else { - output_struct->data.extended_irq.resource_source.index = 0; - output_struct->data.extended_irq.resource_source.string_length = - 0; - output_struct->data.extended_irq.resource_source.string_ptr = - NULL; - } - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_extended_irq_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_ext_irq * ******************************************************************************/ -acpi_status -acpi_rs_extended_irq_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 *length_field; - u8 temp8 = 0; - u8 index; +struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, + ACPI_RS_SIZE(struct acpi_resource_extended_irq), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, - ACPI_FUNCTION_TRACE("rs_extended_irq_stream"); + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_IRQ, + sizeof(struct aml_resource_extended_irq), + 0}, - /* Set the Descriptor Type field */ + /* Flag bits */ - *buffer = ACPI_RDESC_TYPE_EXTENDED_XRUPT; - buffer += 1; + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), + AML_OFFSET(extended_irq.flags), + 0}, - /* Save a pointer to the Length field - to be filled in later */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.triggering), + AML_OFFSET(extended_irq.flags), + 1}, - length_field = ACPI_CAST_PTR(u16, buffer); - buffer += 2; + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.polarity), + AML_OFFSET(extended_irq.flags), + 2}, - /* Set the Interrupt vector flags */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.sharable), + AML_OFFSET(extended_irq.flags), + 3}, - temp8 = (u8) (linked_list->data.extended_irq.producer_consumer & 0x01); - temp8 |= - ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); + /* IRQ Table length (Byte4) */ - /* - * Set the Interrupt Mode - * - * The definition of an Extended IRQ changed between ACPI spec v1.0b - * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not - * implement the more restrictive definition of 1.0b - * - * - Edge/Level are defined opposite in the table vs the headers - */ - if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) { - temp8 |= 0x2; - } - - /* Set the Interrupt Polarity */ + {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), + AML_OFFSET(extended_irq.interrupt_count), + sizeof(u32)} + , - temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2); + /* Copy every IRQ in the table, each is 32 bits */ - *buffer = temp8; - buffer += 1; + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), + AML_OFFSET(extended_irq.interrupts[0]), + 0} + , - /* Set the Interrupt table length */ + /* Optional resource_source (Index and String) */ - temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; + {ACPI_RSC_SOURCEX, ACPI_RS_OFFSET(data.extended_irq.resource_source), + ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), + sizeof(struct aml_resource_extended_irq)} +}; - *buffer = temp8; - buffer += 1; - - for (index = 0; - index < linked_list->data.extended_irq.number_of_interrupts; - index++) { - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.extended_irq. - interrupts[index]); - buffer += 4; - } +/******************************************************************************* + * + * acpi_rs_convert_dma + * + ******************************************************************************/ - /* Resource Source Index and Resource Source are optional */ +struct acpi_rsconvert_info acpi_rs_convert_dma[6] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_DMA, + ACPI_RS_SIZE(struct acpi_resource_dma), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_dma)}, - if (0 != linked_list->data.extended_irq.resource_source.string_length) { - *buffer = - (u8) linked_list->data.extended_irq.resource_source.index; - buffer += 1; + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_DMA, + sizeof(struct aml_resource_dma), + 0}, - /* Copy the string */ + /* Flags: transfer preference, bus mastering, channel speed */ - ACPI_STRCPY((char *)buffer, - linked_list->data.extended_irq.resource_source. - string_ptr); + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.transfer), + AML_OFFSET(dma.flags), + 0}, - /* - * Buffer needs to be set to the length of the string + one for the - * terminating null - */ - buffer += - (acpi_size) (ACPI_STRLEN - (linked_list->data.extended_irq. - resource_source.string_ptr) + 1); - } + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.dma.bus_master), + AML_OFFSET(dma.flags), + 2}, - /* Return the number of bytes consumed in this operation */ + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.dma.type), + AML_OFFSET(dma.flags), + 5}, - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); + /* DMA channel mask bits */ - /* - * Set the length field to the number of bytes consumed - * minus the header size (3 bytes) - */ - *length_field = (u16) (*bytes_consumed - 3); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_BITMASK, ACPI_RS_OFFSET(data.dma.channels[0]), + AML_OFFSET(dma.dma_channel_mask), + ACPI_RS_OFFSET(data.dma.channel_count)} +}; diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 103eb31c284e..1434e786477e 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,52 +49,12 @@ ACPI_MODULE_NAME("rslist") /******************************************************************************* * - * FUNCTION: acpi_rs_get_resource_type + * FUNCTION: acpi_rs_convert_aml_to_resources * - * PARAMETERS: resource_start_byte - Byte 0 of a resource descriptor - * - * RETURN: The Resource Type with no extraneous bits - * - * DESCRIPTION: Extract the Resource Type/Name from the first byte of - * a resource descriptor. - * - ******************************************************************************/ -u8 acpi_rs_get_resource_type(u8 resource_start_byte) -{ - - ACPI_FUNCTION_ENTRY(); - - /* Determine if this is a small or large resource */ - - switch (resource_start_byte & ACPI_RDESC_TYPE_MASK) { - case ACPI_RDESC_TYPE_SMALL: - - /* Small Resource Type -- Only bits 6:3 are valid */ - - return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK)); - - case ACPI_RDESC_TYPE_LARGE: - - /* Large Resource Type -- All bits are valid */ - - return (resource_start_byte); - - default: - /* Invalid type */ - break; - } - - return (0xFF); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_byte_stream_to_list - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream - * byte_stream_buffer_length - Length of byte_stream_buffer - * output_buffer - Pointer to the buffer that will - * contain the output structures + * PARAMETERS: Aml - Pointer to the resource byte stream + * aml_length - Length of Aml + * output_buffer - Pointer to the buffer that will + * contain the output structures * * RETURN: Status * @@ -102,241 +62,78 @@ u8 acpi_rs_get_resource_type(u8 resource_start_byte) * linked list of resources in the caller's output buffer * ******************************************************************************/ - acpi_status -acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer, - u32 byte_stream_buffer_length, u8 * output_buffer) +acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) { + struct acpi_resource *resource = (void *)output_buffer; acpi_status status; - acpi_size bytes_parsed = 0; - u8 resource_type = 0; - acpi_size bytes_consumed = 0; - u8 *buffer = output_buffer; - acpi_size structure_size = 0; - u8 end_tag_processed = FALSE; - struct acpi_resource *resource; - - ACPI_FUNCTION_TRACE("rs_byte_stream_to_list"); - - while (bytes_parsed < byte_stream_buffer_length && !end_tag_processed) { - /* The next byte in the stream is the resource type */ - - resource_type = acpi_rs_get_resource_type(*byte_stream_buffer); - - switch (resource_type) { - case ACPI_RDESC_TYPE_MEMORY_24: - /* - * 24-Bit Memory Resource - */ - status = acpi_rs_memory24_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_LARGE_VENDOR: - /* - * Vendor Defined Resource - */ - status = acpi_rs_vendor_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_MEMORY_32: - /* - * 32-Bit Memory Range Resource - */ - status = - acpi_rs_memory32_range_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_FIXED_MEMORY_32: - /* - * 32-Bit Fixed Memory Resource - */ - status = - acpi_rs_fixed_memory32_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: - case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: - /* - * 64-Bit Address Resource - */ - status = acpi_rs_address64_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: - /* - * 32-Bit Address Resource - */ - status = acpi_rs_address32_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: - /* - * 16-Bit Address Resource - */ - status = acpi_rs_address16_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_EXTENDED_XRUPT: - /* - * Extended IRQ - */ - status = - acpi_rs_extended_irq_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_IRQ_FORMAT: - /* - * IRQ Resource - */ - status = acpi_rs_irq_resource(byte_stream_buffer, - &bytes_consumed, &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_DMA_FORMAT: - /* - * DMA Resource - */ - status = acpi_rs_dma_resource(byte_stream_buffer, - &bytes_consumed, &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_START_DEPENDENT: - /* - * Start Dependent Functions Resource - */ - status = - acpi_rs_start_depend_fns_resource - (byte_stream_buffer, &bytes_consumed, &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_END_DEPENDENT: - /* - * End Dependent Functions Resource - */ - status = - acpi_rs_end_depend_fns_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_IO_PORT: - /* - * IO Port Resource - */ - status = acpi_rs_io_resource(byte_stream_buffer, - &bytes_consumed, &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_FIXED_IO_PORT: - /* - * Fixed IO Port Resource - */ - status = acpi_rs_fixed_io_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_SMALL_VENDOR: - /* - * Vendor Specific Resource - */ - status = acpi_rs_vendor_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - case ACPI_RDESC_TYPE_END_TAG: - /* - * End Tag - */ - end_tag_processed = TRUE; - status = acpi_rs_end_tag_resource(byte_stream_buffer, - &bytes_consumed, - &buffer, - &structure_size); - break; - - default: - /* - * Invalid/Unknown resource type - */ - status = AE_AML_INVALID_RESOURCE_TYPE; - break; - } + u8 resource_index; + u8 *end_aml; + + ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); + end_aml = aml + aml_length; + + /* Loop until end-of-buffer or an end_tag is found */ + + while (aml < end_aml) { + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml, &resource_index); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Update the return value and counter */ + /* Convert the AML byte stream resource to a local resource struct */ - bytes_parsed += bytes_consumed; + status = + acpi_rs_convert_aml_to_resource(resource, + ACPI_CAST_PTR(union + aml_resource, + aml), + acpi_gbl_get_resource_dispatch + [resource_index]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert AML resource (Type %X)", + *aml)); + return_ACPI_STATUS(status); + } - /* Set the byte stream to point to the next resource */ + /* Normal exit on completion of an end_tag resource descriptor */ - byte_stream_buffer += bytes_consumed; + if (acpi_ut_get_resource_type(aml) == + ACPI_RESOURCE_NAME_END_TAG) { + return_ACPI_STATUS(AE_OK); + } - /* Set the Buffer to the next structure */ + /* Point to the next input AML resource */ - resource = ACPI_CAST_PTR(struct acpi_resource, buffer); - resource->length = - (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length); - buffer += ACPI_ALIGN_RESOURCE_SIZE(structure_size); - } + aml += acpi_ut_get_descriptor_length(aml); - /* Check the reason for exiting the while loop */ + /* Point to the next structure in the output buffer */ - if (!end_tag_processed) { - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); } - return_ACPI_STATUS(AE_OK); + /* Did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); } /******************************************************************************* * - * FUNCTION: acpi_rs_list_to_byte_stream + * FUNCTION: acpi_rs_convert_resources_to_aml * - * PARAMETERS: linked_list - Pointer to the resource linked list - * byte_steam_size_needed - Calculated size of the byte stream - * needed from calling - * acpi_rs_get_byte_stream_length() - * The size of the output_buffer is - * guaranteed to be >= - * byte_stream_size_needed - * output_buffer - Pointer to the buffer that will - * contain the byte stream + * PARAMETERS: Resource - Pointer to the resource linked list + * aml_size_needed - Calculated size of the byte stream + * needed from calling acpi_rs_get_aml_length() + * The size of the output_buffer is + * guaranteed to be >= aml_size_needed + * output_buffer - Pointer to the buffer that will + * contain the byte stream * * RETURN: Status * @@ -346,180 +143,73 @@ acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer, ******************************************************************************/ acpi_status -acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list, - acpi_size byte_stream_size_needed, - u8 * output_buffer) +acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, + acpi_size aml_size_needed, u8 * output_buffer) { + u8 *aml = output_buffer; + u8 *end_aml = output_buffer + aml_size_needed; acpi_status status; - u8 *buffer = output_buffer; - acpi_size bytes_consumed = 0; - u8 done = FALSE; - - ACPI_FUNCTION_TRACE("rs_list_to_byte_stream"); - - while (!done) { - switch (linked_list->id) { - case ACPI_RSTYPE_IRQ: - /* - * IRQ Resource - */ - status = - acpi_rs_irq_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_DMA: - /* - * DMA Resource - */ - status = - acpi_rs_dma_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_START_DPF: - /* - * Start Dependent Functions Resource - */ - status = acpi_rs_start_depend_fns_stream(linked_list, - &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_END_DPF: - /* - * End Dependent Functions Resource - */ - status = acpi_rs_end_depend_fns_stream(linked_list, - &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_IO: - /* - * IO Port Resource - */ - status = - acpi_rs_io_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_FIXED_IO: - /* - * Fixed IO Port Resource - */ - status = - acpi_rs_fixed_io_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_VENDOR: - /* - * Vendor Defined Resource - */ - status = - acpi_rs_vendor_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_END_TAG: - /* - * End Tag - */ - status = - acpi_rs_end_tag_stream(linked_list, &buffer, - &bytes_consumed); - - /* An End Tag indicates the end of the Resource Template */ - - done = TRUE; - break; - - case ACPI_RSTYPE_MEM24: - /* - * 24-Bit Memory Resource - */ - status = - acpi_rs_memory24_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_MEM32: - /* - * 32-Bit Memory Range Resource - */ - status = - acpi_rs_memory32_range_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_FIXED_MEM32: - /* - * 32-Bit Fixed Memory Resource - */ - status = - acpi_rs_fixed_memory32_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_ADDRESS16: - /* - * 16-Bit Address Descriptor Resource - */ - status = acpi_rs_address16_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_ADDRESS32: - /* - * 32-Bit Address Descriptor Resource - */ - status = acpi_rs_address32_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_ADDRESS64: - /* - * 64-Bit Address Descriptor Resource - */ - status = acpi_rs_address64_stream(linked_list, &buffer, - &bytes_consumed); - break; - - case ACPI_RSTYPE_EXT_IRQ: - /* - * Extended IRQ Resource - */ - status = - acpi_rs_extended_irq_stream(linked_list, &buffer, - &bytes_consumed); - break; - - default: - /* - * If we get here, everything is out of sync, - * so exit with an error - */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid descriptor type (%X) in resource list\n", - linked_list->id)); - status = AE_BAD_DATA; - break; + + ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml"); + + /* Walk the resource descriptor list, convert each descriptor */ + + while (aml < end_aml) { + /* Validate the (internal) Resource Type */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + ACPI_ERROR((AE_INFO, + "Invalid descriptor type (%X) in resource list", + resource->type)); + return_ACPI_STATUS(AE_BAD_DATA); } + /* Perform the conversion */ + + status = acpi_rs_convert_resource_to_aml(resource, + ACPI_CAST_PTR(union + aml_resource, + aml), + acpi_gbl_set_resource_dispatch + [resource->type]); if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert resource (type %X) to AML", + resource->type)); return_ACPI_STATUS(status); } - /* Set the Buffer to point to the open byte */ + /* Perform final sanity check on the new AML resource descriptor */ + + status = + acpi_ut_validate_resource(ACPI_CAST_PTR + (union aml_resource, aml), NULL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - buffer += bytes_consumed; + /* Check for end-of-list, normal exit */ - /* Point to the next object */ + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + /* An End Tag indicates the end of the input Resource Template */ - linked_list = ACPI_PTR_ADD(struct acpi_resource, - linked_list, linked_list->length); + return_ACPI_STATUS(AE_OK); + } + + /* + * Extract the total length of the new descriptor and set the + * Aml to point to the next (output) resource descriptor + */ + aml += acpi_ut_get_descriptor_length(aml); + + /* Point to the next input resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); } - return_ACPI_STATUS(AE_OK); + /* Completed buffer, but did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); } diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c index daba1a1ed46d..a5131936d690 100644 --- a/drivers/acpi/resources/rsmemory.c +++ b/drivers/acpi/resources/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,454 +49,187 @@ ACPI_MODULE_NAME("rsmemory") /******************************************************************************* * - * FUNCTION: acpi_rs_memory24_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_memory24 * ******************************************************************************/ -acpi_status -acpi_rs_memory24_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24); - - ACPI_FUNCTION_TRACE("rs_memory24_resource"); - - /* Point past the Descriptor to get the number of bytes consumed */ - - buffer += 1; - - ACPI_MOVE_16_TO_16(&temp16, buffer); - buffer += 2; - *bytes_consumed = (acpi_size) temp16 + 3; - output_struct->id = ACPI_RSTYPE_MEM24; - - /* Check Byte 3 the Read/Write bit */ - - temp8 = *buffer; - buffer += 1; - output_struct->data.memory24.read_write_attribute = temp8 & 0x01; - - /* Get min_base_address (Bytes 4-5) */ - - ACPI_MOVE_16_TO_16(&temp16, buffer); - buffer += 2; - output_struct->data.memory24.min_base_address = temp16; - - /* Get max_base_address (Bytes 6-7) */ - - ACPI_MOVE_16_TO_16(&temp16, buffer); - buffer += 2; - output_struct->data.memory24.max_base_address = temp16; +struct acpi_rsconvert_info acpi_rs_convert_memory24[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY24, + ACPI_RS_SIZE(struct acpi_resource_memory24), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory24)}, - /* Get Alignment (Bytes 8-9) */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY24, + sizeof(struct aml_resource_memory24), + 0}, - ACPI_MOVE_16_TO_16(&temp16, buffer); - buffer += 2; - output_struct->data.memory24.alignment = temp16; + /* Read/Write bit */ - /* Get range_length (Bytes 10-11) */ - - ACPI_MOVE_16_TO_16(&temp16, buffer); - output_struct->data.memory24.range_length = temp16; - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory24.write_protect), + AML_OFFSET(memory24.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.memory24.minimum), + AML_OFFSET(memory24.minimum), + 4} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_memory24_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_convert_memory32 * ******************************************************************************/ -acpi_status -acpi_rs_memory24_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_memory24_stream"); - - /* The descriptor field is static */ - - *buffer = 0x81; - buffer += 1; +struct acpi_rsconvert_info acpi_rs_convert_memory32[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_MEMORY32, + ACPI_RS_SIZE(struct acpi_resource_memory32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_memory32)}, - /* The length field is static */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_MEMORY32, + sizeof(struct aml_resource_memory32), + 0}, - temp16 = 0x09; - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; + /* Read/Write bit */ - /* Set the Information Byte */ - - temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01); - *buffer = temp8; - buffer += 1; - - /* Set the Range minimum base address */ - - ACPI_MOVE_32_TO_16(buffer, - &linked_list->data.memory24.min_base_address); - buffer += 2; - - /* Set the Range maximum base address */ - - ACPI_MOVE_32_TO_16(buffer, - &linked_list->data.memory24.max_base_address); - buffer += 2; - - /* Set the base alignment */ - - ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.alignment); - buffer += 2; - - /* Set the range length */ - - ACPI_MOVE_32_TO_16(buffer, &linked_list->data.memory24.range_length); - buffer += 2; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.memory32.write_protect), + AML_OFFSET(memory32.flags), + 0}, + /* + * These fields are contiguous in both the source and destination: + * Minimum Base Address + * Maximum Base Address + * Address Base Alignment + * Range Length + */ + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.memory32.minimum), + AML_OFFSET(memory32.minimum), + 4} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_memory32_range_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_convert_fixed_memory32 * ******************************************************************************/ -acpi_status -acpi_rs_memory32_range_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32); - - ACPI_FUNCTION_TRACE("rs_memory32_range_resource"); - - /* Point past the Descriptor to get the number of bytes consumed */ - - buffer += 1; +struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[4] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_MEMORY32, + ACPI_RS_SIZE(struct acpi_resource_fixed_memory32), + ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_memory32)}, - ACPI_MOVE_16_TO_16(&temp16, buffer); - buffer += 2; - *bytes_consumed = (acpi_size) temp16 + 3; + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_MEMORY32, + sizeof(struct aml_resource_fixed_memory32), + 0}, - output_struct->id = ACPI_RSTYPE_MEM32; + /* Read/Write bit */ + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.fixed_memory32.write_protect), + AML_OFFSET(fixed_memory32.flags), + 0}, /* - * Point to the place in the output buffer where the data portion will - * begin. - * 1. Set the RESOURCE_DATA * Data to point to its own address, then - * 2. Set the pointer to the next address. - * - * NOTE: output_struct->Data is cast to u8, otherwise, this addition adds - * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8) + * These fields are contiguous in both the source and destination: + * Base Address + * Range Length */ - - /* Check Byte 3 the Read/Write bit */ - - temp8 = *buffer; - buffer += 1; - - output_struct->data.memory32.read_write_attribute = temp8 & 0x01; - - /* Get min_base_address (Bytes 4-7) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.memory32.min_base_address, - buffer); - buffer += 4; - - /* Get max_base_address (Bytes 8-11) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.memory32.max_base_address, - buffer); - buffer += 4; - - /* Get Alignment (Bytes 12-15) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.memory32.alignment, buffer); - buffer += 4; - - /* Get range_length (Bytes 16-19) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.memory32.range_length, buffer); - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.fixed_memory32.address), + AML_OFFSET(fixed_memory32.address), + 2} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_fixed_memory32_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * acpi_rs_get_vendor_small * ******************************************************************************/ -acpi_status -acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32); - - ACPI_FUNCTION_TRACE("rs_fixed_memory32_resource"); +struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_small)}, - /* Point past the Descriptor to get the number of bytes consumed */ + /* Length of the vendor data (byte count) */ - buffer += 1; - ACPI_MOVE_16_TO_16(&temp16, buffer); + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + sizeof(u8)} + , - buffer += 2; - *bytes_consumed = (acpi_size) temp16 + 3; + /* Vendor data */ - output_struct->id = ACPI_RSTYPE_FIXED_MEM32; - - /* Check Byte 3 the Read/Write bit */ - - temp8 = *buffer; - buffer += 1; - output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01; - - /* Get range_base_address (Bytes 4-7) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32. - range_base_address, buffer); - buffer += 4; - - /* Get range_length (Bytes 8-11) */ - - ACPI_MOVE_32_TO_32(&output_struct->data.fixed_memory32.range_length, - buffer); - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_small_header), + 0} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_memory32_range_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_get_vendor_large * ******************************************************************************/ -acpi_status -acpi_rs_memory32_range_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_memory32_range_stream"); - - /* The descriptor field is static */ - - *buffer = 0x85; - buffer += 1; - - /* The length field is static */ - - temp16 = 0x11; - - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the Information Byte */ - - temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01); - *buffer = temp8; - buffer += 1; - - /* Set the Range minimum base address */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.memory32.min_base_address); - buffer += 4; - - /* Set the Range maximum base address */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.memory32.max_base_address); - buffer += 4; +struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_VENDOR, + ACPI_RS_SIZE(struct acpi_resource_vendor), + ACPI_RSC_TABLE_SIZE(acpi_rs_get_vendor_large)}, - /* Set the base alignment */ + /* Length of the vendor data (byte count) */ - ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.alignment); - buffer += 4; + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + sizeof(u8)} + , - /* Set the range length */ + /* Vendor data */ - ACPI_MOVE_32_TO_32(buffer, &linked_list->data.memory32.range_length); - buffer += 4; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_large_header), + 0} +}; /******************************************************************************* * - * FUNCTION: acpi_rs_fixed_memory32_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * acpi_rs_set_vendor * ******************************************************************************/ -acpi_status -acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_fixed_memory32_stream"); +struct acpi_rsconvert_info acpi_rs_set_vendor[7] = { + /* Default is a small vendor descriptor */ - /* The descriptor field is static */ + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_SMALL, + sizeof(struct aml_resource_small_header), + ACPI_RSC_TABLE_SIZE(acpi_rs_set_vendor)}, - *buffer = 0x86; - buffer += 1; + /* Get the length and copy the data */ - /* The length field is static */ + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + 0}, - temp16 = 0x09; + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_small_header), + 0}, - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - - /* Set the Information Byte */ - - temp8 = - (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01); - *buffer = temp8; - buffer += 1; - - /* Set the Range base address */ - - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.fixed_memory32. - range_base_address); - buffer += 4; + /* + * All done if the Vendor byte length is 7 or less, meaning that it will + * fit within a small descriptor + */ + {ACPI_RSC_EXIT_LE, 0, 0, 7}, - /* Set the range length */ + /* Must create a large vendor descriptor */ - ACPI_MOVE_32_TO_32(buffer, - &linked_list->data.fixed_memory32.range_length); - buffer += 4; + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_VENDOR_LARGE, + sizeof(struct aml_resource_large_header), + 0}, - /* Return the number of bytes consumed in this operation */ + {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), + 0, + 0}, - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.vendor.byte_data[0]), + sizeof(struct aml_resource_large_header), + 0} +}; diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index 7a8a34e757f5..ed866cf1c6d2 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,481 +47,501 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsmisc") +#define INIT_RESOURCE_TYPE(i) i->resource_offset +#define INIT_RESOURCE_LENGTH(i) i->aml_offset +#define INIT_TABLE_LENGTH(i) i->value +#define COMPARE_OPCODE(i) i->resource_offset +#define COMPARE_TARGET(i) i->aml_offset +#define COMPARE_VALUE(i) i->value /******************************************************************************* * - * FUNCTION: acpi_rs_end_tag_resource + * FUNCTION: acpi_rs_convert_aml_to_resource * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table * * RETURN: Status * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * DESCRIPTION: Convert an external AML resource descriptor to the corresponding + * internal resource descriptor * ******************************************************************************/ acpi_status -acpi_rs_end_tag_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) +acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info) { - struct acpi_resource *output_struct = (void *)*output_buffer; - acpi_size struct_size = ACPI_RESOURCE_LENGTH; - - ACPI_FUNCTION_TRACE("rs_end_tag_resource"); - - /* The number of bytes consumed is static */ - - *bytes_consumed = 2; - - /* Fill out the structure */ - - output_struct->id = ACPI_RSTYPE_END_TAG; - - /* Set the Length parameter */ - - output_struct->length = 0; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_end_tag_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream - * - ******************************************************************************/ - -acpi_status -acpi_rs_end_tag_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_end_tag_stream"); - - /* The descriptor field is static */ - - *buffer = 0x79; - buffer += 1; - - /* - * Set the Checksum - zero means that the resource data is treated as if - * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) - */ - temp8 = 0; - - *buffer = temp8; - buffer += 1; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_vendor_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. - * - ******************************************************************************/ - -acpi_status -acpi_rs_vendor_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; + acpi_rs_length aml_resource_length; + void *source; + void *destination; + char *target; + u8 count; + u8 flags_mode = FALSE; + u16 item_count = 0; u16 temp16 = 0; - u8 temp8 = 0; - u8 index; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor); - - ACPI_FUNCTION_TRACE("rs_vendor_resource"); - - /* Dereference the Descriptor to find if this is a large or small item. */ - - temp8 = *buffer; - - if (temp8 & 0x80) { - /* Large Item, point to the length field */ - - buffer += 1; - /* Dereference */ + ACPI_FUNCTION_TRACE("rs_get_resource"); - ACPI_MOVE_16_TO_16(&temp16, buffer); + if (((acpi_native_uint) resource) & 0x3) { + /* Each internal resource struct is expected to be 32-bit aligned */ - /* Calculate bytes consumed */ - - *bytes_consumed = (acpi_size) temp16 + 3; - - /* Point to the first vendor byte */ - - buffer += 2; - } else { - /* Small Item, dereference the size */ - - temp16 = (u8) (*buffer & 0x07); - - /* Calculate bytes consumed */ - - *bytes_consumed = (acpi_size) temp16 + 1; - - /* Point to the first vendor byte */ - - buffer += 1; + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer (get): %p Type %2.2X Len %X", + resource, resource->type, resource->length)); } - output_struct->id = ACPI_RSTYPE_VENDOR; - output_struct->data.vendor_specific.length = temp16; + /* Extract the resource Length field (does not include header length) */ - for (index = 0; index < temp16; index++) { - output_struct->data.vendor_specific.reserved[index] = *buffer; - buffer += 1; - } + aml_resource_length = acpi_ut_get_resource_length(aml); /* - * In order for the struct_size to fall on a 32-bit boundary, - * calculate the length of the vendor string and expand the - * struct_size to the next 32-bit boundary. + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) */ - struct_size += ACPI_ROUND_UP_to_32_bITS(temp16); - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_rs_vendor_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream - * - ******************************************************************************/ - -acpi_status -acpi_rs_vendor_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u16 temp16 = 0; - u8 temp8 = 0; - u8 index; - - ACPI_FUNCTION_TRACE("rs_vendor_stream"); - - /* Dereference the length to find if this is a large or small item. */ - - if (linked_list->data.vendor_specific.length > 7) { - /* Large Item, Set the descriptor field and length bytes */ - - *buffer = 0x84; - buffer += 1; - - temp16 = (u16) linked_list->data.vendor_specific.length; - - ACPI_MOVE_16_TO_16(buffer, &temp16); - buffer += 2; - } else { - /* Small Item, Set the descriptor field */ - - temp8 = 0x70; - temp8 |= (u8) linked_list->data.vendor_specific.length; + count = INIT_TABLE_LENGTH(info); + + while (count) { + /* + * Source is the external AML byte stream buffer, + * destination is the internal resource descriptor + */ + source = ACPI_ADD_PTR(void, aml, info->aml_offset); + destination = + ACPI_ADD_PTR(void, resource, info->resource_offset); + + switch (info->opcode) { + case ACPI_RSC_INITGET: + /* + * Get the resource type and the initial (minimum) length + */ + ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); + resource->type = INIT_RESOURCE_TYPE(info); + resource->length = INIT_RESOURCE_LENGTH(info); + break; + + case ACPI_RSC_INITSET: + break; + + case ACPI_RSC_FLAGINIT: + + flags_mode = TRUE; + break; + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x01); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x03); + break; + + case ACPI_RSC_COUNT: + + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; + + resource->length = resource->length + + (info->value * (item_count - 1)); + break; + + case ACPI_RSC_COUNT16: + + item_count = aml_resource_length; + ACPI_SET16(destination) = item_count; + + resource->length = resource->length + + (info->value * (item_count - 1)); + break; + + case ACPI_RSC_LENGTH: + + resource->length = resource->length + info->value; + break; + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + /* + * Raw data move. Use the Info value field unless item_count has + * been previously initialized via a COUNT opcode + */ + if (info->value) { + item_count = info->value; + } + acpi_rs_move_data(destination, source, item_count, + info->opcode); + break; + + case ACPI_RSC_SET8: + + ACPI_MEMSET(destination, info->aml_offset, info->value); + break; + + case ACPI_RSC_DATA8: + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_MEMCPY(destination, source, ACPI_GET16(target)); + break; + + case ACPI_RSC_ADDRESS: + /* + * Common handler for address descriptor flags + */ + if (!acpi_rs_get_address_common(resource, aml)) { + return_ACPI_STATUS + (AE_AML_INVALID_RESOURCE_TYPE); + } + break; + + case ACPI_RSC_SOURCE: + /* + * Optional resource_source (Index and String) + */ + resource->length += + acpi_rs_get_resource_source(aml_resource_length, + info->value, + destination, aml, NULL); + break; + + case ACPI_RSC_SOURCEX: + /* + * Optional resource_source (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + target = + ACPI_ADD_PTR(char, resource, + info->aml_offset + (item_count * 4)); + + resource->length += + acpi_rs_get_resource_source(aml_resource_length, + (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); + break; + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + item_count = + acpi_rs_decode_bitmask(ACPI_GET8(source), + destination); + if (item_count) { + resource->length += (item_count - 1); + } + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; + break; + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + ACPI_MOVE_16_TO_16(&temp16, source); + + item_count = + acpi_rs_decode_bitmask(temp16, destination); + if (item_count) { + resource->length += (item_count - 1); + } + + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; + break; + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (info->resource_offset) { + case ACPI_RSC_COMPARE_AML_LENGTH: + if (aml_resource_length != info->value) { + goto exit; + } + break; + + case ACPI_RSC_COMPARE_VALUE: + if (ACPI_GET8(source) != info->value) { + goto exit; + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Invalid conversion sub-opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } - *buffer = temp8; - buffer += 1; + count--; + info++; } - /* Loop through all of the Vendor Specific fields */ + exit: + if (!flags_mode) { + /* Round the resource struct length up to the next 32-bit boundary */ - for (index = 0; index < linked_list->data.vendor_specific.length; - index++) { - temp8 = linked_list->data.vendor_specific.reserved[index]; - - *buffer = temp8; - buffer += 1; + resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length); } - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); return_ACPI_STATUS(AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_rs_start_depend_fns_resource + * FUNCTION: acpi_rs_convert_resource_to_aml * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned + * PARAMETERS: Resource - Pointer to the resource descriptor + * Aml - Where the AML descriptor is returned + * Info - Pointer to appropriate conversion table * * RETURN: Status * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. + * DESCRIPTION: Convert an internal resource descriptor to the corresponding + * external AML resource descriptor. * ******************************************************************************/ acpi_status -acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, - acpi_size * structure_size) +acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info) { - u8 *buffer = byte_stream_buffer; - struct acpi_resource *output_struct = (void *)*output_buffer; - u8 temp8 = 0; - acpi_size struct_size = - ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf); - - ACPI_FUNCTION_TRACE("rs_start_depend_fns_resource"); - - /* The number of bytes consumed are found in the descriptor (Bits:0-1) */ - - temp8 = *buffer; - - *bytes_consumed = (temp8 & 0x01) + 1; - - output_struct->id = ACPI_RSTYPE_START_DPF; - - /* Point to Byte 1 if it is used */ - - if (2 == *bytes_consumed) { - buffer += 1; - temp8 = *buffer; - - /* Check Compatibility priority */ - - output_struct->data.start_dpf.compatibility_priority = - temp8 & 0x03; - - if (3 == output_struct->data.start_dpf.compatibility_priority) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); - } - - /* Check Performance/Robustness preference */ + void *source = NULL; + void *destination; + acpi_rsdesc_size aml_length = 0; + u8 count; + u16 temp16 = 0; + u16 item_count = 0; - output_struct->data.start_dpf.performance_robustness = - (temp8 >> 2) & 0x03; + ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml"); - if (3 == output_struct->data.start_dpf.performance_robustness) { - return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); + /* + * First table entry must be ACPI_RSC_INITxxx and must contain the + * table length (# of table entries) + */ + count = INIT_TABLE_LENGTH(info); + + while (count) { + /* + * Source is the internal resource descriptor, + * destination is the external AML byte stream buffer + */ + source = ACPI_ADD_PTR(void, resource, info->resource_offset); + destination = ACPI_ADD_PTR(void, aml, info->aml_offset); + + switch (info->opcode) { + case ACPI_RSC_INITSET: + + ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); + aml_length = INIT_RESOURCE_LENGTH(info); + acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), + aml_length, aml); + break; + + case ACPI_RSC_INITGET: + break; + + case ACPI_RSC_FLAGINIT: + /* + * Clear the flag byte + */ + ACPI_SET8(destination) = 0; + break; + + case ACPI_RSC_1BITFLAG: + /* + * Mask and shift the flag bit + */ + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x01) << info->value); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x03) << info->value); + break; + + case ACPI_RSC_COUNT: + + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; + + aml_length = + (u16) (aml_length + + (info->value * (item_count - 1))); + break; + + case ACPI_RSC_COUNT16: + + item_count = ACPI_GET16(source); + aml_length = (u16) (aml_length + item_count); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_LENGTH: + + acpi_rs_set_resource_length(info->value, aml); + break; + + case ACPI_RSC_MOVE8: + case ACPI_RSC_MOVE16: + case ACPI_RSC_MOVE32: + case ACPI_RSC_MOVE64: + + if (info->value) { + item_count = info->value; + } + acpi_rs_move_data(destination, source, item_count, + info->opcode); + break; + + case ACPI_RSC_ADDRESS: + + /* Set the Resource Type, General Flags, and Type-Specific Flags */ + + acpi_rs_set_address_common(aml, resource); + break; + + case ACPI_RSC_SOURCEX: + /* + * Optional resource_source (Index and String) + */ + aml_length = + acpi_rs_set_resource_source(aml, + (acpi_rs_length) + aml_length, source); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_SOURCE: + /* + * Optional resource_source (Index and String). This is the more + * complicated case used by the Interrupt() macro + */ + aml_length = + acpi_rs_set_resource_source(aml, info->value, + source); + acpi_rs_set_resource_length(aml_length, aml); + break; + + case ACPI_RSC_BITMASK: + /* + * 8-bit encoded bitmask (DMA macro) + */ + ACPI_SET8(destination) = (u8) + acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, resource, + info->value)); + break; + + case ACPI_RSC_BITMASK16: + /* + * 16-bit encoded bitmask (IRQ macro) + */ + temp16 = acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value)); + ACPI_MOVE_16_TO_16(destination, &temp16); + break; + + case ACPI_RSC_EXIT_LE: + /* + * Control - Exit conversion if less than or equal + */ + if (item_count <= info->value) { + goto exit; + } + break; + + case ACPI_RSC_EXIT_NE: + /* + * Control - Exit conversion if not equal + */ + switch (COMPARE_OPCODE(info)) { + case ACPI_RSC_COMPARE_VALUE: + + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) != + COMPARE_VALUE(info)) { + goto exit; + } + break; + + default: + + ACPI_ERROR((AE_INFO, + "Invalid conversion sub-opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); + return_ACPI_STATUS(AE_BAD_PARAMETER); } - } else { - output_struct->data.start_dpf.compatibility_priority = - ACPI_ACCEPTABLE_CONFIGURATION; - output_struct->data.start_dpf.performance_robustness = - ACPI_ACCEPTABLE_CONFIGURATION; + count--; + info++; } - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; + exit: return_ACPI_STATUS(AE_OK); } -/******************************************************************************* - * - * FUNCTION: acpi_rs_end_depend_fns_resource - * - * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte - * stream - * bytes_consumed - Pointer to where the number of bytes - * consumed the byte_stream_buffer is - * returned - * output_buffer - Pointer to the return data buffer - * structure_size - Pointer to where the number of bytes - * in the return data struct is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the output_buffer. Return the - * number of bytes consumed from the byte stream. - * - ******************************************************************************/ - -acpi_status -acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size) -{ - struct acpi_resource *output_struct = (void *)*output_buffer; - acpi_size struct_size = ACPI_RESOURCE_LENGTH; - - ACPI_FUNCTION_TRACE("rs_end_depend_fns_resource"); - - /* The number of bytes consumed is static */ - - *bytes_consumed = 1; +#if 0 +/* Previous resource validations */ - /* Fill out the structure */ - - output_struct->id = ACPI_RSTYPE_END_DPF; - - /* Set the Length parameter */ - - output_struct->length = (u32) struct_size; - - /* Return the final size of the structure */ - - *structure_size = struct_size; - return_ACPI_STATUS(AE_OK); +if (aml->ext_address64.revision_iD != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { + return_ACPI_STATUS(AE_SUPPORT); } -/******************************************************************************* - * - * FUNCTION: acpi_rs_start_depend_fns_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * output_buffer used - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream - * - ******************************************************************************/ - -acpi_status -acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - u8 temp8 = 0; - - ACPI_FUNCTION_TRACE("rs_start_depend_fns_stream"); +if (resource->data.start_dpf.performance_robustness >= 3) { + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); +} +if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { /* - * The descriptor field is set based upon whether a byte is needed - * to contain Priority data. + * Only [active_high, edge_sensitive] or [active_low, level_sensitive] + * polarity/trigger interrupts are allowed (ACPI spec, section + * "IRQ Format"), so 0x00 and 0x09 are illegal. */ - if (ACPI_ACCEPTABLE_CONFIGURATION == - linked_list->data.start_dpf.compatibility_priority && - ACPI_ACCEPTABLE_CONFIGURATION == - linked_list->data.start_dpf.performance_robustness) { - *buffer = 0x30; - } else { - *buffer = 0x31; - buffer += 1; - - /* Set the Priority Byte Definition */ - - temp8 = 0; - temp8 = - (u8) ((linked_list->data.start_dpf. - performance_robustness & 0x03) << 2); - temp8 |= - (linked_list->data.start_dpf.compatibility_priority & 0x03); - *buffer = temp8; - } - - buffer += 1; - - /* Return the number of bytes consumed in this operation */ - - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); + ACPI_ERROR((AE_INFO, + "Invalid interrupt polarity/trigger in resource list, %X", + aml->irq.flags)); + return_ACPI_STATUS(AE_BAD_DATA); } -/******************************************************************************* - * - * FUNCTION: acpi_rs_end_depend_fns_stream - * - * PARAMETERS: linked_list - Pointer to the resource linked list - * output_buffer - Pointer to the user's return buffer - * bytes_consumed - Pointer to where the number of bytes - * used in the output_buffer is returned - * - * RETURN: Status - * - * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream - * - ******************************************************************************/ - -acpi_status -acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed) -{ - u8 *buffer = *output_buffer; - - ACPI_FUNCTION_TRACE("rs_end_depend_fns_stream"); - - /* The descriptor field is static */ - - *buffer = 0x38; - buffer += 1; +resource->data.extended_irq.interrupt_count = temp8; +if (temp8 < 1) { + /* Must have at least one IRQ */ - /* Return the number of bytes consumed in this operation */ + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); +} - *bytes_consumed = ACPI_PTR_DIFF(buffer, *output_buffer); - return_ACPI_STATUS(AE_OK); +if (resource->data.dma.transfer == 0x03) { + ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)")); + return_ACPI_STATUS(AE_BAD_DATA); } +#endif diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 4446778eaf79..25b5aedd6612 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,6 +50,389 @@ ACPI_MODULE_NAME("rsutils") /******************************************************************************* * + * FUNCTION: acpi_rs_decode_bitmask + * + * PARAMETERS: Mask - Bitmask to decode + * List - Where the converted list is returned + * + * RETURN: Count of bits set (length of list) + * + * DESCRIPTION: Convert a bit mask into a list of values + * + ******************************************************************************/ +u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) +{ + acpi_native_uint i; + u8 bit_count; + + ACPI_FUNCTION_ENTRY(); + + /* Decode the mask bits */ + + for (i = 0, bit_count = 0; mask; i++) { + if (mask & 0x0001) { + list[bit_count] = (u8) i; + bit_count++; + } + + mask >>= 1; + } + + return (bit_count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_encode_bitmask + * + * PARAMETERS: List - List of values to encode + * Count - Length of list + * + * RETURN: Encoded bitmask + * + * DESCRIPTION: Convert a list of values to an encoded bitmask + * + ******************************************************************************/ + +u16 acpi_rs_encode_bitmask(u8 * list, u8 count) +{ + acpi_native_uint i; + u16 mask; + + ACPI_FUNCTION_ENTRY(); + + /* Encode the list into a single bitmask */ + + for (i = 0, mask = 0; i < count; i++) { + mask |= (0x0001 << list[i]); + } + + return (mask); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_move_data + * + * PARAMETERS: Destination - Pointer to the destination descriptor + * Source - Pointer to the source descriptor + * item_count - How many items to move + * move_type - Byte width + * + * RETURN: None + * + * DESCRIPTION: Move multiple data items from one descriptor to another. Handles + * alignment issues and endian issues if necessary, as configured + * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) + * + ******************************************************************************/ + +void +acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) +{ + acpi_native_uint i; + + ACPI_FUNCTION_ENTRY(); + + /* One move per item */ + + for (i = 0; i < item_count; i++) { + switch (move_type) { + /* + * For the 8-bit case, we can perform the move all at once + * since there are no alignment or endian issues + */ + case ACPI_RSC_MOVE8: + ACPI_MEMCPY(destination, source, item_count); + return; + + /* + * 16-, 32-, and 64-bit cases must use the move macros that perform + * endian conversion and/or accomodate hardware that cannot perform + * misaligned memory transfers + */ + case ACPI_RSC_MOVE16: + ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], + &ACPI_CAST_PTR(u16, source)[i]); + break; + + case ACPI_RSC_MOVE32: + ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], + &ACPI_CAST_PTR(u32, source)[i]); + break; + + case ACPI_RSC_MOVE64: + ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], + &ACPI_CAST_PTR(u64, source)[i]); + break; + + default: + return; + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_length + * + * PARAMETERS: total_length - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the resource_length field of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically. Note: Descriptor Type field must + * be valid. + * + ******************************************************************************/ + +void +acpi_rs_set_resource_length(acpi_rsdesc_size total_length, + union aml_resource *aml) +{ + acpi_rs_length resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* Length is the total descriptor length minus the header length */ + + resource_length = (acpi_rs_length) + (total_length - acpi_ut_get_resource_header_length(aml)); + + /* Length is stored differently for large and small descriptors */ + + if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large descriptor -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, + &resource_length); + } else { + /* Small descriptor -- bits 2:0 of byte 0 contain the length */ + + aml->small_header.descriptor_type = (u8) + + /* Clear any existing length, preserving descriptor type bits */ + ((aml->small_header. + descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK) + + | resource_length); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_header + * + * PARAMETERS: descriptor_type - Byte to be inserted as the type + * total_length - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically + * + ******************************************************************************/ + +void +acpi_rs_set_resource_header(u8 descriptor_type, + acpi_rsdesc_size total_length, + union aml_resource *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* Set the Resource Type */ + + aml->small_header.descriptor_type = descriptor_type; + + /* Set the Resource Length */ + + acpi_rs_set_resource_length(total_length, aml); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_strcpy + * + * PARAMETERS: Destination - Pointer to the destination string + * Source - Pointer to the source string + * + * RETURN: String length, including NULL terminator + * + * DESCRIPTION: Local string copy that returns the string length, saving a + * strcpy followed by a strlen. + * + ******************************************************************************/ + +static u16 acpi_rs_strcpy(char *destination, char *source) +{ + u16 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; source[i]; i++) { + destination[i] = source[i]; + } + + destination[i] = 0; + + /* Return string length including the NULL terminator */ + + return ((u16) (i + 1)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_source + * + * PARAMETERS: resource_length - Length field of the descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Where the resource_source is returned + * Aml - Pointer to the raw AML descriptor + * string_ptr - (optional) where to store the actual + * resource_source string + * + * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit + * + * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +acpi_rs_length +acpi_rs_get_resource_source(acpi_rs_length resource_length, + acpi_rs_length minimum_length, + struct acpi_resource_source * resource_source, + union aml_resource * aml, char *string_ptr) +{ + acpi_rsdesc_size total_length; + u8 *aml_resource_source; + + ACPI_FUNCTION_ENTRY(); + + total_length = + resource_length + sizeof(struct aml_resource_large_header); + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); + + /* + * resource_source is present if the length of the descriptor is longer than + * the minimum length. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the minimum length. + */ + if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { + /* Get the resource_source_index */ + + resource_source->index = aml_resource_source[0]; + + resource_source->string_ptr = string_ptr; + if (!string_ptr) { + /* + * String destination pointer is not specified; Set the String + * pointer to the end of the current resource_source structure. + */ + resource_source->string_ptr = + ACPI_ADD_PTR(char, resource_source, + sizeof(struct acpi_resource_source)); + } + + /* + * In order for the struct_size to fall on a 32-bit boundary, calculate + * the length of the string (+1 for the NULL terminator) and expand the + * struct_size to the next 32-bit boundary. + * + * Zero the entire area of the buffer. + */ + total_length = + ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN + ((char *)&aml_resource_source[1]) + + 1); + ACPI_MEMSET(resource_source->string_ptr, 0, total_length); + + /* Copy the resource_source string to the destination */ + + resource_source->string_length = + acpi_rs_strcpy(resource_source->string_ptr, + (char *)&aml_resource_source[1]); + + return ((acpi_rs_length) total_length); + } + + /* resource_source is not present */ + + resource_source->index = 0; + resource_source->string_length = 0; + resource_source->string_ptr = NULL; + return (0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_source + * + * PARAMETERS: Aml - Pointer to the raw AML descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Internal resource_source + + * + * RETURN: Total length of the AML descriptor + * + * DESCRIPTION: Convert an optional resource_source from internal format to a + * raw AML resource descriptor + * + ******************************************************************************/ + +acpi_rsdesc_size +acpi_rs_set_resource_source(union aml_resource * aml, + acpi_rs_length minimum_length, + struct acpi_resource_source * resource_source) +{ + u8 *aml_resource_source; + acpi_rsdesc_size descriptor_length; + + ACPI_FUNCTION_ENTRY(); + + descriptor_length = minimum_length; + + /* Non-zero string length indicates presence of a resource_source */ + + if (resource_source->string_length) { + /* Point to the end of the AML descriptor */ + + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); + + /* Copy the resource_source_index */ + + aml_resource_source[0] = (u8) resource_source->index; + + /* Copy the resource_source string */ + + ACPI_STRCPY((char *)&aml_resource_source[1], + resource_source->string_ptr); + + /* + * Add the length of the string (+ 1 for null terminator) to the + * final descriptor length + */ + descriptor_length += + ((acpi_rsdesc_size) resource_source->string_length + 1); + } + + /* Return the new total length of the AML descriptor */ + + return (descriptor_length); +} + +/******************************************************************************* + * * FUNCTION: acpi_rs_get_prt_method_data * * PARAMETERS: Handle - a handle to the containing object @@ -65,8 +448,9 @@ ACPI_MODULE_NAME("rsutils") * and the contents of the callers buffer is undefined. * ******************************************************************************/ + acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; @@ -284,7 +668,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) * Convert the linked list into a byte stream */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer); + status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index ee5a5c509199..88b67077aeeb 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,13 +57,17 @@ ACPI_MODULE_NAME("rsxface") ACPI_COPY_FIELD(out, in, decode); \ ACPI_COPY_FIELD(out, in, min_address_fixed); \ ACPI_COPY_FIELD(out, in, max_address_fixed); \ - ACPI_COPY_FIELD(out, in, attribute); \ + ACPI_COPY_FIELD(out, in, info); \ ACPI_COPY_FIELD(out, in, granularity); \ - ACPI_COPY_FIELD(out, in, min_address_range); \ - ACPI_COPY_FIELD(out, in, max_address_range); \ - ACPI_COPY_FIELD(out, in, address_translation_offset); \ + ACPI_COPY_FIELD(out, in, minimum); \ + ACPI_COPY_FIELD(out, in, maximum); \ + ACPI_COPY_FIELD(out, in, translation_offset); \ ACPI_COPY_FIELD(out, in, address_length); \ ACPI_COPY_FIELD(out, in, resource_source); +/* Local prototypes */ +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); + /******************************************************************************* * * FUNCTION: acpi_get_irq_routing_table @@ -86,6 +90,7 @@ ACPI_MODULE_NAME("rsxface") * the object indicated by the passed device_handle. * ******************************************************************************/ + acpi_status acpi_get_irq_routing_table(acpi_handle device_handle, struct acpi_buffer *ret_buffer) @@ -222,12 +227,12 @@ EXPORT_SYMBOL(acpi_get_possible_resources); * * FUNCTION: acpi_walk_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * Path - method name of the resources we want + * Name - Method name of the resources we want * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * user_function - called for each resource - * Context - passed to user_function + * user_function - Called for each resource + * Context - Passed to user_function * * RETURN: Status * @@ -239,79 +244,74 @@ EXPORT_SYMBOL(acpi_get_possible_resources); acpi_status acpi_walk_resources(acpi_handle device_handle, - char *path, + char *name, ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) { acpi_status status; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer buffer; struct acpi_resource *resource; - struct acpi_resource *buffer_end; + struct acpi_resource *resource_end; ACPI_FUNCTION_TRACE("acpi_walk_resources"); - if (!device_handle || - (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && - ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && + ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_rs_get_method_data(device_handle, path, &buffer); + /* Get the _CRS or _PRS resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Setup pointers */ + /* Buffer now contains the resource list */ - resource = (struct acpi_resource *)buffer.pointer; - buffer_end = ACPI_CAST_PTR(struct acpi_resource, - ((u8 *) buffer.pointer + buffer.length)); + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - /* Walk the resource list */ + /* Walk the resource list until the end_tag is found (or buffer end) */ - for (;;) { - if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { + while (resource < resource_end) { + /* Sanity check the resource */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; break; } - status = user_function(resource, context); - - switch (status) { - case AE_OK: - case AE_CTRL_DEPTH: + /* Invoke the user function, abort on any error returned */ - /* Just keep going */ + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + /* This is an OK termination by the user function */ - status = AE_OK; + status = AE_OK; + } break; + } - case AE_CTRL_TERMINATE: - - /* Exit now, with OK stats */ - - status = AE_OK; - goto cleanup; - - default: - - /* All others are valid exceptions */ + /* end_tag indicates end-of-list */ - goto cleanup; + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; } /* Get the next resource descriptor */ - resource = ACPI_NEXT_RESOURCE(resource); - - /* Check for end-of-buffer */ - - if (resource >= buffer_end) { - goto cleanup; - } + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); } - cleanup: - - acpi_os_free(buffer.pointer); + ACPI_MEM_FREE(buffer.pointer); return_ACPI_STATUS(status); } @@ -360,8 +360,8 @@ EXPORT_SYMBOL(acpi_set_current_resources); * * FUNCTION: acpi_resource_to_address64 * - * PARAMETERS: resource - Pointer to a resource - * out - Pointer to the users's return + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return * buffer (a struct * struct acpi_resource_address64) * @@ -381,20 +381,26 @@ acpi_resource_to_address64(struct acpi_resource *resource, struct acpi_resource_address16 *address16; struct acpi_resource_address32 *address32; - switch (resource->id) { - case ACPI_RSTYPE_ADDRESS16: + if (!resource || !out) { + return (AE_BAD_PARAMETER); + } + + /* Convert 16 or 32 address descriptor to 64 */ + + switch (resource->type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: address16 = (struct acpi_resource_address16 *)&resource->data; ACPI_COPY_ADDRESS(out, address16); break; - case ACPI_RSTYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS32: address32 = (struct acpi_resource_address32 *)&resource->data; ACPI_COPY_ADDRESS(out, address32); break; - case ACPI_RSTYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_ADDRESS64: /* Simple copy for 64 bit source */ @@ -410,3 +416,113 @@ acpi_resource_to_address64(struct acpi_resource *resource, } EXPORT_SYMBOL(acpi_resource_to_address64); + +/******************************************************************************* + * + * FUNCTION: acpi_get_vendor_resource + * + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Walk a resource template for the specified evice to find a + * vendor-defined resource that matches the supplied UUID and + * UUID subtype. Returns a struct acpi_resource of type Vendor. + * + ******************************************************************************/ + +acpi_status +acpi_get_vendor_resource(acpi_handle device_handle, + char *name, + struct acpi_vendor_uuid * uuid, + struct acpi_buffer * ret_buffer) +{ + struct acpi_vendor_walk_info info; + acpi_status status; + + /* Other parameters are validated by acpi_walk_resources */ + + if (!uuid || !ret_buffer) { + return (AE_BAD_PARAMETER); + } + + info.uuid = uuid; + info.buffer = ret_buffer; + info.status = AE_NOT_EXIST; + + /* Walk the _CRS or _PRS resource list for this device */ + + status = + acpi_walk_resources(device_handle, name, + acpi_rs_match_vendor_resource, &info); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (info.status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_match_vendor_resource + * + * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID + * + ******************************************************************************/ + +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) +{ + struct acpi_vendor_walk_info *info = context; + struct acpi_resource_vendor_typed *vendor; + struct acpi_buffer *buffer; + acpi_status status; + + /* Ignore all descriptors except Vendor */ + + if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { + return (AE_OK); + } + + vendor = &resource->data.vendor_typed; + + /* + * For a valid match, these conditions must hold: + * + * 1) Length of descriptor data must be at least as long as a UUID struct + * 2) The UUID subtypes must match + * 3) The UUID data must match + */ + if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || + (vendor->uuid_subtype != info->uuid->subtype) || + (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { + return (AE_OK); + } + + /* Validate/Allocate/Clear caller buffer */ + + buffer = info->buffer; + status = acpi_ut_initialize_buffer(buffer, resource->length); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Found the correct resource, copy and return it */ + + ACPI_MEMCPY(buffer->pointer, resource, resource->length); + buffer->length = resource->length; + + /* Found the desired descriptor, terminate resource walk */ + + info->status = AE_OK; + return (AE_CTRL_TERMINATE); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3b26a7104363..9271e5209ac1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -851,7 +851,7 @@ static void acpi_device_set_id(struct acpi_device *device, * ---- * Fix for the system root bus device -- the only root-level device. */ - if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { + if (((acpi_handle)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) { hid = ACPI_BUS_HID; strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); strcpy(device->pnp.device_class, ACPI_BUS_CLASS); diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c index af7935a95bcc..47fb4b394eec 100644 --- a/drivers/acpi/sleep/poweroff.c +++ b/drivers/acpi/sleep/poweroff.c @@ -33,9 +33,7 @@ int acpi_sleep_prepare(u32 acpi_state) ACPI_FLUSH_CPU_CACHE(); acpi_enable_wakeup_device_prep(acpi_state); #endif - if (acpi_state == ACPI_STATE_S5) { - acpi_wakeup_gpe_poweroff_prepare(); - } + acpi_gpe_sleep_prepare(acpi_state); acpi_enter_sleep_state_prep(acpi_state); return 0; } @@ -53,11 +51,16 @@ void acpi_power_off(void) static int acpi_shutdown(struct sys_device *x) { - if (system_state == SYSTEM_POWER_OFF) { - /* Prepare if we are going to power off the system */ + switch (system_state) { + case SYSTEM_POWER_OFF: + /* Prepare to power off the system */ return acpi_sleep_prepare(ACPI_STATE_S5); + case SYSTEM_SUSPEND_DISK: + /* Prepare to suspend the system to disk */ + return acpi_sleep_prepare(ACPI_STATE_S4); + default: + return 0; } - return 0; } static struct sysdev_class acpi_sysclass = { diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index efd0001c6f05..f3e70397a7d6 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h @@ -5,4 +5,4 @@ extern int acpi_suspend (u32 state); extern void acpi_enable_wakeup_device_prep(u8 sleep_state); extern void acpi_enable_wakeup_device(u8 sleep_state); extern void acpi_disable_wakeup_device(u8 sleep_state); -extern void acpi_wakeup_gpe_poweroff_prepare(void); +extern void acpi_gpe_sleep_prepare(u32 sleep_state); diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 4134ed43d026..85df0ceda2a9 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -192,7 +192,7 @@ late_initcall(acpi_wakeup_device_init); * RUNTIME GPEs, we simply mark all GPES that * are not enabled for wakeup from S5 as RUNTIME. */ -void acpi_wakeup_gpe_poweroff_prepare(void) +void acpi_gpe_sleep_prepare(u32 sleep_state) { struct list_head *node, *next; @@ -201,8 +201,8 @@ void acpi_wakeup_gpe_poweroff_prepare(void) struct acpi_device, wakeup_list); - /* The GPE can wakeup system from S5, don't touch it */ - if ((u32) dev->wakeup.sleep_state == ACPI_STATE_S5) + /* The GPE can wakeup system from this state, don't touch it */ + if ((u32) dev->wakeup.sleep_state >= sleep_state) continue; /* acpi_set_gpe_type will automatically disable GPE */ acpi_set_gpe_type(dev->wakeup.gpe_device, diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index a03939399fa9..03b37d2223bc 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -501,8 +501,8 @@ acpi_status acpi_tb_convert_table_fadt(void) * at least as long as the version 1.0 FADT */ if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) { - ACPI_REPORT_ERROR(("FADT is invalid, too short: 0x%X\n", - acpi_gbl_FADT->length)); + ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X", + acpi_gbl_FADT->length)); return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } @@ -517,7 +517,10 @@ acpi_status acpi_tb_convert_table_fadt(void) if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) { /* Length is too short to be a V2.0 table */ - ACPI_REPORT_WARNING(("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", acpi_gbl_FADT->length, acpi_gbl_FADT->revision)); + ACPI_WARNING((AE_INFO, + "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table", + acpi_gbl_FADT->length, + acpi_gbl_FADT->revision)); acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT); @@ -554,7 +557,9 @@ acpi_status acpi_tb_convert_table_fadt(void) ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Hex dump of common internal FADT, size %d (%X)\n", acpi_gbl_FADT->length, acpi_gbl_FADT->length)); - ACPI_DUMP_BUFFER((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length); + + ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT), + acpi_gbl_FADT->length); return_ACPI_STATUS(AE_OK); } @@ -580,13 +585,15 @@ acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) /* Absolute minimum length is 24, but the ACPI spec says 64 */ if (acpi_gbl_FACS->length < 24) { - ACPI_REPORT_ERROR(("Invalid FACS table length: 0x%X\n", - acpi_gbl_FACS->length)); + ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X", + acpi_gbl_FACS->length)); return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); } if (acpi_gbl_FACS->length < 64) { - ACPI_REPORT_WARNING(("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", acpi_gbl_FACS->length)); + ACPI_WARNING((AE_INFO, + "FACS is shorter than the ACPI specification allows: 0x%X, using anyway", + acpi_gbl_FACS->length)); } /* Copy fields to the new FACS */ diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 6acd5aeb093e..09b4ee6dfd60 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -91,9 +91,9 @@ acpi_tb_get_table(struct acpi_pointer *address, status = acpi_tb_get_table_body(address, &header, table_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not get ACPI table (size %X), %s\n", - header.length, - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not get ACPI table (size %X)", + header.length)); return_ACPI_STATUS(status); } @@ -148,7 +148,6 @@ acpi_tb_get_table_header(struct acpi_pointer *address, sizeof(struct acpi_table_header), (void *)&header); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_FORMAT_UINT64(address->pointer.physical), sizeof(struct acpi_table_header))); return_ACPI_STATUS(status); } @@ -161,8 +160,8 @@ acpi_tb_get_table_header(struct acpi_pointer *address, default: - ACPI_REPORT_ERROR(("Invalid address flags %X\n", - address->pointer_type)); + ACPI_ERROR((AE_INFO, "Invalid address flags %X", + address->pointer_type)); return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -253,8 +252,8 @@ acpi_tb_table_override(struct acpi_table_header *header, if (ACPI_FAILURE(status)) { /* Some severe error from the OSL, but we basically ignore it */ - ACPI_REPORT_ERROR(("Could not override ACPI table, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not override ACPI table")); return_ACPI_STATUS(status); } @@ -273,15 +272,14 @@ acpi_tb_table_override(struct acpi_table_header *header, status = acpi_tb_get_this_table(&address, new_table, table_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not copy override ACPI table, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table")); return_ACPI_STATUS(status); } /* Copy the table info */ - ACPI_REPORT_INFO(("Table [%4.4s] replaced by host OS\n", - table_info->pointer->signature)); + ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS", + table_info->pointer->signature)); return_ACPI_STATUS(AE_OK); } @@ -327,7 +325,9 @@ acpi_tb_get_this_table(struct acpi_pointer *address, full_table = ACPI_MEM_ALLOCATE(header->length); if (!full_table) { - ACPI_REPORT_ERROR(("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length)); + ACPI_ERROR((AE_INFO, + "Could not allocate table memory for [%4.4s] length %X", + header->signature, header->length)); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -351,7 +351,12 @@ acpi_tb_get_this_table(struct acpi_pointer *address, (acpi_size) header->length, (void *)&full_table); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64(address->pointer.physical), header->length)); + ACPI_ERROR((AE_INFO, + "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X", + header->signature, + ACPI_FORMAT_UINT64(address->pointer. + physical), + header->length)); return (status); } @@ -362,8 +367,8 @@ acpi_tb_get_this_table(struct acpi_pointer *address, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid address flags %X\n", - address->pointer_type)); + ACPI_ERROR((AE_INFO, "Invalid address flags %X", + address->pointer_type)); return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c index 8d72343537e7..134e5dce0bc1 100644 --- a/drivers/acpi/tables/tbgetall.c +++ b/drivers/acpi/tables/tbgetall.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -152,7 +152,9 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address, /* Signature must match request */ if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) { - ACPI_REPORT_ERROR(("Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature)); + ACPI_ERROR((AE_INFO, + "Incorrect table signature - wanted [%s] found [%4.4s]", + signature, header.signature)); return_ACPI_STATUS(AE_BAD_SIGNATURE); } @@ -231,14 +233,18 @@ acpi_status acpi_tb_get_required_tables(void) */ status = acpi_tb_get_primary_table(&address, &table_info); if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { - ACPI_REPORT_WARNING(("%s, while getting table at %8.8X%8.8X\n", acpi_format_exception(status), ACPI_FORMAT_UINT64(address.pointer.value))); + ACPI_WARNING((AE_INFO, + "%s, while getting table at %8.8X%8.8X", + acpi_format_exception(status), + ACPI_FORMAT_UINT64(address.pointer. + value))); } } /* We must have a FADT to continue */ if (!acpi_gbl_FADT) { - ACPI_REPORT_ERROR(("No FADT present in RSDT/XSDT\n")); + ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -248,7 +254,8 @@ acpi_status acpi_tb_get_required_tables(void) */ status = acpi_tb_convert_table_fadt(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not convert FADT to internal common format\n")); + ACPI_ERROR((AE_INFO, + "Could not convert FADT to internal common format")); return_ACPI_STATUS(status); } @@ -258,8 +265,8 @@ acpi_status acpi_tb_get_required_tables(void) status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not get/install the FACS, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not get/install the FACS")); return_ACPI_STATUS(status); } @@ -278,7 +285,7 @@ acpi_status acpi_tb_get_required_tables(void) status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not get/install the DSDT\n")); + ACPI_ERROR((AE_INFO, "Could not get/install the DSDT")); return_ACPI_STATUS(status); } @@ -292,7 +299,9 @@ acpi_status acpi_tb_get_required_tables(void) "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width)); - ACPI_DUMP_BUFFER((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length); + + ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT), + acpi_gbl_DSDT->length); /* Always delete the RSDP mapping, we are done with it */ diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 10db8484e462..7ffd0fddb4e5 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -128,8 +128,8 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not acquire table mutex, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire table mutex")); return_ACPI_STATUS(status); } @@ -146,9 +146,9 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) status = acpi_tb_init_table_descriptor(table_info->type, table_info); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Could not install table [%4.4s], %s\n", - table_info->pointer->signature, - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not install table [%4.4s]", + table_info->pointer->signature)); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index ad0252c2f7db..4d308220225d 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,7 +176,7 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) { int no_match; - ACPI_FUNCTION_NAME("tb_validate_rsdt"); + ACPI_FUNCTION_ENTRY(); /* * Search for appropriate signature, RSDT or XSDT @@ -192,24 +192,24 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) if (no_match) { /* Invalid RSDT or XSDT signature */ - ACPI_REPORT_ERROR(("Invalid signature where RSDP indicates RSDT/XSDT should be located\n")); + ACPI_ERROR((AE_INFO, + "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:")); ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); - ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, - "RSDT/XSDT signature at %X (%p) is invalid\n", - acpi_gbl_RSDP->rsdt_physical_address, - (void *)(acpi_native_uint) acpi_gbl_RSDP-> - rsdt_physical_address)); + ACPI_ERROR((AE_INFO, + "RSDT/XSDT signature at %X (%p) is invalid", + acpi_gbl_RSDP->rsdt_physical_address, + (void *)(acpi_native_uint) acpi_gbl_RSDP-> + rsdt_physical_address)); if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - ACPI_REPORT_ERROR(("Looking for RSDT\n")) + ACPI_ERROR((AE_INFO, "Looking for RSDT")); } else { - ACPI_REPORT_ERROR(("Looking for XSDT\n")) + ACPI_ERROR((AE_INFO, "Looking for XSDT")); } ACPI_DUMP_BUFFER((char *)table_ptr, 48); - return (AE_BAD_SIGNATURE); } @@ -243,15 +243,13 @@ acpi_status acpi_tb_get_table_rsdt(void) table_info.type = ACPI_TABLE_XSDT; status = acpi_tb_get_table(&address, &table_info); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not get the RSDT/XSDT, %s\n", - acpi_format_exception(status))); - + ACPI_EXCEPTION((AE_INFO, status, + "Could not get the RSDT/XSDT")); return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n", + "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n", acpi_gbl_RSDP, ACPI_FORMAT_UINT64(address.pointer.value))); diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 4b2fbb592f49..bc571592f087 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,9 +94,8 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) new_table_desc->pointer->length) && (!ACPI_MEMCMP - ((const char *)table_desc->pointer, - (const char *)new_table_desc->pointer, - (acpi_size) new_table_desc->pointer->length))) { + (table_desc->pointer, new_table_desc->pointer, + new_table_desc->pointer->length))) { /* Match: this table is already installed */ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, @@ -145,14 +144,13 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) { acpi_name signature; - ACPI_FUNCTION_NAME("tb_validate_table_header"); + ACPI_FUNCTION_ENTRY(); /* Verify that this is a valid address */ if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Cannot read table header at %p\n", - table_header)); + ACPI_ERROR((AE_INFO, + "Cannot read table header at %p", table_header)); return (AE_BAD_ADDRESS); } @@ -161,12 +159,12 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) ACPI_MOVE_32_TO_32(&signature, table_header->signature); if (!acpi_ut_valid_acpi_name(signature)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Table signature at %p [%p] has invalid characters\n", - table_header, &signature)); + ACPI_ERROR((AE_INFO, + "Table signature at %p [%p] has invalid characters", + table_header, &signature)); - ACPI_REPORT_WARNING(("Invalid table signature found: [%4.4s]\n", - (char *)&signature)); + ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]", + ACPI_CAST_PTR(char, &signature))); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); @@ -176,11 +174,13 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) /* Validate the table length */ if (table_header->length < sizeof(struct acpi_table_header)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid length in table header %p name %4.4s\n", - table_header, (char *)&signature)); + ACPI_ERROR((AE_INFO, + "Invalid length in table header %p name %4.4s", + table_header, (char *)&signature)); - ACPI_REPORT_WARNING(("Invalid table header length (0x%X) found\n", (u32) table_header->length)); + ACPI_WARNING((AE_INFO, + "Invalid table header length (0x%X) found", + (u32) table_header->length)); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); @@ -219,7 +219,10 @@ acpi_tb_verify_table_checksum(struct acpi_table_header * table_header) /* Return the appropriate exception */ if (checksum) { - ACPI_REPORT_WARNING(("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", table_header->signature, (u32) table_header->checksum, (u32) checksum)); + ACPI_WARNING((AE_INFO, + "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)", + table_header->signature, + (u32) table_header->checksum, (u32) checksum)); status = AE_BAD_CHECKSUM; } @@ -241,16 +244,16 @@ acpi_tb_verify_table_checksum(struct acpi_table_header * table_header) u8 acpi_tb_generate_checksum(void *buffer, u32 length) { - const u8 *limit; - const u8 *rover; + u8 *end_buffer; + u8 *rover; u8 sum = 0; if (buffer && length) { /* Buffer and Length are valid */ - limit = (u8 *) buffer + length; + end_buffer = ACPI_ADD_PTR(u8, buffer, length); - for (rover = buffer; rover < limit; rover++) { + for (rover = buffer; rover < end_buffer; rover++) { sum = (u8) (sum + *rover); } } @@ -292,8 +295,7 @@ acpi_tb_handle_to_object(u16 table_id, } } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "table_id=%X does not exist\n", - table_id)); + ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id)); return (AE_BAD_PARAMETER); } #endif diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 3f96a4909aad..9fe53c9d5b9a 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,8 +75,7 @@ acpi_status acpi_load_tables(void) status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, &rsdp_address); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); goto error_exit; } @@ -86,7 +85,7 @@ acpi_status acpi_load_tables(void) status = acpi_tb_verify_rsdp(&rsdp_address); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); goto error_exit; } @@ -94,7 +93,7 @@ acpi_status acpi_load_tables(void) status = acpi_tb_get_table_rsdt(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); goto error_exit; } @@ -102,7 +101,8 @@ acpi_status acpi_load_tables(void) status = acpi_tb_get_required_tables(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not get all required tables (DSDT/FADT/FACS)")); goto error_exit; } @@ -112,16 +112,14 @@ acpi_status acpi_load_tables(void) status = acpi_ns_load_namespace(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); goto error_exit; } return_ACPI_STATUS(AE_OK); error_exit: - ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n", - acpi_format_exception(status))); - + ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 3b8a7e063e8a..a62db6af83c9 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -251,7 +251,7 @@ acpi_get_firmware_table(acpi_string signature, acpi_tb_get_rsdt_address(&address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", + "RSDP located at %p, RSDT physical=%8.8X%8.8X\n", acpi_gbl_RSDP, ACPI_FORMAT_UINT64(address.pointer.value))); @@ -396,9 +396,8 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) status = acpi_tb_find_rsdp(&table_info, flags); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "RSDP structure not found, %s Flags=%X\n", - acpi_format_exception(status), flags)); + ACPI_EXCEPTION((AE_INFO, status, + "RSDP structure not found - Flags=%X", flags)); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } @@ -503,10 +502,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ACPI_EBDA_PTR_LENGTH, (void *)&table_ptr); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not map memory at %8.8X for length %X\n", - ACPI_EBDA_PTR_LOCATION, - ACPI_EBDA_PTR_LENGTH)); + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH)); return_ACPI_STATUS(status); } @@ -530,10 +529,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ACPI_EBDA_WINDOW_SIZE, (void *)&table_ptr); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not map memory at %8.8X for length %X\n", - physical_address, - ACPI_EBDA_WINDOW_SIZE)); + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + physical_address, + ACPI_EBDA_WINDOW_SIZE)); return_ACPI_STATUS(status); } @@ -563,10 +562,10 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) (void *)&table_ptr); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Could not map memory at %8.8X for length %X\n", - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE)); + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS(status); } @@ -635,7 +634,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) /* A valid RSDP was not found */ - ACPI_REPORT_ERROR(("No valid RSDP was found\n")); + ACPI_ERROR((AE_INFO, "No valid RSDP was found")); return_ACPI_STATUS(AE_NOT_FOUND); } diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile index e87108b7338a..88eff14c4894 100644 --- a/drivers/acpi/utilities/Makefile +++ b/drivers/acpi/utilities/Makefile @@ -2,7 +2,8 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ - utcopy.o utdelete.o utglobal.o utmath.o utobject.o utstate.o utmutex.o utobject.o utcache.o +obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ + utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ + utstate.o utmutex.o utobject.o utcache.o utresrc.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 068450b36475..03b0044974c2 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ ACPI_MODULE_NAME("utalloc") /* Local prototypes */ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS +#ifdef ACPI_DBG_TRACK_ALLOCATIONS static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation); static acpi_status @@ -58,9 +58,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *address, static acpi_status acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, u32 component, char *module, u32 line); -#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS static acpi_status acpi_ut_create_list(char *list_name, u16 object_size, struct acpi_memory_list **return_cache); @@ -303,8 +301,8 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) /* Check for an inadvertent size of zero bytes */ if (!size) { - _ACPI_REPORT_ERROR(module, line, component, - ("ut_allocate: Attempt to allocate zero bytes\n")); + ACPI_ERROR((module, line, + "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte")); size = 1; } @@ -312,9 +310,9 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line) if (!allocation) { /* Report allocation error */ - _ACPI_REPORT_ERROR(module, line, component, - ("ut_allocate: Could not allocate size %X\n", - (u32) size)); + ACPI_ERROR((module, line, + "ut_allocate: Could not allocate size %X", + (u32) size)); return_PTR(NULL); } @@ -346,18 +344,17 @@ void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line) /* Check for an inadvertent size of zero bytes */ if (!size) { - _ACPI_REPORT_ERROR(module, line, component, - ("ut_callocate: Attempt to allocate zero bytes\n")); - return_PTR(NULL); + ACPI_ERROR((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); + size = 1; } allocation = acpi_os_allocate(size); if (!allocation) { /* Report allocation error */ - _ACPI_REPORT_ERROR(module, line, component, - ("ut_callocate: Could not allocate size %X\n", - (u32) size)); + ACPI_ERROR((module, line, + "Could not allocate size %X", (u32) size)); return_PTR(NULL); } @@ -482,9 +479,8 @@ void *acpi_ut_callocate_and_track(acpi_size size, if (!allocation) { /* Report allocation error */ - _ACPI_REPORT_ERROR(module, line, component, - ("ut_callocate: Could not allocate size %X\n", - (u32) size)); + ACPI_ERROR((module, line, + "Could not allocate size %X", (u32) size)); return (NULL); } @@ -526,8 +522,7 @@ acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line) ACPI_FUNCTION_TRACE_PTR("ut_free", allocation); if (NULL == allocation) { - _ACPI_REPORT_ERROR(module, line, component, - ("acpi_ut_free: Attempt to delete a NULL address\n")); + ACPI_ERROR((module, line, "Attempt to delete a NULL address")); return_VOID; } @@ -542,14 +537,11 @@ acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line) status = acpi_ut_remove_allocation(debug_block, component, module, line); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not free memory, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); } acpi_os_free(debug_block); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); - return_VOID; } @@ -626,10 +618,12 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, */ element = acpi_ut_find_allocation(allocation); if (element) { - ACPI_REPORT_ERROR(("ut_track_allocation: Allocation already present in list! (%p)\n", allocation)); + ACPI_ERROR((AE_INFO, + "ut_track_allocation: Allocation already present in list! (%p)", + allocation)); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Element %p Address %p\n", - element, allocation)); + ACPI_ERROR((AE_INFO, "Element %p Address %p", + element, allocation)); goto unlock_and_exit; } @@ -689,8 +683,8 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, if (NULL == mem_list->list_head) { /* No allocations! */ - _ACPI_REPORT_ERROR(module, line, component, - ("ut_remove_allocation: Empty allocation list, nothing to free!\n")); + ACPI_ERROR((module, line, + "Empty allocation list, nothing to free!")); return_ACPI_STATUS(AE_OK); } @@ -865,12 +859,11 @@ void acpi_ut_dump_allocations(u32 component, char *module) /* Print summary */ if (!num_outstanding) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "No outstanding allocations.\n")); + ACPI_INFO((AE_INFO, "No outstanding allocations")); } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%d(%X) Outstanding allocations\n", - num_outstanding, num_outstanding)); + ACPI_ERROR((AE_INFO, + "%d(%X) Outstanding allocations", + num_outstanding, num_outstanding)); } return_VOID; diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 93d48681d276..2177cb1ef2c4 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 5442b32de611..df2d32096b72 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -398,14 +398,17 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, * Build a simple object (no nested objects) */ status = acpi_ut_copy_isimple_to_esimple(internal_object, - (union acpi_object *) - ret_buffer->pointer, - ((u8 *) ret_buffer-> - pointer + - ACPI_ROUND_UP_TO_NATIVE_WORD - (sizeof - (union - acpi_object))), + ACPI_CAST_PTR(union + acpi_object, + ret_buffer-> + pointer), + ACPI_ADD_PTR(u8, + ret_buffer-> + pointer, + ACPI_ROUND_UP_TO_NATIVE_WORD + (sizeof + (union + acpi_object))), &ret_buffer->length); /* * build simple does not include the object size in the length @@ -603,8 +606,8 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, /* * Packages as external input to control methods are not supported, */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Packages as parameters not implemented!\n")); + ACPI_ERROR((AE_INFO, + "Packages as parameters not implemented!")); return_ACPI_STATUS(AE_NOT_IMPLEMENTED); } @@ -867,7 +870,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, count + 1) * sizeof(void *)); if (!dest_obj->package.elements) { - ACPI_REPORT_ERROR(("aml_build_copy_internal_package_object: Package allocation failure\n")); + ACPI_ERROR((AE_INFO, "Package allocation failure")); return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index d80e92639932..35f3d581e034 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 2bc878f7a127..1db9695b0029 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -363,8 +363,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown action (%X)\n", - action)); + ACPI_ERROR((AE_INFO, "Unknown action (%X)", action)); break; } @@ -374,9 +373,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) */ if (count > ACPI_MAX_REFERENCE_COUNT) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "**** Warning **** Large Reference Count (%X) in object %p\n\n", - count, object)); + ACPI_WARNING((AE_INFO, + "Large Reference Count (%X) in object %p", + count, object)); } return; @@ -535,8 +534,8 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) error_exit: - ACPI_REPORT_ERROR(("Could not update object reference count, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Could not update object reference count")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 7b81d5ef3c32..106cc97cb4af 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,7 +95,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) { if (!ACPI_STRCMP(string_desc->string.pointer, - (char *)acpi_gbl_valid_osi_strings[i])) { + ACPI_CAST_PTR(char, + acpi_gbl_valid_osi_strings[i]))) + { /* This string is supported */ return_desc->integer.value = 0xFFFFFFFF; @@ -152,8 +154,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, acpi_ut_get_node_name(prefix_node), path)); } else { - ACPI_REPORT_METHOD_ERROR("Method execution failed", - prefix_node, path, status); + ACPI_ERROR_METHOD("Method execution failed", + prefix_node, path, status); } return_ACPI_STATUS(status); @@ -163,9 +165,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, if (!info.return_object) { if (expected_return_btypes) { - ACPI_REPORT_METHOD_ERROR("No object was returned from", - prefix_node, path, - AE_NOT_EXIST); + ACPI_ERROR_METHOD("No object was returned from", + prefix_node, path, AE_NOT_EXIST); return_ACPI_STATUS(AE_NOT_EXIST); } @@ -210,15 +211,14 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, /* Is the return object one of the expected types? */ if (!(expected_return_btypes & return_btype)) { - ACPI_REPORT_METHOD_ERROR("Return object type is incorrect", - prefix_node, path, AE_TYPE); + ACPI_ERROR_METHOD("Return object type is incorrect", + prefix_node, path, AE_TYPE); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Type returned from %s was incorrect: %s, expected Btypes: %X\n", - path, - acpi_ut_get_object_type_name(info. - return_object), - expected_return_btypes)); + ACPI_ERROR((AE_INFO, + "Type returned from %s was incorrect: %s, expected Btypes: %X", + path, + acpi_ut_get_object_type_name(info.return_object), + expected_return_btypes)); /* On error exit, we must delete the return object */ @@ -592,7 +592,7 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) "_STA on %4.4s was not found, assuming device is present\n", acpi_ut_get_node_name(device_node))); - *flags = 0x0F; + *flags = ACPI_UINT32_MAX; status = AE_OK; } @@ -637,17 +637,17 @@ acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) for (i = 0; i < 4; i++) { highest[i] = 0xFF; status = acpi_ut_evaluate_object(device_node, - (char *) - acpi_gbl_highest_dstate_names - [i], ACPI_BTYPE_INTEGER, - &obj_desc); + ACPI_CAST_PTR(char, + acpi_gbl_highest_dstate_names + [i]), + ACPI_BTYPE_INTEGER, &obj_desc); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s on Device %4.4s, %s\n", - (char *) - acpi_gbl_highest_dstate_names - [i], + ACPI_CAST_PTR(char, + acpi_gbl_highest_dstate_names + [i]), acpi_ut_get_node_name (device_node), acpi_format_exception diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 399e64b51886..ffd13383a325 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,8 +67,11 @@ const char *acpi_format_exception(acpi_status status) acpi_status sub_status; const char *exception = NULL; - ACPI_FUNCTION_NAME("format_exception"); + ACPI_FUNCTION_ENTRY(); + /* + * Status is composed of two parts, a "type" and an actual code + */ sub_status = (status & ~AE_CODE_MASK); switch (status & AE_CODE_MASK) { @@ -118,13 +121,13 @@ const char *acpi_format_exception(acpi_status status) if (!exception) { /* Exception code was not recognized */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unknown exception code: 0x%8.8X\n", status)); + ACPI_ERROR((AE_INFO, + "Unknown exception code: 0x%8.8X", status)); - return ((const char *)"UNKNOWN_STATUS_CODE"); + exception = "UNKNOWN_STATUS_CODE"; } - return ((const char *)exception); + return (ACPI_CAST_PTR(const char, exception)); } /******************************************************************************* @@ -217,23 +220,23 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to * perform a Notify() operation on it. */ -const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = - { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, -{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, -{"_SB_", ACPI_TYPE_DEVICE, NULL}, -{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, -{"_TZ_", ACPI_TYPE_THERMAL, NULL}, -{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, -{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, -{"_GL_", ACPI_TYPE_MUTEX, (char *)1}, +const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { + {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_SB_", ACPI_TYPE_DEVICE, NULL}, + {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_TZ_", ACPI_TYPE_THERMAL, NULL}, + {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) -{"_OSI", ACPI_TYPE_METHOD, (char *)1}, + {"_OSI", ACPI_TYPE_METHOD, (char *)1}, #endif /* Table terminator */ -{NULL, ACPI_TYPE_ANY, NULL} + {NULL, ACPI_TYPE_ANY, NULL} }; /* @@ -485,7 +488,7 @@ char *acpi_ut_get_region_name(u8 space_id) return ("invalid_space_id"); } - return ((char *)acpi_gbl_region_types[space_id]); + return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); } /******************************************************************************* @@ -503,11 +506,13 @@ char *acpi_ut_get_region_name(u8 space_id) /* Event type decoding */ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { +/*! [Begin] no source code translation (keep these strings as-is) */ "PM_Timer", - "global_lock", - "power_button", - "sleep_button", - "real_time_clock", + "GlobalLock", + "PowerButton", + "SleepButton", + "RealTimeClock", +/*! [End] no source code translation !*/ }; char *acpi_ut_get_event_name(u32 event_id) @@ -517,7 +522,7 @@ char *acpi_ut_get_event_name(u32 event_id) return ("invalid_event_iD"); } - return ((char *)acpi_gbl_event_types[event_id]); + return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); } /******************************************************************************* @@ -545,12 +550,13 @@ static const char acpi_gbl_bad_type[] = "UNDEFINED"; /* Printable names of the ACPI object types */ static const char *acpi_gbl_ns_type_names[] = { +/*! [Begin] no source code translation (keep these strings as-is) */ /* 00 */ "Untyped", /* 01 */ "Integer", /* 02 */ "String", /* 03 */ "Buffer", /* 04 */ "Package", - /* 05 */ "field_unit", + /* 05 */ "FieldUnit", /* 06 */ "Device", /* 07 */ "Event", /* 08 */ "Method", @@ -559,33 +565,34 @@ static const char *acpi_gbl_ns_type_names[] = { /* 11 */ "Power", /* 12 */ "Processor", /* 13 */ "Thermal", - /* 14 */ "buffer_field", - /* 15 */ "ddb_handle", - /* 16 */ "debug_object", - /* 17 */ "region_field", - /* 18 */ "bank_field", - /* 19 */ "index_field", + /* 14 */ "BufferField", + /* 15 */ "DdbHandle", + /* 16 */ "DebugObject", + /* 17 */ "RegionField", + /* 18 */ "BankField", + /* 19 */ "IndexField", /* 20 */ "Reference", /* 21 */ "Alias", - /* 22 */ "method_alias", + /* 22 */ "MethodAlias", /* 23 */ "Notify", - /* 24 */ "addr_handler", - /* 25 */ "resource_desc", - /* 26 */ "resource_fld", + /* 24 */ "AddrHandler", + /* 25 */ "ResourceDesc", + /* 26 */ "ResourceFld", /* 27 */ "Scope", /* 28 */ "Extra", /* 29 */ "Data", /* 30 */ "Invalid" +/*! [End] no source code translation !*/ }; char *acpi_ut_get_type_name(acpi_object_type type) { if (type > ACPI_TYPE_INVALID) { - return ((char *)acpi_gbl_bad_type); + return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); } - return ((char *)acpi_gbl_ns_type_names[type]); + return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type])); } char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) @@ -634,7 +641,7 @@ char *acpi_ut_get_node_name(void *object) /* Name must be a valid ACPI name */ - if (!acpi_ut_valid_acpi_name(*(u32 *) node->name.ascii)) { + if (!acpi_ut_valid_acpi_name(node->name.integer)) { return ("????"); } @@ -658,15 +665,16 @@ char *acpi_ut_get_node_name(void *object) /* Printable names of object descriptor types */ static const char *acpi_gbl_desc_type_names[] = { +/*! [Begin] no source code translation (keep these ASL Keywords as-is) */ /* 00 */ "Invalid", /* 01 */ "Cached", /* 02 */ "State-Generic", /* 03 */ "State-Update", /* 04 */ "State-Package", /* 05 */ "State-Control", - /* 06 */ "State-root_parse_scope", - /* 07 */ "State-parse_scope", - /* 08 */ "State-walk_scope", + /* 06 */ "State-RootParseScope", + /* 07 */ "State-ParseScope", + /* 08 */ "State-WalkScope", /* 09 */ "State-Result", /* 10 */ "State-Notify", /* 11 */ "State-Thread", @@ -674,6 +682,7 @@ static const char *acpi_gbl_desc_type_names[] = { /* 13 */ "Parser", /* 14 */ "Operand", /* 15 */ "Node" +/*! [End] no source code translation !*/ }; char *acpi_ut_get_descriptor_name(void *object) @@ -684,11 +693,12 @@ char *acpi_ut_get_descriptor_name(void *object) } if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) { - return ((char *)acpi_gbl_bad_type); + return (ACPI_CAST_PTR(char, acpi_gbl_bad_type)); } - return ((char *) - acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]); + return (ACPI_CAST_PTR(char, + acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE + (object)])); } @@ -787,6 +797,11 @@ void acpi_ut_init_globals(void) acpi_gbl_mutex_info[i].use_count = 0; } + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { + acpi_gbl_owner_id_mask[i] = 0; + } + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ + /* GPE support */ acpi_gbl_gpe_xrupt_list_head = NULL; @@ -824,7 +839,11 @@ void acpi_ut_init_globals(void) acpi_gbl_ns_lookup_count = 0; acpi_gbl_ps_find_count = 0; acpi_gbl_acpi_hardware_present = TRUE; - acpi_gbl_owner_id_mask = 0; + acpi_gbl_last_owner_id_index = 0; + acpi_gbl_next_owner_id_offset = 0; + acpi_gbl_trace_method_name = 0; + acpi_gbl_trace_dbg_level = 0; + acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; @@ -836,7 +855,6 @@ void acpi_ut_init_globals(void) /* Namespace */ acpi_gbl_root_node = NULL; - acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED; acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index 9dde82b0beaf..ba771b4f39bc 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,9 +72,9 @@ static void acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset) { - ACPI_REPORT_WARNING(("Invalid FADT value %s=%X at offset %X FADT=%p\n", - register_name, value, (u32) offset, - acpi_gbl_FADT)); + ACPI_WARNING((AE_INFO, + "Invalid FADT value %s=%X at offset %X FADT=%p", + register_name, value, (u32) offset, acpi_gbl_FADT)); } /****************************************************************************** @@ -221,15 +221,14 @@ void acpi_ut_subsystem_shutdown(void) /* Just exit if subsystem is already shutdown */ if (acpi_gbl_shutdown) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "ACPI Subsystem is already terminated\n")); + ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); return_VOID; } /* Subsystem appears active, go ahead and shut it down */ acpi_gbl_shutdown = TRUE; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem...\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); /* Close the acpi_event Handling */ diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 68a0a6f94129..4a3360484e72 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -82,7 +82,7 @@ acpi_ut_short_divide(acpi_integer dividend, /* Always check for a zero divisor */ if (divisor == 0) { - ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n")); + ACPI_ERROR((AE_INFO, "Divide by zero")); return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); } @@ -144,7 +144,7 @@ acpi_ut_divide(acpi_integer in_dividend, /* Always check for a zero divisor */ if (in_divisor == 0) { - ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n")); + ACPI_ERROR((AE_INFO, "Divide by zero")); return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); } @@ -266,7 +266,7 @@ acpi_ut_short_divide(acpi_integer in_dividend, /* Always check for a zero divisor */ if (divisor == 0) { - ACPI_REPORT_ERROR(("acpi_ut_short_divide: Divide by zero\n")); + ACPI_ERROR((AE_INFO, "Divide by zero")); return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); } @@ -292,7 +292,7 @@ acpi_ut_divide(acpi_integer in_dividend, /* Always check for a zero divisor */ if (in_divisor == 0) { - ACPI_REPORT_ERROR(("acpi_ut_divide: Divide by zero\n")); + ACPI_ERROR((AE_INFO, "Divide by zero")); return_ACPI_STATUS(AE_AML_DIVIDE_BY_ZERO); } diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2ce872d75890..7364f5f8c9cd 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,6 +63,8 @@ ACPI_MODULE_NAME("utmisc") acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) { acpi_native_uint i; + acpi_native_uint j; + acpi_native_uint k; acpi_status status; ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); @@ -70,8 +72,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) /* Guard against multiple allocations of ID to the same location */ if (*owner_id) { - ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n", - *owner_id)); + ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists", + *owner_id)); return_ACPI_STATUS(AE_ALREADY_EXISTS); } @@ -82,31 +84,67 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) return_ACPI_STATUS(status); } - /* Find a free owner ID */ + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = acpi_gbl_last_owner_id_index; + i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { + if (j >= ACPI_NUM_OWNERID_MASKS) { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { + if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + /* There are no free IDs in this mask */ - for (i = 0; i < 64; i++) { - if (!(acpi_gbl_owner_id_mask & (1ULL << i))) { - ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Current owner_id mask: %16.16LX New ID: %2.2X\n", - acpi_gbl_owner_id_mask, - (unsigned int)(i + 1))); + break; + } - acpi_gbl_owner_id_mask |= (1ULL << i); - *owner_id = (acpi_owner_id) (i + 1); - goto exit; + if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + acpi_gbl_owner_id_mask[j] |= (1 << k); + + acpi_gbl_last_owner_id_index = (u8) j; + acpi_gbl_next_owner_id_offset = (u8) (k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *owner_id = + (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); + + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, + "Allocated owner_id: %2.2X\n", + (unsigned int)*owner_id)); + goto exit; + } } + + acpi_gbl_next_owner_id_offset = 0; } /* - * If we are here, all owner_ids have been allocated. This probably should + * All owner_ids have been allocated. This typically should * not happen since the IDs are reused after deallocation. The IDs are * allocated upon table load (one per table) and method execution, and * they are released when a table is unloaded or a method completes * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. */ - *owner_id = 0; status = AE_OWNER_ID_LIMIT; - ACPI_REPORT_ERROR(("Could not allocate new owner_id (64 max), AE_OWNER_ID_LIMIT\n")); + ACPI_ERROR((AE_INFO, + "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT")); exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); @@ -123,7 +161,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) * control method or unloading a table. Either way, we would * ignore any error anyway. * - * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 64 + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 * ******************************************************************************/ @@ -131,6 +169,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) { acpi_owner_id owner_id = *owner_id_ptr; acpi_status status; + acpi_native_uint index; + u32 bit; ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); @@ -140,8 +180,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) /* Zero is not a valid owner_iD */ - if ((owner_id == 0) || (owner_id > 64)) { - ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); + if (owner_id == 0) { + ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id)); return_VOID; } @@ -156,10 +196,19 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) owner_id--; + /* Decode ID to index/offset pair */ + + index = ACPI_DIV_32(owner_id); + bit = 1 << ACPI_MOD_32(owner_id); + /* Free the owner ID only if it is valid */ - if (acpi_gbl_owner_id_mask & (1ULL << owner_id)) { - acpi_gbl_owner_id_mask ^= (1ULL << owner_id); + if (acpi_gbl_owner_id_mask[index] & bit) { + acpi_gbl_owner_id_mask[index] ^= bit; + } else { + ACPI_ERROR((AE_INFO, + "Release of non-allocated owner_id: %2.2X", + owner_id + 1)); } (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); @@ -790,109 +839,97 @@ u8 acpi_ut_generate_checksum(u8 * buffer, u32 length) /******************************************************************************* * - * FUNCTION: acpi_ut_get_resource_end_tag + * FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info * - * PARAMETERS: obj_desc - The resource template buffer object + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * Format - Printf format string + additional args * - * RETURN: Pointer to the end tag + * RETURN: None * - * DESCRIPTION: Find the END_TAG resource descriptor in a resource template + * DESCRIPTION: Print message with module/line/version info * ******************************************************************************/ -u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc) +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_error(char *module_name, u32 line_number, char *format, ...) { - u8 buffer_byte; - u8 *buffer; - u8 *end_buffer; + va_list args; - buffer = obj_desc->buffer.pointer; - end_buffer = buffer + obj_desc->buffer.length; + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); - while (buffer < end_buffer) { - buffer_byte = *buffer; - if (buffer_byte & ACPI_RDESC_TYPE_MASK) { - /* Large Descriptor - Length is next 2 bytes */ + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); +} - buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3); - } else { - /* Small Descriptor. End Tag will be found here */ +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_exception(char *module_name, + u32 line_number, acpi_status status, char *format, ...) +{ + va_list args; - if ((buffer_byte & ACPI_RDESC_SMALL_MASK) == - ACPI_RDESC_TYPE_END_TAG) { - /* Found the end tag descriptor, all done. */ + acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name, + line_number, acpi_format_exception(status)); - return (buffer); - } + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); +} - /* Length is in the header */ +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) +{ + va_list args; - buffer += ((buffer_byte & 0x07) + 1); - } - } + acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); + + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); +} + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_info(char *module_name, u32 line_number, char *format, ...) +{ + va_list args; - /* End tag not found */ + acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number); - return (NULL); + va_start(args, format); + acpi_os_vprintf(format, args); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } /******************************************************************************* * - * FUNCTION: acpi_ut_report_error + * FUNCTION: acpi_ut_report_error, Warning, Info * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) * * RETURN: None * * DESCRIPTION: Print error message * + * Note: Legacy only, should be removed when no longer used by drivers. + * ******************************************************************************/ -void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id) +void acpi_ut_report_error(char *module_name, u32 line_number) { - acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number); + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); } -/******************************************************************************* - * - * FUNCTION: acpi_ut_report_warning - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) - * - * RETURN: None - * - * DESCRIPTION: Print warning message - * - ******************************************************************************/ - -void -acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id) +void acpi_ut_report_warning(char *module_name, u32 line_number) { - acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number); + acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); } -/******************************************************************************* - * - * FUNCTION: acpi_ut_report_info - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * component_id - Caller's component ID (for error output) - * - * RETURN: None - * - * DESCRIPTION: Print information message - * - ******************************************************************************/ - -void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id) +void acpi_ut_report_info(char *module_name, u32 line_number) { - acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number); + acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number); } diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 90134c56ece9..45a7244df924 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -214,23 +214,22 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) * the ACPI subsystem code. */ for (i = mutex_id; i < MAX_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { + if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Mutex [%s] already acquired by this thread [%X]\n", - acpi_ut_get_mutex_name - (mutex_id), - this_thread_id)); + ACPI_ERROR((AE_INFO, + "Mutex [%s] already acquired by this thread [%X]", + acpi_ut_get_mutex_name + (mutex_id), + this_thread_id)); return (AE_ALREADY_ACQUIRED); } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", - this_thread_id, - acpi_ut_get_mutex_name(i), - acpi_ut_get_mutex_name - (mutex_id))); + ACPI_ERROR((AE_INFO, + "Invalid acquire order: Thread %X owns [%s], wants [%s]", + this_thread_id, + acpi_ut_get_mutex_name(i), + acpi_ut_get_mutex_name(mutex_id))); return (AE_ACQUIRE_DEADLOCK); } @@ -253,11 +252,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) acpi_gbl_mutex_info[mutex_id].use_count++; acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; } else { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Thread %X could not acquire Mutex [%s] %s\n", - this_thread_id, - acpi_ut_get_mutex_name(mutex_id), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Thread %X could not acquire Mutex [%X]", + this_thread_id, mutex_id)); } return (status); @@ -295,9 +292,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) * Mutex must be acquired in order to release it! */ if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Mutex [%s] is not acquired, cannot release\n", - acpi_ut_get_mutex_name(mutex_id))); + ACPI_ERROR((AE_INFO, + "Mutex [%X] is not acquired, cannot release", + mutex_id)); return (AE_NOT_ACQUIRED); } @@ -313,16 +310,15 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) * the ACPI subsystem code. */ for (i = mutex_id; i < MAX_MUTEX; i++) { - if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { + if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { continue; } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid release order: owns [%s], releasing [%s]\n", - acpi_ut_get_mutex_name(i), - acpi_ut_get_mutex_name - (mutex_id))); + ACPI_ERROR((AE_INFO, + "Invalid release order: owns [%s], releasing [%s]", + acpi_ut_get_mutex_name(i), + acpi_ut_get_mutex_name(mutex_id))); return (AE_RELEASE_DEADLOCK); } @@ -338,11 +334,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) acpi_os_signal_semaphore(acpi_gbl_mutex_info[mutex_id].mutex, 1); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Thread %X could not release Mutex [%s] %s\n", - this_thread_id, - acpi_ut_get_mutex_name(mutex_id), - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "Thread %X could not release Mutex [%X]", + this_thread_id, mutex_id)); } else { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 3015e1540053..7ee2d1d98071 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -177,7 +177,8 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) buffer = ACPI_MEM_CALLOCATE(buffer_size); if (!buffer) { - ACPI_REPORT_ERROR(("create_buffer: could not allocate size %X\n", (u32) buffer_size)); + ACPI_ERROR((AE_INFO, "Could not allocate size %X", + (u32) buffer_size)); acpi_ut_remove_reference(buffer_desc); return_PTR(NULL); } @@ -228,7 +229,8 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) */ string = ACPI_MEM_CALLOCATE(string_size + 1); if (!string) { - ACPI_REPORT_ERROR(("create_string: could not allocate size %X\n", (u32) string_size)); + ACPI_ERROR((AE_INFO, "Could not allocate size %X", + (u32) string_size)); acpi_ut_remove_reference(string_desc); return_PTR(NULL); } @@ -310,8 +312,8 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name, object = acpi_os_acquire_object(acpi_gbl_operand_cache); if (!object) { - _ACPI_REPORT_ERROR(module_name, line_number, component_id, - ("Could not allocate an object descriptor\n")); + ACPI_ERROR((module_name, line_number, + "Could not allocate an object descriptor")); return_PTR(NULL); } @@ -345,9 +347,9 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object) /* Object must be an union acpi_operand_object */ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "%p is not an ACPI Operand object [%s]\n", - object, acpi_ut_get_descriptor_name(object))); + ACPI_ERROR((AE_INFO, + "%p is not an ACPI Operand object [%s]", object, + acpi_ut_get_descriptor_name(object))); return_VOID; } @@ -449,10 +451,10 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * Notably, Locals and Args are not supported, but this may be * required eventually. */ - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported Reference opcode=%X in object %p\n", - internal_object->reference.opcode, - internal_object)); + ACPI_ERROR((AE_INFO, + "Unsupported Reference opcode=%X in object %p", + internal_object->reference.opcode, + internal_object)); status = AE_TYPE; break; } @@ -460,10 +462,9 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, default: - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unsupported type=%X in object %p\n", - ACPI_GET_OBJECT_TYPE(internal_object), - internal_object)); + ACPI_ERROR((AE_INFO, "Unsupported type=%X in object %p", + ACPI_GET_OBJECT_TYPE(internal_object), + internal_object)); status = AE_TYPE; break; } diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c new file mode 100644 index 000000000000..16461317113f --- /dev/null +++ b/drivers/acpi/utilities/utresrc.c @@ -0,0 +1,554 @@ +/******************************************************************************* + * + * Module Name: utresrc - Resource managment utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include <acpi/acpi.h> +#include <acpi/amlresrc.h> + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utmisc") + +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) +/* + * Strings used to decode resource descriptors. + * Used by both the disasssembler and the debugger resource dump routines + */ +const char *acpi_gbl_BMdecode[2] = { + "not_bus_master", + "bus_master" +}; + +const char *acpi_gbl_config_decode[4] = { + "0 - Good Configuration", + "1 - Acceptable Configuration", + "2 - Suboptimal Configuration", + "3 - ***Invalid Configuration***", +}; + +const char *acpi_gbl_consume_decode[2] = { + "resource_producer", + "resource_consumer" +}; + +const char *acpi_gbl_DECdecode[2] = { + "pos_decode", + "sub_decode" +}; + +const char *acpi_gbl_HEdecode[2] = { + "Level", + "Edge" +}; + +const char *acpi_gbl_io_decode[2] = { + "Decode10", + "Decode16" +}; + +const char *acpi_gbl_LLdecode[2] = { + "active_high", + "active_low" +}; + +const char *acpi_gbl_max_decode[2] = { + "max_not_fixed", + "max_fixed" +}; + +const char *acpi_gbl_MEMdecode[4] = { + "non_cacheable", + "Cacheable", + "write_combining", + "Prefetchable" +}; + +const char *acpi_gbl_min_decode[2] = { + "min_not_fixed", + "min_fixed" +}; + +const char *acpi_gbl_MTPdecode[4] = { + "address_range_memory", + "address_range_reserved", + "address_range_aCPI", + "address_range_nVS" +}; + +const char *acpi_gbl_RNGdecode[4] = { + "invalid_ranges", + "non_iSAonly_ranges", + "ISAonly_ranges", + "entire_range" +}; + +const char *acpi_gbl_RWdecode[2] = { + "read_only", + "read_write" +}; + +const char *acpi_gbl_SHRdecode[2] = { + "Exclusive", + "Shared" +}; + +const char *acpi_gbl_SIZdecode[4] = { + "Transfer8", + "Transfer8_16", + "Transfer16", + "invalid_size" +}; + +const char *acpi_gbl_TRSdecode[2] = { + "dense_translation", + "sparse_translation" +}; + +const char *acpi_gbl_TTPdecode[2] = { + "type_static", + "type_translation" +}; + +const char *acpi_gbl_TYPdecode[4] = { + "Compatibility", + "type_a", + "type_b", + "type_f" +}; + +#endif + +/* + * Base sizes of the raw AML resource descriptors, indexed by resource type. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +const u8 acpi_gbl_resource_aml_sizes[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL(struct aml_resource_irq), + ACPI_AML_SIZE_SMALL(struct aml_resource_dma), + ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent), + ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), + ACPI_AML_SIZE_SMALL(struct aml_resource_io), + ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small), + ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag), + + /* Large descriptors */ + + 0, + ACPI_AML_SIZE_LARGE(struct aml_resource_memory24), + ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register), + 0, + ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large), + ACPI_AML_SIZE_LARGE(struct aml_resource_memory32), + ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32), + ACPI_AML_SIZE_LARGE(struct aml_resource_address32), + ACPI_AML_SIZE_LARGE(struct aml_resource_address16), + ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), + ACPI_AML_SIZE_LARGE(struct aml_resource_address64), + ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) +}; + +/* + * Resource types, used to validate the resource length field. + * The length of fixed-length types must match exactly, variable + * lengths must meet the minimum required length, etc. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +static const u8 acpi_gbl_resource_types[] = { + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_SMALL_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_SMALL_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + 0, + 0, + 0, + 0, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + + /* Large descriptors */ + + 0, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + 0, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_FIXED_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_VARIABLE_LENGTH, + ACPI_FIXED_LENGTH +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_validate_resource + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * return_index - Where the resource index is returned. NULL + * if the index is not required. + * + * RETURN: Status, and optionally the Index into the global resource tables + * + * DESCRIPTION: Validate an AML resource descriptor by checking the Resource + * Type and Resource Length. Returns an index into the global + * resource information/dispatch tables for later use. + * + ******************************************************************************/ + +acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) +{ + u8 resource_type; + u8 resource_index; + acpi_rs_length resource_length; + acpi_rs_length minimum_resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* + * 1) Validate the resource_type field (Byte 0) + */ + resource_type = ACPI_GET8(aml); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + /* Verify the large resource type (name) against the max */ + + if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* + * Large Resource Type -- bits 6:0 contain the name + * Translate range 0x80-0x8B to index range 0x10-0x1B + */ + resource_index = (u8) (resource_type - 0x70); + } else { + /* + * Small Resource Type -- bits 6:3 contain the name + * Shift range to index range 0x00-0x0F + */ + resource_index = (u8) + ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); + } + + /* Check validity of the resource type, zero indicates name is invalid */ + + if (!acpi_gbl_resource_types[resource_index]) { + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* + * 2) Validate the resource_length field. This ensures that the length + * is at least reasonable, and guarantees that it is non-zero. + */ + resource_length = acpi_ut_get_resource_length(aml); + minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; + + /* Validate based upon the type of resource - fixed length or variable */ + + switch (acpi_gbl_resource_types[resource_index]) { + case ACPI_FIXED_LENGTH: + + /* Fixed length resource, length must match exactly */ + + if (resource_length != minimum_resource_length) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + case ACPI_VARIABLE_LENGTH: + + /* Variable length resource, length must be at least the minimum */ + + if (resource_length < minimum_resource_length) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + case ACPI_SMALL_VARIABLE_LENGTH: + + /* Small variable length resource, length can be (Min) or (Min-1) */ + + if ((resource_length > minimum_resource_length) || + (resource_length < (minimum_resource_length - 1))) { + return (AE_AML_BAD_RESOURCE_LENGTH); + } + break; + + default: + + /* Shouldn't happen (because of validation earlier), but be sure */ + + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Optionally return the resource table index */ + + if (return_index) { + *return_index = resource_index; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_type + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: The Resource Type with no extraneous bits (except the + * Large/Small descriptor bit -- this is left alone) + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +u8 acpi_ut_get_resource_type(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource Type -- bits 6:0 contain the name */ + + return (ACPI_GET8(aml)); + } else { + /* Small Resource Type -- bits 6:3 contain the name */ + + return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte Length + * + * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By + * definition, this does not include the size of the descriptor + * header or the length field itself. + * + ******************************************************************************/ + +u16 acpi_ut_get_resource_length(void *aml) +{ + acpi_rs_length resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); + + } else { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + resource_length = (u16) (ACPI_GET8(aml) & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + } + + return (resource_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_header_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Length of the AML header (depends on large/small descriptor) + * + * DESCRIPTION: Get the length of the header for this resource. + * + ******************************************************************************/ + +u8 acpi_ut_get_resource_header_length(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* Examine the large/small bit in the resource header */ + + if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + return (sizeof(struct aml_resource_large_header)); + } else { + return (sizeof(struct aml_resource_small_header)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_descriptor_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte length + * + * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the + * length of the descriptor header and the length field itself. + * Used to walk descriptor lists. + * + ******************************************************************************/ + +u32 acpi_ut_get_descriptor_length(void *aml) +{ + ACPI_FUNCTION_ENTRY(); + + /* + * Get the Resource Length (does not include header length) and add + * the header length (depends on if this is a small or large resource) + */ + return (acpi_ut_get_resource_length(aml) + + acpi_ut_get_resource_header_length(aml)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_get_resource_end_tag + * + * PARAMETERS: obj_desc - The resource template buffer object + * end_tag - Where the pointer to the end_tag is returned + * + * RETURN: Status, pointer to the end tag + * + * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template + * Note: allows a buffer length of zero. + * + ******************************************************************************/ + +acpi_status +acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, + u8 ** end_tag) +{ + acpi_status status; + u8 *aml; + u8 *end_aml; + + ACPI_FUNCTION_TRACE("ut_get_resource_end_tag"); + + /* Get start and end pointers */ + + aml = obj_desc->buffer.pointer; + end_aml = aml + obj_desc->buffer.length; + + /* Allow a buffer length of zero */ + + if (!obj_desc->buffer.length) { + *end_tag = aml; + return_ACPI_STATUS(AE_OK); + } + + /* Walk the resource template, one descriptor per iteration */ + + while (aml < end_aml) { + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml, NULL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* end_tag resource indicates the end of the resource template */ + + if (acpi_ut_get_resource_type(aml) == + ACPI_RESOURCE_NAME_END_TAG) { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the end_tag + */ + if ((aml + 1) >= end_aml) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the end_tag */ + + *end_tag = aml; + return_ACPI_STATUS(AE_OK); + } + + /* + * Point to the next resource descriptor in the AML buffer. The + * descriptor length is guaranteed to be non-zero by resource + * validation above. + */ + aml += acpi_ut_get_descriptor_length(aml); + } + + /* Did not find an end_tag resource descriptor */ + + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); +} diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index c1cb27583be8..4b134a722907 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,7 +63,7 @@ acpi_status acpi_ut_create_pkg_state_and_push(void *internal_object, void *external_object, u16 index, - union acpi_generic_state ** state_list) + union acpi_generic_state **state_list) { union acpi_generic_state *state; diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index f06bd5e5e9d1..308a960871be 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,8 +75,7 @@ acpi_status acpi_initialize_subsystem(void) status = acpi_os_initialize(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("OSD failed to initialize, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); return_ACPI_STATUS(status); } @@ -88,8 +87,8 @@ acpi_status acpi_initialize_subsystem(void) status = acpi_ut_mutex_initialize(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Global mutex creation failure, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "During Global Mutex creation")); return_ACPI_STATUS(status); } @@ -99,15 +98,14 @@ acpi_status acpi_initialize_subsystem(void) */ status = acpi_ns_root_initialize(); if (ACPI_FAILURE(status)) { - ACPI_REPORT_ERROR(("Namespace initialization failure, %s\n", - acpi_format_exception(status))); + ACPI_EXCEPTION((AE_INFO, status, + "During Namespace initialization")); return_ACPI_STATUS(status); } /* If configured, initialize the AML debugger */ ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); - return_ACPI_STATUS(status); } @@ -154,8 +152,7 @@ acpi_status acpi_enable_subsystem(u32 flags) status = acpi_enable(); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, - "acpi_enable failed.\n")); + ACPI_WARNING((AE_INFO, "acpi_enable failed")); return_ACPI_STATUS(status); } } @@ -178,10 +175,14 @@ acpi_status acpi_enable_subsystem(u32 flags) /* * Initialize ACPI Event handling (Fixed and General Purpose) * - * NOTE: We must have the hardware AND events initialized before we can - * execute ANY control methods SAFELY. Any control method can require - * ACPI hardware support, so the hardware MUST be initialized before - * execution! + * Note1: We must have the hardware and events initialized before we can + * execute any control methods safely. Any control method can require + * ACPI hardware support, so the hardware must be fully initialized before + * any method execution! + * + * Note2: Fixed events are initialized and enabled here. GPEs are + * initialized, but cannot be enabled until after the hardware is + * completely initialized (SCI and global_lock activated) */ if (!(flags & ACPI_NO_EVENT_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -193,8 +194,10 @@ acpi_status acpi_enable_subsystem(u32 flags) } } - /* Install the SCI handler and Global Lock handler */ - + /* + * Install the SCI handler and Global Lock handler. This completes the + * hardware initialization. + */ if (!(flags & ACPI_NO_HANDLER_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n")); @@ -205,6 +208,24 @@ acpi_status acpi_enable_subsystem(u32 flags) } } + /* + * Complete the GPE initialization for the GPE blocks defined in the FADT + * (GPE block 0 and 1). + * + * Note1: This is where the _PRW methods are executed for the GPEs. These + * methods can only be executed after the SCI and Global Lock handlers are + * installed and initialized. + * + * Note2: Currently, there seems to be no need to run the _REG methods + * before execution of the _PRW methods and enabling of the GPEs. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_install_fadt_gpes(); + if (ACPI_FAILURE(status)) { + return (status); + } + } + return_ACPI_STATUS(status); } @@ -230,9 +251,9 @@ acpi_status acpi_initialize_objects(u32 flags) /* * Run all _REG methods * - * NOTE: Any objects accessed - * by the _REG methods will be automatically initialized, even if they - * contain executable AML (see call to acpi_ns_initialize_objects below). + * Note: Any objects accessed by the _REG methods will be automatically + * initialized, even if they contain executable AML (see the call to + * acpi_ns_initialize_objects below). */ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -245,9 +266,9 @@ acpi_status acpi_initialize_objects(u32 flags) } /* - * Initialize the objects that remain uninitialized. This - * runs the executable AML that may be part of the declaration of these - * objects: operation_regions, buffer_fields, Buffers, and Packages. + * Initialize the objects that remain uninitialized. This runs the + * executable AML that may be part of the declaration of these objects: + * operation_regions, buffer_fields, Buffers, and Packages. */ if (!(flags & ACPI_NO_OBJECT_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -260,8 +281,8 @@ acpi_status acpi_initialize_objects(u32 flags) } /* - * Initialize all device objects in the namespace - * This runs the _STA and _INI methods. + * Initialize all device objects in the namespace. This runs the device + * _STA and _INI methods. */ if (!(flags & ACPI_NO_DEVICE_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d10668f14699..bd4887518373 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -920,8 +920,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'state' fs entry\n")); else { + acpi_video_device_state_fops.write = acpi_video_device_write_state; entry->proc_fops = &acpi_video_device_state_fops; - entry->proc_fops->write = acpi_video_device_write_state; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -934,8 +934,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'brightness' fs entry\n")); else { + acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness; entry->proc_fops = &acpi_video_device_brightness_fops; - entry->proc_fops->write = acpi_video_device_write_brightness; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -1239,8 +1239,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST' fs entry\n")); else { + acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; entry->proc_fops = &acpi_video_bus_POST_fops; - entry->proc_fops->write = acpi_video_bus_write_POST; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -1253,8 +1253,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'DOS' fs entry\n")); else { + acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; entry->proc_fops = &acpi_video_bus_DOS_fops; - entry->proc_fops->write = acpi_video_bus_write_DOS; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f12898d53078..e99471d3232b 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -8,6 +8,7 @@ obj-y += power/ obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o +obj-$(CONFIG_SMP) += topology.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/base/base.h b/drivers/base/base.h index e3b548d46cff..5735b38582d0 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *); extern void driver_detach(struct device_driver * drv); extern int driver_probe_device(struct device_driver *, struct device *); +extern void sysdev_shutdown(void); +extern int sysdev_suspend(pm_message_t state); +extern int sysdev_resume(void); + static inline struct class_device *to_class_dev(struct kobject *obj) { return container_of(obj, struct class_device, kobj); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 29f6af554e71..c3141565d59d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -133,6 +133,8 @@ static struct kobj_type ktype_bus = { decl_subsys(bus, &ktype_bus, NULL); +#ifdef CONFIG_HOTPLUG + /* Manually detach a device from its associated driver. */ static int driver_helper(struct device *dev, void *data) { @@ -193,6 +195,7 @@ static ssize_t driver_bind(struct device_driver *drv, } static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); +#endif static struct device * next_device(struct klist_iter * i) { diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d1a05224627e..105a0d61eb1f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -303,7 +303,7 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct class *class, const char __user *buf, size_t count) +memory_probe_store(struct class *class, const char *buf, size_t count) { u64 phys_addr; int ret; diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 0a7aa07b9a2a..317edbf0feca 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -9,10 +9,9 @@ */ #include <linux/device.h> +#include "../base.h" #include "power.h" -extern int sysdev_resume(void); - /** * resume_device - Restore state for one device. diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index c2475f3134ea..8826a5b6673e 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -12,6 +12,7 @@ #include <linux/device.h> #include <asm/semaphore.h> +#include "../base.h" #include "power.h" #define to_dev(node) container_of(node, struct device, kobj.entry) @@ -28,7 +29,6 @@ extern struct subsystem devices_subsys; * they only get one called once when interrupts are disabled. */ -extern int sysdev_shutdown(void); /** * device_shutdown - call ->shutdown() on each device to shutdown. diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 50501764d050..8660779fb288 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -9,10 +9,9 @@ */ #include <linux/device.h> +#include "../base.h" #include "power.h" -extern int sysdev_suspend(pm_message_t state); - /* * The entries in the dpm_active list are in a depth first order, simply * because children are guaranteed to be discovered after parents, and diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index f3a0c562bcb5..40d7242a07c1 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -27,22 +27,30 @@ static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) { - return sprintf(buf, "%u\n", dev->power.power_state.event); + if (dev->power.power_state.event) + return sprintf(buf, "2\n"); + else + return sprintf(buf, "0\n"); } static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) { pm_message_t state; - char * rest; - int error = 0; + int error = -EINVAL; - state.event = simple_strtoul(buf, &rest, 10); - if (*rest) - return -EINVAL; - if (state.event) + state.event = PM_EVENT_SUSPEND; + /* Older apps expected to write "3" here - confused with PCI D3 */ + if ((n == 1) && !strcmp(buf, "3")) error = dpm_runtime_suspend(dev, state); - else + + if ((n == 1) && !strcmp(buf, "2")) + error = dpm_runtime_suspend(dev, state); + + if ((n == 1) && !strcmp(buf, "0")) { dpm_runtime_resume(dev); + error = 0; + } + return error ? error : n; } diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 66ed8f2fece5..6fc23ab127bd 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -21,8 +21,11 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/pm.h> +#include <linux/device.h> #include <asm/semaphore.h> +#include "base.h" + extern struct subsystem devices_subsys; #define to_sysdev(k) container_of(k, struct sys_device, kobj) diff --git a/drivers/base/topology.c b/drivers/base/topology.c new file mode 100644 index 000000000000..915810f6237e --- /dev/null +++ b/drivers/base/topology.c @@ -0,0 +1,148 @@ +/* + * driver/base/topology.c - Populate sysfs with cpu topology information + * + * Written by: Zhang Yanmin, Intel Corporation + * + * Copyright (C) 2006, Intel Corp. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include <linux/sysdev.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/cpu.h> +#include <linux/module.h> +#include <linux/topology.h> + +#define define_one_ro(_name) \ +static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) + +#define define_id_show_func(name) \ +static ssize_t show_##name(struct sys_device *dev, char *buf) \ +{ \ + unsigned int cpu = dev->id; \ + return sprintf(buf, "%d\n", topology_##name(cpu)); \ +} + +#define define_siblings_show_func(name) \ +static ssize_t show_##name(struct sys_device *dev, char *buf) \ +{ \ + ssize_t len = -1; \ + unsigned int cpu = dev->id; \ + len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \ + return (len + sprintf(buf + len, "\n")); \ +} + +#ifdef topology_physical_package_id +define_id_show_func(physical_package_id); +define_one_ro(physical_package_id); +#define ref_physical_package_id_attr &attr_physical_package_id.attr, +#else +#define ref_physical_package_id_attr +#endif + +#ifdef topology_core_id +define_id_show_func(core_id); +define_one_ro(core_id); +#define ref_core_id_attr &attr_core_id.attr, +#else +#define ref_core_id_attr +#endif + +#ifdef topology_thread_siblings +define_siblings_show_func(thread_siblings); +define_one_ro(thread_siblings); +#define ref_thread_siblings_attr &attr_thread_siblings.attr, +#else +#define ref_thread_siblings_attr +#endif + +#ifdef topology_core_siblings +define_siblings_show_func(core_siblings); +define_one_ro(core_siblings); +#define ref_core_siblings_attr &attr_core_siblings.attr, +#else +#define ref_core_siblings_attr +#endif + +static struct attribute *default_attrs[] = { + ref_physical_package_id_attr + ref_core_id_attr + ref_thread_siblings_attr + ref_core_siblings_attr + NULL +}; + +static struct attribute_group topology_attr_group = { + .attrs = default_attrs, + .name = "topology" +}; + +/* Add/Remove cpu_topology interface for CPU device */ +static int __cpuinit topology_add_dev(struct sys_device * sys_dev) +{ + sysfs_create_group(&sys_dev->kobj, &topology_attr_group); + return 0; +} + +static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) +{ + sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); + return 0; +} + +static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + struct sys_device *sys_dev; + + sys_dev = get_cpu_sysdev(cpu); + switch (action) { + case CPU_ONLINE: + topology_add_dev(sys_dev); + break; + case CPU_DEAD: + topology_remove_dev(sys_dev); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block topology_cpu_notifier = +{ + .notifier_call = topology_cpu_callback, +}; + +static int __cpuinit topology_sysfs_init(void) +{ + int i; + + for_each_online_cpu(i) { + topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, + (void *)(long)i); + } + + register_cpu_notifier(&topology_cpu_notifier); + + return 0; +} + +device_initcall(topology_sysfs_init); + diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 139cbba76180..8b1331677407 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -433,12 +433,12 @@ config CDROM_PKTCDVD_BUFFERS This controls the maximum number of active concurrent packets. More concurrent packets can increase write performance, but also require more memory. Each concurrent packet will require approximately 64Kb - of non-swappable kernel memory, memory which will be allocated at - pktsetup time. + of non-swappable kernel memory, memory which will be allocated when + a disc is opened for writing. config CDROM_PKTCDVD_WCACHE - bool "Enable write caching" - depends on CDROM_PKTCDVD + bool "Enable write caching (EXPERIMENTAL)" + depends on CDROM_PKTCDVD && EXPERIMENTAL help If enabled, write caching will be set for the CD-R/W device. For now this option is dangerous unless the CD-RW media is known good, as we diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 12d7b9bdfa93..0d65394707db 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2183,6 +2183,7 @@ static void cciss_softirq_done(struct request *rq) { CommandList_struct *cmd = rq->completion_data; ctlr_info_t *h = hba[cmd->ctlr]; + unsigned long flags; u64bit temp64; int i, ddir; @@ -2205,10 +2206,10 @@ static void cciss_softirq_done(struct request *rq) printk("Done with %p\n", rq); #endif /* CCISS_DEBUG */ - spin_lock_irq(&h->lock); + spin_lock_irqsave(&h->lock, flags); end_that_request_last(rq, rq->errors); cmd_free(h, cmd,1); - spin_unlock_irq(&h->lock); + spin_unlock_irqrestore(&h->lock, flags); } /* checks the status of the job and calls complete buffers to mark all diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 93affeeef7bd..4e7dbcc425ff 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -43,8 +43,6 @@ * *************************************************************************/ -#define VERSION_CODE "v0.2.0a 2004-07-14 Jens Axboe (axboe@suse.de) and petero2@telia.com" - #include <linux/pktcdvd.h> #include <linux/config.h> #include <linux/module.h> @@ -131,7 +129,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs) /* * Allocate a packet_data struct */ -static struct packet_data *pkt_alloc_packet_data(void) +static struct packet_data *pkt_alloc_packet_data(int frames) { int i; struct packet_data *pkt; @@ -140,11 +138,12 @@ static struct packet_data *pkt_alloc_packet_data(void) if (!pkt) goto no_pkt; - pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); + pkt->frames = frames; + pkt->w_bio = pkt_bio_alloc(frames); if (!pkt->w_bio) goto no_bio; - for (i = 0; i < PAGES_PER_PACKET; i++) { + for (i = 0; i < frames / FRAMES_PER_PAGE; i++) { pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); if (!pkt->pages[i]) goto no_page; @@ -152,7 +151,7 @@ static struct packet_data *pkt_alloc_packet_data(void) spin_lock_init(&pkt->lock); - for (i = 0; i < PACKET_MAX_SIZE; i++) { + for (i = 0; i < frames; i++) { struct bio *bio = pkt_bio_alloc(1); if (!bio) goto no_rd_bio; @@ -162,14 +161,14 @@ static struct packet_data *pkt_alloc_packet_data(void) return pkt; no_rd_bio: - for (i = 0; i < PACKET_MAX_SIZE; i++) { + for (i = 0; i < frames; i++) { struct bio *bio = pkt->r_bios[i]; if (bio) bio_put(bio); } no_page: - for (i = 0; i < PAGES_PER_PACKET; i++) + for (i = 0; i < frames / FRAMES_PER_PAGE; i++) if (pkt->pages[i]) __free_page(pkt->pages[i]); bio_put(pkt->w_bio); @@ -186,12 +185,12 @@ static void pkt_free_packet_data(struct packet_data *pkt) { int i; - for (i = 0; i < PACKET_MAX_SIZE; i++) { + for (i = 0; i < pkt->frames; i++) { struct bio *bio = pkt->r_bios[i]; if (bio) bio_put(bio); } - for (i = 0; i < PAGES_PER_PACKET; i++) + for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++) __free_page(pkt->pages[i]); bio_put(pkt->w_bio); kfree(pkt); @@ -206,17 +205,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd) list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { pkt_free_packet_data(pkt); } + INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); } static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) { struct packet_data *pkt; - INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); - INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); - spin_lock_init(&pd->cdrw.active_list_lock); + BUG_ON(!list_empty(&pd->cdrw.pkt_free_list)); + while (nr_packets > 0) { - pkt = pkt_alloc_packet_data(); + pkt = pkt_alloc_packet_data(pd->settings.size >> 2); if (!pkt) { pkt_shrink_pktlist(pd); return 0; @@ -951,7 +950,7 @@ try_next_bio: pd->current_sector = zone + pd->settings.size; pkt->sector = zone; - pkt->frames = pd->settings.size >> 2; + BUG_ON(pkt->frames != pd->settings.size >> 2); pkt->write_size = 0; /* @@ -1639,7 +1638,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2; if (pd->settings.size == 0) { printk("pktcdvd: detected zero packet size!\n"); - pd->settings.size = 128; + return -ENXIO; } if (pd->settings.size > PACKET_MAX_SECTORS) { printk("pktcdvd: packet size is too big\n"); @@ -1987,8 +1986,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) if ((ret = pkt_set_segment_merging(pd, q))) goto out_unclaim; - if (write) + if (write) { + if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { + printk("pktcdvd: not enough memory for buffers\n"); + ret = -ENOMEM; + goto out_unclaim; + } printk("pktcdvd: %lukB available on disc\n", lba << 1); + } return 0; @@ -2014,6 +2019,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); bd_release(pd->bdev); blkdev_put(pd->bdev); + + pkt_shrink_pktlist(pd); } static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) @@ -2379,12 +2386,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) /* This is safe, since we have a reference from open(). */ __module_get(THIS_MODULE); - if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { - printk("pktcdvd: not enough memory for buffers\n"); - ret = -ENOMEM; - goto out_mem; - } - pd->bdev = bdev; set_blocksize(bdev, CD_FRAMESIZE); @@ -2395,7 +2396,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) if (IS_ERR(pd->cdrw.thread)) { printk("pktcdvd: can't start kernel thread\n"); ret = -ENOMEM; - goto out_thread; + goto out_mem; } proc = create_proc_entry(pd->name, 0, pkt_proc); @@ -2406,8 +2407,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b)); return 0; -out_thread: - pkt_shrink_pktlist(pd); out_mem: blkdev_put(bdev); /* This is safe: open() is still holding a reference. */ @@ -2503,6 +2502,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) goto out_mem; pd->disk = disk; + INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); + INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); + spin_lock_init(&pd->cdrw.active_list_lock); + spin_lock_init(&pd->lock); spin_lock_init(&pd->iosched.lock); sprintf(pd->name, "pktcdvd%d", idx); @@ -2567,8 +2570,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) blkdev_put(pd->bdev); - pkt_shrink_pktlist(pd); - remove_proc_entry(pd->name, pkt_proc); DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); @@ -2678,7 +2679,6 @@ static int __init pkt_init(void) pkt_proc = proc_mkdir("pktcdvd", proc_root_driver); - DPRINTK("pktcdvd: %s\n", VERSION_CODE); return 0; out: diff --git a/drivers/block/ub.c b/drivers/block/ub.c index a05fe5843e6c..f04d864770ad 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -14,7 +14,6 @@ * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries * -- verify the 13 conditions and do bulk resets * -- kill last_pipe and simply do two-state clearing on both pipes - * -- verify protocol (bulk) from USB descriptors (maybe...) * -- highmem * -- move top_sense and work_bcs into separate allocations (if they survive) * for cache purists and esoteric architectures. @@ -355,7 +354,7 @@ struct ub_lun { * The USB device instance. */ struct ub_dev { - spinlock_t lock; + spinlock_t *lock; atomic_t poison; /* The USB device is disconnected */ int openc; /* protected by ub_lock! */ /* kref is too implicit for our taste */ @@ -420,11 +419,13 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe); static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); -static void ub_reset_enter(struct ub_dev *sc); +static void ub_reset_enter(struct ub_dev *sc, int try); static void ub_reset_task(void *arg); static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret); +static int ub_sync_reset(struct ub_dev *sc); +static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe); static int ub_probe_lun(struct ub_dev *sc, int lnum); /* @@ -452,6 +453,10 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids); #define UB_MAX_HOSTS 26 static char ub_hostv[UB_MAX_HOSTS]; +#define UB_QLOCK_NUM 5 +static spinlock_t ub_qlockv[UB_QLOCK_NUM]; +static int ub_qlock_next = 0; + static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ /* @@ -531,7 +536,7 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, return 0; cnt = 0; - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); cnt += sprintf(page + cnt, "poison %d reset %d\n", @@ -579,7 +584,7 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, if (++nc == SCMD_TRACE_SZ) nc = 0; } - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); return cnt; } @@ -627,6 +632,24 @@ static void ub_id_put(int id) } /* + * This is necessitated by the fact that blk_cleanup_queue does not + * necesserily destroy the queue. Instead, it may merely decrease q->refcnt. + * Since our blk_init_queue() passes a spinlock common with ub_dev, + * we have life time issues when ub_cleanup frees ub_dev. + */ +static spinlock_t *ub_next_lock(void) +{ + unsigned long flags; + spinlock_t *ret; + + spin_lock_irqsave(&ub_lock, flags); + ret = &ub_qlockv[ub_qlock_next]; + ub_qlock_next = (ub_qlock_next + 1) % UB_QLOCK_NUM; + spin_unlock_irqrestore(&ub_lock, flags); + return ret; +} + +/* * Downcount for deallocation. This rides on two assumptions: * - once something is poisoned, its refcount cannot grow * - opens cannot happen at this time (del_gendisk was done) @@ -961,7 +984,7 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, if (atomic_read(&sc->poison)) return -ENXIO; - ub_reset_enter(sc); + ub_reset_enter(sc, urq->current_try); if (urq->current_try >= 3) return -EIO; @@ -997,8 +1020,6 @@ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, * No exceptions. * * Host is assumed locked. - * - * XXX We only support Bulk for the moment. */ static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { @@ -1083,9 +1104,10 @@ static void ub_urb_timeout(unsigned long arg) struct ub_dev *sc = (struct ub_dev *) arg; unsigned long flags; - spin_lock_irqsave(&sc->lock, flags); - usb_unlink_urb(&sc->work_urb); - spin_unlock_irqrestore(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); + if (!ub_is_completed(&sc->work_done)) + usb_unlink_urb(&sc->work_urb); + spin_unlock_irqrestore(sc->lock, flags); } /* @@ -1108,10 +1130,9 @@ static void ub_scsi_action(unsigned long _dev) struct ub_dev *sc = (struct ub_dev *) _dev; unsigned long flags; - spin_lock_irqsave(&sc->lock, flags); - del_timer(&sc->work_timer); + spin_lock_irqsave(sc->lock, flags); ub_scsi_dispatch(sc); - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); } static void ub_scsi_dispatch(struct ub_dev *sc) @@ -1133,6 +1154,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc) } else { if (!ub_is_completed(&sc->work_done)) break; + del_timer(&sc->work_timer); ub_scsi_urb_compl(sc, cmd); } } @@ -1680,16 +1702,18 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) /* * Reset management + * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing. + * XXX Make usb_sync_reset asynchronous. */ -static void ub_reset_enter(struct ub_dev *sc) +static void ub_reset_enter(struct ub_dev *sc, int try) { if (sc->reset) { /* This happens often on multi-LUN devices. */ return; } - sc->reset = 1; + sc->reset = try + 1; #if 0 /* Not needed because the disconnect waits for us. */ unsigned long flags; @@ -1727,6 +1751,11 @@ static void ub_reset_task(void *arg) if (atomic_read(&sc->poison)) { printk(KERN_NOTICE "%s: Not resetting disconnected device\n", sc->name); /* P3 This floods. Remove soon. XXX */ + } else if ((sc->reset & 1) == 0) { + ub_sync_reset(sc); + msleep(700); /* usb-storage sleeps 6s (!) */ + ub_probe_clear_stall(sc, sc->recv_bulk_pipe); + ub_probe_clear_stall(sc, sc->send_bulk_pipe); } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { printk(KERN_NOTICE "%s: Not resetting multi-interface device\n", sc->name); /* P3 This floods. Remove soon. XXX */ @@ -1754,7 +1783,7 @@ static void ub_reset_task(void *arg) * queues of resets or anything. We do need a spinlock though, * to interact with block layer. */ - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); sc->reset = 0; tasklet_schedule(&sc->tasklet); list_for_each(p, &sc->luns) { @@ -1762,7 +1791,7 @@ static void ub_reset_task(void *arg) blk_start_queue(lun->disk->queue); } wake_up(&sc->reset_wait); - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); } /* @@ -1990,11 +2019,11 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun) cmd->done = ub_probe_done; cmd->back = &compl; - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); if (rc != 0) { printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */ @@ -2052,11 +2081,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->done = ub_probe_done; cmd->back = &compl; - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); if (rc != 0) { printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */ @@ -2118,6 +2147,52 @@ static void ub_probe_timeout(unsigned long arg) } /* + * Reset with a Bulk reset. + */ +static int ub_sync_reset(struct ub_dev *sc) +{ + int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber; + struct usb_ctrlrequest *cr; + struct completion compl; + struct timer_list timer; + int rc; + + init_completion(&compl); + + cr = &sc->work_cr; + cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; + cr->bRequest = US_BULK_RESET_REQUEST; + cr->wValue = cpu_to_le16(0); + cr->wIndex = cpu_to_le16(ifnum); + cr->wLength = cpu_to_le16(0); + + usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, + (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); + sc->work_urb.actual_length = 0; + sc->work_urb.error_count = 0; + sc->work_urb.status = 0; + + if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { + printk(KERN_WARNING + "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc); + return rc; + } + + init_timer(&timer); + timer.function = ub_probe_timeout; + timer.data = (unsigned long) &compl; + timer.expires = jiffies + UB_CTRL_TIMEOUT; + add_timer(&timer); + + wait_for_completion(&compl); + + del_timer_sync(&timer); + usb_kill_urb(&sc->work_urb); + + return sc->work_urb.status; +} + +/* * Get number of LUNs by the way of Bulk GetMaxLUN command. */ static int ub_sync_getmaxlun(struct ub_dev *sc) @@ -2333,7 +2408,7 @@ static int ub_probe(struct usb_interface *intf, if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; memset(sc, 0, sizeof(struct ub_dev)); - spin_lock_init(&sc->lock); + sc->lock = ub_next_lock(); INIT_LIST_HEAD(&sc->luns); usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); @@ -2483,7 +2558,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) disk->driverfs_dev = &sc->intf->dev; rc = -ENOMEM; - if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL) + if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; @@ -2554,7 +2629,7 @@ static void ub_disconnect(struct usb_interface *intf) * and the whole queue drains. So, we just use this code to * print warnings. */ - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); { struct ub_scsi_cmd *cmd; int cnt = 0; @@ -2571,7 +2646,7 @@ static void ub_disconnect(struct usb_interface *intf) "%d was queued after shutdown\n", sc->name, cnt); } } - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); /* * Unregister the upper layer. @@ -2590,19 +2665,15 @@ static void ub_disconnect(struct usb_interface *intf) } /* - * Taking a lock on a structure which is about to be freed - * is very nonsensual. Here it is largely a way to do a debug freeze, - * and a bracket which shows where the nonsensual code segment ends. - * * Testing for -EINPROGRESS is always a bug, so we are bending * the rules a little. */ - spin_lock_irqsave(&sc->lock, flags); + spin_lock_irqsave(sc->lock, flags); if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */ printk(KERN_WARNING "%s: " "URB is active after disconnect\n", sc->name); } - spin_unlock_irqrestore(&sc->lock, flags); + spin_unlock_irqrestore(sc->lock, flags); /* * There is virtually no chance that other CPU runs times so long @@ -2636,6 +2707,10 @@ static struct usb_driver ub_driver = { static int __init ub_init(void) { int rc; + int i; + + for (i = 0; i < UB_QLOCK_NUM; i++) + spin_lock_init(&ub_qlockv[i]); if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index a3614e6a68d0..4ada1268b40d 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -882,7 +882,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->card_number, dev->bus->number, dev->devfn); if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && - !pci_set_dma_mask(dev, 0xffffffffLL)) { + pci_set_dma_mask(dev, 0xffffffffLL)) { printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); return -ENOMEM; } diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index e522d19ad886..7e21b1ff27c4 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -474,18 +474,6 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long /* ======================== Card services HCI interaction ======================== */ -static struct device *bt3c_device(void) -{ - static struct device dev = { - .bus_id = "pcmcia", - }; - kobject_set_name(&dev.kobj, "bt3c"); - kobject_init(&dev.kobj); - - return &dev; -} - - static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count) { char *ptr = (char *) firmware; @@ -574,6 +562,7 @@ static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; + client_handle_t handle; int err; spin_lock_init(&(info->lock)); @@ -605,8 +594,10 @@ static int bt3c_open(bt3c_info_t *info) hdev->owner = THIS_MODULE; + handle = info->link.handle; + /* Load firmware */ - err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device()); + err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle)); if (err < 0) { BT_ERR("Firmware request failed"); goto error; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 193446e6a08a..e27617259552 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -42,8 +42,6 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <asm/bug.h> - #include <asm/vio.h> #include <asm/scatterlist.h> #include <asm/iseries/hv_types.h> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4135d8c5bcae..05ba410682a3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -222,7 +222,7 @@ config SYNCLINKMP config SYNCLINK_GT tristate "SyncLink GT/AC support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && PCI help Support for SyncLink GT and SyncLink AC families of synchronous and asynchronous serial adapters @@ -992,7 +992,7 @@ config HPET_MMAP config HANGCHECK_TIMER tristate "Hangcheck timer" - depends on X86 || IA64 || PPC64 || S390 + depends on X86 || IA64 || PPC64 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 810679dcbbb0..9964c508c111 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -600,6 +600,26 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev) agp_put_bridge(bridge); } +#ifdef CONFIG_PM + +static int agp_amd64_suspend(struct pci_dev *pdev, pm_message_t state) +{ + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int agp_amd64_resume(struct pci_dev *pdev) +{ + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + return amd_8151_configure(); +} + +#endif /* CONFIG_PM */ + static struct pci_device_id agp_amd64_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), @@ -718,6 +738,10 @@ static struct pci_driver agp_amd64_pci_driver = { .id_table = agp_amd64_pci_table, .probe = agp_amd64_probe, .remove = agp_amd64_remove, +#ifdef CONFIG_PM + .suspend = agp_amd64_suspend, + .resume = agp_amd64_resume, +#endif }; diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 53372a83b675..5b74c36c116c 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -244,6 +244,22 @@ static int ati_configure(void) } +#ifdef CONFIG_PM +static int agp_ati_resume(struct pci_dev *dev) +{ + pci_restore_state(dev); + + return ati_configure(); +} + +static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state) +{ + pci_save_state(dev); + + return 0; +} +#endif + /* *Since we don't need contigious memory we just try * to get the gatt table once @@ -525,6 +541,10 @@ static struct pci_driver agp_ati_pci_driver = { .id_table = agp_ati_pci_table, .probe = agp_ati_probe, .remove = agp_ati_remove, +#ifdef CONFIG_PM + .resume = agp_ati_resume, + .suspend = agp_ati_suspend, +#endif }; static int __init agp_ati_init(void) diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 17f520c9d471..97eeb2345b18 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -592,7 +592,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) struct agp_file_private *priv = file->private_data; struct agp_kern_info kerninfo; - down(&(agp_fe.agp_mutex)); + mutex_lock(&(agp_fe.agp_mutex)); if (agp_fe.backend_acquired != TRUE) goto out_eperm; @@ -627,7 +627,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) size, vma->vm_page_prot)) { goto out_again; } - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return 0; } @@ -643,20 +643,20 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) size, vma->vm_page_prot)) { goto out_again; } - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return 0; } out_eperm: - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return -EPERM; out_inval: - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return -EINVAL; out_again: - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return -EAGAIN; } @@ -664,7 +664,7 @@ static int agp_release(struct inode *inode, struct file *file) { struct agp_file_private *priv = file->private_data; - down(&(agp_fe.agp_mutex)); + mutex_lock(&(agp_fe.agp_mutex)); DBG("priv=%p", priv); @@ -687,7 +687,7 @@ static int agp_release(struct inode *inode, struct file *file) agp_remove_file_private(priv); kfree(priv); file->private_data = NULL; - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return 0; } @@ -698,7 +698,7 @@ static int agp_open(struct inode *inode, struct file *file) struct agp_client *client; int rc = -ENXIO; - down(&(agp_fe.agp_mutex)); + mutex_lock(&(agp_fe.agp_mutex)); if (minor != AGPGART_MINOR) goto err_out; @@ -723,13 +723,13 @@ static int agp_open(struct inode *inode, struct file *file) file->private_data = (void *) priv; agp_insert_file_private(priv); DBG("private=%p, client=%p", priv, client); - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return 0; err_out_nomem: rc = -ENOMEM; err_out: - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return rc; } @@ -985,7 +985,7 @@ static int agp_ioctl(struct inode *inode, struct file *file, int ret_val = -ENOTTY; DBG("priv=%p, cmd=%x", curr_priv, cmd); - down(&(agp_fe.agp_mutex)); + mutex_lock(&(agp_fe.agp_mutex)); if ((agp_fe.current_controller == NULL) && (cmd != AGPIOC_ACQUIRE)) { @@ -1055,7 +1055,7 @@ static int agp_ioctl(struct inode *inode, struct file *file, ioctl_out: DBG("ioctl returns %d\n", ret_val); - up(&(agp_fe.agp_mutex)); + mutex_unlock(&(agp_fe.agp_mutex)); return ret_val; } @@ -1081,7 +1081,7 @@ static struct miscdevice agp_miscdev = int agp_frontend_initialize(void) { memset(&agp_fe, 0, sizeof(struct agp_front_data)); - sema_init(&(agp_fe.agp_mutex), 1); + mutex_init(&(agp_fe.agp_mutex)); if (misc_register(&agp_miscdev)) { printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index e7bed5047dcc..631531fd97a5 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -422,7 +422,8 @@ static void intel_i830_init_gtt_entries(void) /* Check it's really I915G */ if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) gtt_entries = MB(48) - KB(size); else gtt_entries = 0; @@ -431,7 +432,8 @@ static void intel_i830_init_gtt_entries(void) /* Check it's really I915G */ if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) gtt_entries = MB(64) - KB(size); else gtt_entries = 0; @@ -1681,6 +1683,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, } name = "945G"; break; + case PCI_DEVICE_ID_INTEL_82945GM_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) { + bridge->driver = &intel_915_driver; + } else { + bridge->driver = &intel_845_driver; + } + name = "945GM"; + break; case PCI_DEVICE_ID_INTEL_7505_0: bridge->driver = &intel_7505_driver; name = "E7505"; @@ -1821,6 +1831,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82915G_HB), ID(PCI_DEVICE_ID_INTEL_82915GM_HB), ID(PCI_DEVICE_ID_INTEL_82945G_HB), + ID(PCI_DEVICE_ID_INTEL_82945GM_HB), { } }; diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index 40083241804e..7c14a096b85e 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -218,10 +218,8 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, master[cdev].rq *= (1 << (master[cdev].y - 1)); tot_rq += master[cdev].rq; - - if (cdev == ndevs-1) - master[cdev].n += rem; } + master[ndevs-1].n += rem; /* Figure the number of isochronous and asynchronous RQ slots the * target is providing. */ diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 39c61a71176e..cc7acf877dc0 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1233,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) } info->idle_stats.recv_idle = jiffies; } - schedule_delayed_work(&tty->buf.work, 1); + tty_schedule_flip(tty); } /* end of service */ cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f)); @@ -1606,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info, } #endif info->idle_stats.recv_idle = jiffies; - schedule_delayed_work(&tty->buf.work, 1); + tty_schedule_flip(tty); } /* Update rx_get */ cy_writel(&buf_ctrl->rx_get, new_rx_get); @@ -1809,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo) if(delta_count) cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); if(special_count) - schedule_delayed_work(&tty->buf.work, 1); + tty_schedule_flip(tty); } } diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index 5485382cadec..bd7be09ea53d 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c @@ -59,17 +59,16 @@ static void *drm_ati_alloc_pcigart_table(void) int i; DRM_DEBUG("%s\n", __FUNCTION__); - address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER); + address = __get_free_pages(GFP_KERNEL | __GFP_COMP, + ATI_PCIGART_TABLE_ORDER); if (address == 0UL) { - return 0; + return NULL; } page = virt_to_page(address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { - get_page(page); + for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) SetPageReserved(page); - } DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); return (void *)address; @@ -83,10 +82,8 @@ static void drm_ati_free_pcigart_table(void *address) page = virt_to_page((unsigned long)address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { - __put_page(page); + for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) ClearPageReserved(page); - } free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); } @@ -127,7 +124,7 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && gart_info->addr) { drm_ati_free_pcigart_table(gart_info->addr); - gart_info->addr = 0; + gart_info->addr = NULL; } return 1; @@ -168,7 +165,7 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (bus_address == 0) { DRM_ERROR("unable to map PCIGART pages!\n"); drm_ati_free_pcigart_table(address); - address = 0; + address = NULL; goto done; } } else { diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 54b561e69486..107df9fdba4e 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -57,6 +57,7 @@ #include <linux/smp_lock.h> /* For (un)lock_kernel */ #include <linux/mm.h> #include <linux/cdev.h> +#include <linux/mutex.h> #if defined(__alpha__) || defined(__powerpc__) #include <asm/pgtable.h> /* For pte_wrprotect */ #endif @@ -623,7 +624,7 @@ typedef struct drm_device { /** \name Locks */ /*@{ */ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ - struct semaphore struct_sem; /**< For others */ + struct mutex struct_mutex; /**< For others */ /*@} */ /** \name Usage Counters */ @@ -658,7 +659,7 @@ typedef struct drm_device { /*@{ */ drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ int ctx_count; /**< Number of context handles */ - struct semaphore ctxlist_sem; /**< For ctxlist */ + struct mutex ctxlist_mutex; /**< For ctxlist */ drm_map_t **context_sareas; /**< per-context SAREA's */ int max_context; @@ -979,7 +980,7 @@ extern int drm_put_head(drm_head_t * head); extern unsigned int drm_debug; extern unsigned int drm_cards_limit; extern drm_head_t **drm_heads; -extern struct drm_sysfs_class *drm_class; +extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; /* Proc support (drm_proc.h) */ @@ -1010,11 +1011,9 @@ extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah); extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah); /* sysfs support (drm_sysfs.c) */ -struct drm_sysfs_class; -extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner, - char *name); -extern void drm_sysfs_destroy(struct drm_sysfs_class *cs); -extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, +extern struct class *drm_sysfs_create(struct module *owner, char *name); +extern void drm_sysfs_destroy(struct class *cs); +extern struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head); extern void drm_sysfs_device_remove(struct class_device *class_dev); diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c index a47b502bc7cc..2a37586a7ee8 100644 --- a/drivers/char/drm/drm_auth.c +++ b/drivers/char/drm/drm_auth.c @@ -56,7 +56,7 @@ static int drm_hash_magic(drm_magic_t magic) * \param magic magic number. * * Searches in drm_device::magiclist within all files with the same hash key - * the one with matching magic number, while holding the drm_device::struct_sem + * the one with matching magic number, while holding the drm_device::struct_mutex * lock. */ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) @@ -65,14 +65,14 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) drm_magic_entry_t *pt; int hash = drm_hash_magic(magic); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { if (pt->magic == magic) { retval = pt->priv; break; } } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return retval; } @@ -85,7 +85,7 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) * * Creates a drm_magic_entry structure and appends to the linked list * associated the magic number hash key in drm_device::magiclist, while holding - * the drm_device::struct_sem lock. + * the drm_device::struct_mutex lock. */ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, drm_magic_t magic) @@ -104,7 +104,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, entry->priv = priv; entry->next = NULL; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (dev->magiclist[hash].tail) { dev->magiclist[hash].tail->next = entry; dev->magiclist[hash].tail = entry; @@ -112,7 +112,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, dev->magiclist[hash].head = entry; dev->magiclist[hash].tail = entry; } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -124,7 +124,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, * \param magic magic number. * * Searches and unlinks the entry in drm_device::magiclist with the magic - * number hash key, while holding the drm_device::struct_sem lock. + * number hash key, while holding the drm_device::struct_mutex lock. */ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) { @@ -135,7 +135,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) DRM_DEBUG("%d\n", magic); hash = drm_hash_magic(magic); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { if (pt->magic == magic) { if (dev->magiclist[hash].head == pt) { @@ -147,11 +147,11 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) if (prev) { prev->next = pt->next; } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return 0; } } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 1db12dcb6802..e2637b4d51de 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, memset(list, 0, sizeof(*list)); list->map = map; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); list_add(&list->head, &dev->maplist->head); /* Assign a 32-bit handle */ - /* We do it here so that dev->struct_sem protects the increment */ + /* We do it here so that dev->struct_mutex protects the increment */ list->user_token = HandleID(map->type == _DRM_SHM ? (unsigned long)map->handle : map->offset, dev); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); *maplist = list; return 0; @@ -392,9 +392,9 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) { int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm_rmmap_locked(dev, map); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -423,7 +423,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, return -EFAULT; } - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); list_for_each(list, &dev->maplist->head) { drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); @@ -439,7 +439,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, * find anything. */ if (list == (&dev->maplist->head)) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } @@ -448,13 +448,13 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, /* Register and framebuffer maps are permanent */ if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return 0; } ret = drm_rmmap_locked(dev, map); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -566,16 +566,16 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) atomic_inc(&dev->buf_alloc); spin_unlock(&dev->count_lock); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); entry = &dma->bufs[order]; if (entry->buf_count) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; /* May only call once for each order */ } if (count < 0 || count > 4096) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -EINVAL; } @@ -583,7 +583,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) entry->buflist = drm_alloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS); if (!entry->buflist) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -616,7 +616,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) /* Set count correctly so we free the proper amount. */ entry->buf_count = count; drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -638,7 +638,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) if (!temp_buflist) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -656,7 +656,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); request->count = entry->buf_count; request->size = size; @@ -722,16 +722,16 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) atomic_inc(&dev->buf_alloc); spin_unlock(&dev->count_lock); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); entry = &dma->bufs[order]; if (entry->buf_count) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; /* May only call once for each order */ } if (count < 0 || count > 4096) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -EINVAL; } @@ -739,7 +739,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) entry->buflist = drm_alloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS); if (!entry->buflist) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -750,7 +750,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) if (!entry->seglist) { drm_free(entry->buflist, count * sizeof(*entry->buflist), DRM_MEM_BUFS); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -766,7 +766,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) count * sizeof(*entry->buflist), DRM_MEM_BUFS); drm_free(entry->seglist, count * sizeof(*entry->seglist), DRM_MEM_SEGS); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -790,7 +790,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) drm_free(temp_pagelist, (dma->page_count + (count << page_order)) * sizeof(*dma->pagelist), DRM_MEM_PAGES); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -831,7 +831,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) (count << page_order)) * sizeof(*dma->pagelist), DRM_MEM_PAGES); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -853,7 +853,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) drm_free(temp_pagelist, (dma->page_count + (count << page_order)) * sizeof(*dma->pagelist), DRM_MEM_PAGES); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -878,7 +878,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) dma->page_count += entry->seg_count << page_order; dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); request->count = entry->buf_count; request->size = size; @@ -948,16 +948,16 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) atomic_inc(&dev->buf_alloc); spin_unlock(&dev->count_lock); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); entry = &dma->bufs[order]; if (entry->buf_count) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; /* May only call once for each order */ } if (count < 0 || count > 4096) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -EINVAL; } @@ -965,7 +965,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) entry->buflist = drm_alloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS); if (!entry->buflist) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -999,7 +999,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) /* Set count correctly so we free the proper amount. */ entry->buf_count = count; drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -1022,7 +1022,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) if (!temp_buflist) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -1040,7 +1040,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); request->count = entry->buf_count; request->size = size; @@ -1110,16 +1110,16 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) atomic_inc(&dev->buf_alloc); spin_unlock(&dev->count_lock); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); entry = &dma->bufs[order]; if (entry->buf_count) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; /* May only call once for each order */ } if (count < 0 || count > 4096) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -EINVAL; } @@ -1127,7 +1127,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) entry->buflist = drm_alloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS); if (!entry->buflist) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -1160,7 +1160,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) /* Set count correctly so we free the proper amount. */ entry->buf_count = count; drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -1182,7 +1182,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) if (!temp_buflist) { /* Free the entry because it isn't valid */ drm_cleanup_buf_error(dev, entry); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); atomic_dec(&dev->buf_alloc); return -ENOMEM; } @@ -1200,7 +1200,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); request->count = entry->buf_count; request->size = size; diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index f84254526949..83094c73da67 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c @@ -53,7 +53,7 @@ * \param ctx_handle context handle. * * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry - * in drm_device::context_sareas, while holding the drm_device::struct_sem + * in drm_device::context_sareas, while holding the drm_device::struct_mutex * lock. */ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) @@ -64,10 +64,10 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) goto failed; if (ctx_handle < DRM_MAX_CTXBITMAP) { - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); clear_bit(ctx_handle, dev->ctx_bitmap); dev->context_sareas[ctx_handle] = NULL; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return; } failed: @@ -83,7 +83,7 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) * * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates * drm_device::context_sareas to accommodate the new entry while holding the - * drm_device::struct_sem lock. + * drm_device::struct_mutex lock. */ static int drm_ctxbitmap_next(drm_device_t * dev) { @@ -92,7 +92,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev) if (!dev->ctx_bitmap) return -1; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); if (bit < DRM_MAX_CTXBITMAP) { set_bit(bit, dev->ctx_bitmap); @@ -113,7 +113,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev) DRM_MEM_MAPS); if (!ctx_sareas) { clear_bit(bit, dev->ctx_bitmap); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -1; } dev->context_sareas = ctx_sareas; @@ -126,16 +126,16 @@ static int drm_ctxbitmap_next(drm_device_t * dev) DRM_MEM_MAPS); if (!dev->context_sareas) { clear_bit(bit, dev->ctx_bitmap); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -1; } dev->context_sareas[bit] = NULL; } } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return bit; } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -1; } @@ -145,24 +145,24 @@ static int drm_ctxbitmap_next(drm_device_t * dev) * \param dev DRM device. * * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding - * the drm_device::struct_sem lock. + * the drm_device::struct_mutex lock. */ int drm_ctxbitmap_init(drm_device_t * dev) { int i; int temp; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE, DRM_MEM_CTXBITMAP); if (dev->ctx_bitmap == NULL) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -ENOMEM; } memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE); dev->context_sareas = NULL; dev->max_context = -1; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { temp = drm_ctxbitmap_next(dev); @@ -178,17 +178,17 @@ int drm_ctxbitmap_init(drm_device_t * dev) * \param dev DRM device. * * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding - * the drm_device::struct_sem lock. + * the drm_device::struct_mutex lock. */ void drm_ctxbitmap_cleanup(drm_device_t * dev) { - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (dev->context_sareas) drm_free(dev->context_sareas, sizeof(*dev->context_sareas) * dev->max_context, DRM_MEM_MAPS); drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); } /*@}*/ @@ -222,15 +222,15 @@ int drm_getsareactx(struct inode *inode, struct file *filp, if (copy_from_user(&request, argp, sizeof(request))) return -EFAULT; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (dev->max_context < 0 || request.ctx_id >= (unsigned)dev->max_context) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } map = dev->context_sareas[request.ctx_id]; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); request.handle = NULL; list_for_each_entry(_entry, &dev->maplist->head, head) { @@ -274,7 +274,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, (drm_ctx_priv_map_t __user *) arg, sizeof(request))) return -EFAULT; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); list_for_each(list, &dev->maplist->head) { r_list = list_entry(list, drm_map_list_t, head); if (r_list->map @@ -282,7 +282,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, goto found; } bad: - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; found: @@ -294,7 +294,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, if (request.ctx_id >= (unsigned)dev->max_context) goto bad; dev->context_sareas[request.ctx_id] = map; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -448,10 +448,10 @@ int drm_addctx(struct inode *inode, struct file *filp, ctx_entry->handle = ctx.handle; ctx_entry->tag = priv; - down(&dev->ctxlist_sem); + mutex_lock(&dev->ctxlist_mutex); list_add(&ctx_entry->head, &dev->ctxlist->head); ++dev->ctx_count; - up(&dev->ctxlist_sem); + mutex_unlock(&dev->ctxlist_mutex); if (copy_to_user(argp, &ctx, sizeof(ctx))) return -EFAULT; @@ -574,7 +574,7 @@ int drm_rmctx(struct inode *inode, struct file *filp, drm_ctxbitmap_free(dev, ctx.handle); } - down(&dev->ctxlist_sem); + mutex_lock(&dev->ctxlist_mutex); if (!list_empty(&dev->ctxlist->head)) { drm_ctx_list_t *pos, *n; @@ -586,7 +586,7 @@ int drm_rmctx(struct inode *inode, struct file *filp, } } } - up(&dev->ctxlist_sem); + mutex_unlock(&dev->ctxlist_mutex); return 0; } diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index c4fa5a29582b..dc6bbe8a18dc 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -151,7 +151,7 @@ int drm_lastclose(drm_device_t * dev) if (dev->irq_enabled) drm_irq_uninstall(dev); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); del_timer(&dev->timer); /* Clear pid list */ @@ -231,7 +231,7 @@ int drm_lastclose(drm_device_t * dev) dev->lock.filp = NULL; wake_up_interruptible(&dev->lock.lock_queue); } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); DRM_DEBUG("lastclose completed\n"); return 0; diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 403f44a1bf01..641f7633878c 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -262,7 +262,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_free; } - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (!dev->file_last) { priv->next = NULL; priv->prev = NULL; @@ -276,7 +276,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, dev->file_last->next = priv; dev->file_last = priv; } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); #ifdef __alpha__ /* @@ -413,7 +413,7 @@ int drm_release(struct inode *inode, struct file *filp) drm_fasync(-1, filp, 0); - down(&dev->ctxlist_sem); + mutex_lock(&dev->ctxlist_mutex); if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) { drm_ctx_list_t *pos, *n; @@ -432,9 +432,9 @@ int drm_release(struct inode *inode, struct file *filp) } } } - up(&dev->ctxlist_sem); + mutex_unlock(&dev->ctxlist_mutex); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (priv->remove_auth_on_close == 1) { drm_file_t *temp = dev->file_first; while (temp) { @@ -452,7 +452,7 @@ int drm_release(struct inode *inode, struct file *filp) } else { dev->file_last = priv->prev; } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); if (dev->driver->postclose) dev->driver->postclose(dev, priv); diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index bcd4e604d3ec..555f323b8a32 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c @@ -194,9 +194,9 @@ int drm_getmap(struct inode *inode, struct file *filp, return -EFAULT; idx = map.offset; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); if (idx < 0) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } @@ -209,7 +209,7 @@ int drm_getmap(struct inode *inode, struct file *filp, i++; } if (!r_list || !r_list->map) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } @@ -219,7 +219,7 @@ int drm_getmap(struct inode *inode, struct file *filp, map.flags = r_list->map->flags; map.handle = (void *)(unsigned long)r_list->user_token; map.mtrr = r_list->map->mtrr; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); if (copy_to_user(argp, &map, sizeof(map))) return -EFAULT; @@ -253,11 +253,11 @@ int drm_getclient(struct inode *inode, struct file *filp, if (copy_from_user(&client, argp, sizeof(client))) return -EFAULT; idx = client.idx; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ; if (!pt) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } client.auth = pt->authenticated; @@ -265,7 +265,7 @@ int drm_getclient(struct inode *inode, struct file *filp, client.uid = pt->uid; client.magic = pt->magic; client.iocs = pt->ioctl_count; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); if (copy_to_user(argp, &client, sizeof(client))) return -EFAULT; @@ -292,7 +292,7 @@ int drm_getstats(struct inode *inode, struct file *filp, memset(&stats, 0, sizeof(stats)); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (i = 0; i < dev->counters; i++) { if (dev->types[i] == _DRM_STAT_LOCK) @@ -305,7 +305,7 @@ int drm_getstats(struct inode *inode, struct file *filp, stats.count = dev->counters; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats))) return -EFAULT; diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index b0d4b236e837..611a1173091d 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c @@ -98,20 +98,20 @@ static int drm_irq_install(drm_device_t * dev) if (dev->irq == 0) return -EINVAL; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); /* Driver must have been initialized */ if (!dev->dev_private) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } if (dev->irq_enabled) { - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return -EBUSY; } dev->irq_enabled = 1; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq); @@ -135,9 +135,9 @@ static int drm_irq_install(drm_device_t * dev) ret = request_irq(dev->irq, dev->driver->irq_handler, sh_flags, dev->devname, dev); if (ret < 0) { - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); dev->irq_enabled = 0; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -161,10 +161,10 @@ int drm_irq_uninstall(drm_device_t * dev) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); irq_enabled = dev->irq_enabled; dev->irq_enabled = 0; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); if (!irq_enabled) return -EINVAL; diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 5b1d3a04458d..2c17e88a8847 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,6 +3,7 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ @@ -84,7 +85,6 @@ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ @@ -242,5 +242,6 @@ {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0} diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 6f943e3309ef..362a270af0f1 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c @@ -258,7 +258,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, } /** - * Simply calls _vm_info() while holding the drm_device::struct_sem lock. + * Simply calls _vm_info() while holding the drm_device::struct_mutex lock. */ static int drm_vm_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) @@ -266,9 +266,9 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request, drm_device_t *dev = (drm_device_t *) data; int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm__vm_info(buf, start, offset, request, eof, data); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -331,7 +331,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset, } /** - * Simply calls _queues_info() while holding the drm_device::struct_sem lock. + * Simply calls _queues_info() while holding the drm_device::struct_mutex lock. */ static int drm_queues_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) @@ -339,9 +339,9 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, drm_device_t *dev = (drm_device_t *) data; int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm__queues_info(buf, start, offset, request, eof, data); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -403,7 +403,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request, } /** - * Simply calls _bufs_info() while holding the drm_device::struct_sem lock. + * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock. */ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) @@ -411,9 +411,9 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, drm_device_t *dev = (drm_device_t *) data; int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm__bufs_info(buf, start, offset, request, eof, data); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -459,7 +459,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset, } /** - * Simply calls _clients_info() while holding the drm_device::struct_sem lock. + * Simply calls _clients_info() while holding the drm_device::struct_mutex lock. */ static int drm_clients_info(char *buf, char **start, off_t offset, int request, int *eof, void *data) @@ -467,9 +467,9 @@ static int drm_clients_info(char *buf, char **start, off_t offset, drm_device_t *dev = (drm_device_t *) data; int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm__clients_info(buf, start, offset, request, eof, data); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -540,9 +540,9 @@ static int drm_vma_info(char *buf, char **start, off_t offset, int request, drm_device_t *dev = (drm_device_t *) data; int ret; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); ret = drm__vma_info(buf, start, offset, request, eof, data); - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); return ret; } #endif diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 42d766359caa..68073e14fdec 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -50,7 +50,7 @@ module_param_named(cards_limit, drm_cards_limit, int, 0444); module_param_named(debug, drm_debug, int, 0600); drm_head_t **drm_heads; -struct drm_sysfs_class *drm_class; +struct class *drm_class; struct proc_dir_entry *drm_proc_root; static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, @@ -61,8 +61,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, spin_lock_init(&dev->count_lock); init_timer(&dev->timer); - sema_init(&dev->struct_sem, 1); - sema_init(&dev->ctxlist_sem, 1); + mutex_init(&dev->struct_mutex); + mutex_init(&dev->ctxlist_mutex); dev->pdev = pdev; diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 68e43ddc16ae..0b9f98a7eb10 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -1,3 +1,4 @@ + /* * drm_sysfs.c - Modifications to drm_sysfs_class.c to support * extra sysfs attribute from DRM. Normal drm_sysfs_class @@ -19,36 +20,6 @@ #include "drm_core.h" #include "drmP.h" -struct drm_sysfs_class { - struct class_device_attribute attr; - struct class class; -}; -#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class) - -struct simple_dev { - dev_t dev; - struct class_device class_dev; -}; -#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) - -static void release_simple_dev(struct class_device *class_dev) -{ - struct simple_dev *s_dev = to_simple_dev(class_dev); - kfree(s_dev); -} - -static ssize_t show_dev(struct class_device *class_dev, char *buf) -{ - struct simple_dev *s_dev = to_simple_dev(class_dev); - return print_dev_t(buf, s_dev->dev); -} - -static void drm_sysfs_class_release(struct class *class) -{ - struct drm_sysfs_class *cs = to_drm_sysfs_class(class); - kfree(cs); -} - /* Display the version of drm_core. This doesn't work right in current design */ static ssize_t version_show(struct class *dev, char *buf) { @@ -69,38 +40,16 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); * Note, the pointer created here is to be destroyed when finished by making a * call to drm_sysfs_destroy(). */ -struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name) +struct class *drm_sysfs_create(struct module *owner, char *name) { - struct drm_sysfs_class *cs; - int retval; - - cs = kmalloc(sizeof(*cs), GFP_KERNEL); - if (!cs) { - retval = -ENOMEM; - goto error; - } - memset(cs, 0x00, sizeof(*cs)); - - cs->class.name = name; - cs->class.class_release = drm_sysfs_class_release; - cs->class.release = release_simple_dev; - - cs->attr.attr.name = "dev"; - cs->attr.attr.mode = S_IRUGO; - cs->attr.attr.owner = owner; - cs->attr.show = show_dev; - cs->attr.store = NULL; - - retval = class_register(&cs->class); - if (retval) - goto error; - class_create_file(&cs->class, &class_attr_version); - - return cs; - - error: - kfree(cs); - return ERR_PTR(retval); + struct class *class; + + class = class_create(owner, name); + if (!class) + return class; + + class_create_file(class, &class_attr_version); + return class; } /** @@ -110,12 +59,13 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name) * Note, the pointer to be destroyed must have been created with a call to * drm_sysfs_create(). */ -void drm_sysfs_destroy(struct drm_sysfs_class *cs) +void drm_sysfs_destroy(struct class *class) { - if ((cs == NULL) || (IS_ERR(cs))) + if ((class == NULL) || (IS_ERR(class))) return; - class_unregister(&cs->class); + class_remove_file(class, &class_attr_version); + class_destroy(class); } static ssize_t show_dri(struct class_device *class_device, char *buf) @@ -132,7 +82,7 @@ static struct class_device_attribute class_device_attrs[] = { /** * drm_sysfs_device_add - adds a class device to sysfs for a character driver - * @cs: pointer to the struct drm_sysfs_class that this device should be registered to. + * @cs: pointer to the struct class that this device should be registered to. * @dev: the dev_t for the device to be added. * @device: a pointer to a struct device that is assiociated with this class device. * @fmt: string for the class device's name @@ -141,46 +91,26 @@ static struct class_device_attribute class_device_attrs[] = { * class. A "dev" file will be created, showing the dev_t for the device. The * pointer to the struct class_device will be returned from the call. Any further * sysfs files that might be required can be created using this pointer. - * Note: the struct drm_sysfs_class passed to this function must have previously been + * Note: the struct class passed to this function must have previously been * created with a call to drm_sysfs_create(). */ -struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, - drm_head_t *head) +struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) { - struct simple_dev *s_dev = NULL; - int i, retval; - - if ((cs == NULL) || (IS_ERR(cs))) { - retval = -ENODEV; - goto error; - } - - s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL); - if (!s_dev) { - retval = -ENOMEM; - goto error; - } - memset(s_dev, 0x00, sizeof(*s_dev)); - - s_dev->dev = MKDEV(DRM_MAJOR, head->minor); - s_dev->class_dev.dev = &(head->dev->pdev)->dev; - s_dev->class_dev.class = &cs->class; + struct class_device *class_dev; + int i; - snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor); - retval = class_device_register(&s_dev->class_dev); - if (retval) - goto error; + class_dev = class_device_create(cs, NULL, + MKDEV(DRM_MAJOR, head->minor), + &(head->dev->pdev)->dev, + "card%d", head->minor); + if (!class_dev) + return NULL; - class_device_create_file(&s_dev->class_dev, &cs->attr); - class_set_devdata(&s_dev->class_dev, head); + class_set_devdata(class_dev, head); for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]); - return &s_dev->class_dev; - -error: - kfree(s_dev); - return ERR_PTR(retval); + class_device_create_file(class_dev, &class_device_attrs[i]); + return class_dev; } /** @@ -192,10 +122,9 @@ error: */ void drm_sysfs_device_remove(struct class_device *class_dev) { - struct simple_dev *s_dev = to_simple_dev(class_dev); int i; for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]); - class_device_unregister(&s_dev->class_dev); + class_device_remove_file(class_dev, &class_device_attrs[i]); + class_device_unregister(class_dev); } diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 3f73aa774c80..0291cd62c69f 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -188,7 +188,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) map = vma->vm_private_data; - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (pt = dev->vmalist, prev = NULL; pt; pt = next) { next = pt->next; if (pt->vma->vm_private_data == map) @@ -248,7 +248,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) drm_free(map, sizeof(*map), DRM_MEM_MAPS); } } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); } /** @@ -404,12 +404,12 @@ static void drm_vm_open(struct vm_area_struct *vma) vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); if (vma_entry) { - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); vma_entry->vma = vma; vma_entry->next = dev->vmalist; vma_entry->pid = current->pid; dev->vmalist = vma_entry; - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); } } @@ -431,7 +431,7 @@ static void drm_vm_close(struct vm_area_struct *vma) vma->vm_start, vma->vm_end - vma->vm_start); atomic_dec(&dev->vma_count); - down(&dev->struct_sem); + mutex_lock(&dev->struct_mutex); for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { if (pt->vma == vma) { if (prev) { @@ -443,7 +443,7 @@ static void drm_vm_close(struct vm_area_struct *vma) break; } } - up(&dev->struct_sem); + mutex_unlock(&dev->struct_mutex); } /** diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index cc1b89086876..ae0aa6d7e0bb 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -958,7 +958,7 @@ static int i810_flush_queue(drm_device_t * dev) } /* Must be called with the lock held */ -void i810_reclaim_buffers(drm_device_t * dev, struct file *filp) +static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp) { drm_device_dma_t *dma = dev->dma; int i; diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index a18b80d91920..e8cf3ff606f0 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h @@ -113,8 +113,6 @@ typedef struct drm_i810_private { } drm_i810_private_t; /* i810_dma.c */ -extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp); - extern int i810_driver_dma_quiescent(drm_device_t * dev); extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp); diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 4fea32aed6d2..163f2cbfe60d 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -1239,7 +1239,7 @@ static int i830_flush_queue(drm_device_t * dev) } /* Must be called with the lock held */ -void i830_reclaim_buffers(drm_device_t * dev, struct file *filp) +static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp) { drm_device_dma_t *dma = dev->dma; int i; diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index bf9075b576bd..85bc5be6f916 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h @@ -123,9 +123,6 @@ typedef struct drm_i830_private { extern drm_ioctl_desc_t i830_ioctls[]; extern int i830_max_ioctl; -/* i830_dma.c */ -extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp); - /* i830_irq.c */ extern int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 9140703da1ba..1ff4c7ca0bff 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -344,18 +344,20 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) int i; RING_LOCALS; + if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) + return DRM_ERR(EINVAL); + + BEGIN_LP_RING(((dwords+1)&~1)); + for (i = 0; i < dwords;) { int cmd, sz; if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) return DRM_ERR(EINVAL); -/* printk("%d/%d ", i, dwords); */ - if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) return DRM_ERR(EINVAL); - BEGIN_LP_RING(sz); OUT_RING(cmd); while (++i, --sz) { @@ -365,9 +367,13 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) } OUT_RING(cmd); } - ADVANCE_LP_RING(); } + if (dwords & 1) + OUT_RING(0); + + ADVANCE_LP_RING(); + return 0; } @@ -401,6 +407,21 @@ static int i915_emit_box(drm_device_t * dev, return 0; } +static void i915_emit_breadcrumb(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; + + BEGIN_LP_RING(4); + OUT_RING(CMD_STORE_DWORD_IDX); + OUT_RING(20); + OUT_RING(dev_priv->counter); + OUT_RING(0); + ADVANCE_LP_RING(); +} + static int i915_dispatch_cmdbuffer(drm_device_t * dev, drm_i915_cmdbuffer_t * cmd) { @@ -429,6 +450,7 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev, return ret; } + i915_emit_breadcrumb(dev); return 0; } @@ -475,12 +497,7 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; - BEGIN_LP_RING(4); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(20); - OUT_RING(dev_priv->counter); - OUT_RING(0); - ADVANCE_LP_RING(); + i915_emit_breadcrumb(dev); return 0; } @@ -657,7 +674,7 @@ static int i915_getparam(DRM_IOCTL_ARGS) value = READ_BREADCRUMB(dev_priv); break; default: - DRM_ERROR("Unkown parameter %d\n", param.param); + DRM_ERROR("Unknown parameter %d\n", param.param); return DRM_ERR(EINVAL); } @@ -742,7 +759,8 @@ drm_ioctl_desc_t i915_ioctls[] = { [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH} + [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY } }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 77412ddac007..4cb3da578330 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h @@ -74,6 +74,30 @@ typedef struct _drm_i915_sarea { int pf_active; int pf_current_page; /* which buffer is being displayed? */ int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; } drm_i915_sarea_t; /* Flags for perf_boxes @@ -99,6 +123,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_FREE 0x09 #define DRM_I915_INIT_HEAP 0x0a #define DRM_I915_CMDBUFFER 0x0b +#define DRM_I915_DESTROY_HEAP 0x0c #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -112,6 +137,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) +#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -191,4 +217,11 @@ typedef struct drm_i915_mem_init_heap { int start; } drm_i915_mem_init_heap_t; +/* Allow memory manager to be torn down and re-initialized (eg on + * rotate): + */ +typedef struct drm_i915_mem_destroy_heap { + int region; +} drm_i915_mem_destroy_heap_t; + #endif /* _I915_DRM_H_ */ diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index c6c71b45f101..7a65666899e4 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -37,16 +37,17 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20051209" +#define DRIVER_DATE "20060119" /* Interface history: * * 1.1: Original. * 1.2: Add Power Management * 1.3: Add vblank support + * 1.4: Fix cmdbuffer path, add heap destroy */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 3 +#define DRIVER_MINOR 4 #define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { @@ -123,6 +124,7 @@ extern void i915_driver_irq_uninstall(drm_device_t * dev); extern int i915_mem_alloc(DRM_IOCTL_ARGS); extern int i915_mem_free(DRM_IOCTL_ARGS); extern int i915_mem_init_heap(DRM_IOCTL_ARGS); +extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS); extern void i915_mem_takedown(struct mem_block **heap); extern void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap); diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c index ba87ff17ff64..52c67324df58 100644 --- a/drivers/char/drm/i915_mem.c +++ b/drivers/char/drm/i915_mem.c @@ -365,3 +365,34 @@ int i915_mem_init_heap(DRM_IOCTL_ARGS) return init_heap(heap, initheap.start, initheap.size); } + +int i915_mem_destroy_heap( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_mem_destroy_heap_t destroyheap; + struct mem_block **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data, + sizeof(destroyheap) ); + + heap = get_heap( dev_priv, destroyheap.region ); + if (!heap) { + DRM_ERROR("get_heap failed"); + return DRM_ERR(EFAULT); + } + + if (!*heap) { + DRM_ERROR("heap not initialized?"); + return DRM_ERR(EFAULT); + } + + i915_mem_takedown( heap ); + return 0; +} + diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 915665c7fe7c..9bb8ae0c1c27 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1640,7 +1640,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); - dev_priv->gart_info.addr = 0; + dev_priv->gart_info.addr = NULL; } } /* only clear to the start of flags */ diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 0d426deeefec..59c7520bf9a2 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c @@ -32,6 +32,8 @@ #define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */ #define SAVAGE_FREELIST_DEBUG 0 +static int savage_do_cleanup_bci(drm_device_t *dev); + static int savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) { @@ -895,7 +897,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) return 0; } -int savage_do_cleanup_bci(drm_device_t * dev) +static int savage_do_cleanup_bci(drm_device_t * dev) { drm_savage_private_t *dev_priv = dev->dev_private; diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h index dd46cb85439c..8f04b3d82292 100644 --- a/drivers/char/drm/savage_drv.h +++ b/drivers/char/drm/savage_drv.h @@ -212,7 +212,6 @@ extern int savage_driver_load(drm_device_t *dev, unsigned long chipset); extern int savage_driver_firstopen(drm_device_t *dev); extern void savage_driver_lastclose(drm_device_t *dev); extern int savage_driver_unload(drm_device_t *dev); -extern int savage_do_cleanup_bci(drm_device_t * dev); extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp); /* state functions */ diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index 593c0b8f650a..a691ae74129d 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -222,7 +222,7 @@ static int via_initialize(drm_device_t * dev, return 0; } -int via_dma_init(DRM_IOCTL_ARGS) +static int via_dma_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; @@ -321,7 +321,7 @@ int via_driver_dma_quiescent(drm_device_t * dev) return 0; } -int via_flush_ioctl(DRM_IOCTL_ARGS) +static int via_flush_ioctl(DRM_IOCTL_ARGS) { DRM_DEVICE; @@ -330,7 +330,7 @@ int via_flush_ioctl(DRM_IOCTL_ARGS) return via_driver_dma_quiescent(dev); } -int via_cmdbuffer(DRM_IOCTL_ARGS) +static int via_cmdbuffer(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_via_cmdbuffer_t cmdbuf; @@ -375,7 +375,7 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, return ret; } -int via_pci_cmdbuffer(DRM_IOCTL_ARGS) +static int via_pci_cmdbuffer(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_via_cmdbuffer_t cmdbuf; @@ -665,7 +665,7 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv) * User interface to the space and lag functions. */ -int via_cmdbuf_size(DRM_IOCTL_ARGS) +static int via_cmdbuf_size(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_via_cmdbuf_size_t d_siz; diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 9d5e027dae0e..b7f17457b424 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -108,7 +108,7 @@ via_map_blit_for_device(struct pci_dev *pdev, int num_desc = 0; int cur_line; dma_addr_t next = 0 | VIA_DMA_DPR_EC; - drm_via_descriptor_t *desc_ptr = 0; + drm_via_descriptor_t *desc_ptr = NULL; if (mode == 1) desc_ptr = vsg->desc_pages[cur_descriptor_page]; @@ -167,7 +167,7 @@ via_map_blit_for_device(struct pci_dev *pdev, */ -void +static void via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) { struct page *page; @@ -581,7 +581,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t * int ret = 0; vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - vsg->bounce_buffer = 0; + vsg->bounce_buffer = NULL; vsg->state = dr_via_sg_init; diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index aad4f99f5405..52bcc7b1ba45 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h @@ -110,11 +110,6 @@ extern int via_mem_free(DRM_IOCTL_ARGS); extern int via_agp_init(DRM_IOCTL_ARGS); extern int via_map_init(DRM_IOCTL_ARGS); extern int via_decoder_futex(DRM_IOCTL_ARGS); -extern int via_dma_init(DRM_IOCTL_ARGS); -extern int via_cmdbuffer(DRM_IOCTL_ARGS); -extern int via_flush_ioctl(DRM_IOCTL_ARGS); -extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS); -extern int via_cmdbuf_size(DRM_IOCTL_ARGS); extern int via_wait_irq(DRM_IOCTL_ARGS); extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); extern int via_dma_blit( DRM_IOCTL_ARGS ); @@ -139,8 +134,6 @@ extern int via_driver_dma_quiescent(drm_device_t * dev); extern void via_init_futex(drm_via_private_t * dev_priv); extern void via_cleanup_futex(drm_via_private_t * dev_priv); extern void via_release_futex(drm_via_private_t * dev_priv, int context); -extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq, - int force_sequence, unsigned int *sequence); extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); extern void via_init_dmablit(drm_device_t *dev); diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index 56d7e3daea12..6152415644e9 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c @@ -190,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) return ret; } -int +static int via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, unsigned int *sequence) { diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 3f3ac039f4d9..57539d8f9f7c 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -359,7 +359,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes) } } - schedule_delayed_work(&tty->buf.work, 1); + tty_schedule_flip(tty); info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; release_pio_buffer(pio_buf); @@ -426,7 +426,7 @@ static inline void receive_chars_dma_done(struct esp_struct *info, } tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag); } - schedule_delayed_work(&tty->buf.work, 1); + tty_schedule_flip(tty); } if (dma_bytes != num_bytes) { diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index 40a67c86420c..ac626418b329 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -117,12 +117,9 @@ __setup("hcheck_reboot", hangcheck_parse_reboot); __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); #endif /* not MODULE */ -#if defined(CONFIG_X86) +#if defined(CONFIG_X86) || defined(CONFIG_S390) # define HAVE_MONOTONIC # define TIMER_FREQ 1000000000ULL -#elif defined(CONFIG_S390) -/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */ -# define TIMER_FREQ 0xFA240000ULL #elif defined(CONFIG_IA64) # define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq) #elif defined(CONFIG_PPC64) @@ -134,12 +131,7 @@ extern unsigned long long monotonic_clock(void); #else static inline unsigned long long monotonic_clock(void) { -# ifdef __s390__ - /* returns the TOD. see 4-38 Principles of Op of zSeries */ - return get_clock(); -# else return get_cycles(); -# endif /* __s390__ */ } #endif /* HAVE_MONOTONIC */ @@ -188,8 +180,6 @@ static int __init hangcheck_init(void) VERSION_STR, hangcheck_tick, hangcheck_margin); #if defined (HAVE_MONOTONIC) printk("Hangcheck: Using monotonic_clock().\n"); -#elif defined(__s390__) - printk("Hangcheck: Using TOD.\n"); #else printk("Hangcheck: Using get_cycles().\n"); #endif /* HAVE_MONOTONIC */ diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 3808d9572619..66a2fee06eb9 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -927,9 +927,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) if (ACPI_SUCCESS(status)) { unsigned long size; - size = addr.max_address_range - addr.min_address_range + 1; - hdp->hd_phys_address = addr.min_address_range; - hdp->hd_address = ioremap(addr.min_address_range, size); + size = addr.maximum - addr.minimum + 1; + hdp->hd_phys_address = addr.minimum; + hdp->hd_address = ioremap(addr.minimum, size); if (hpet_is_known(hdp)) { printk(KERN_DEBUG "%s: 0x%lx is busy\n", @@ -937,15 +937,15 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) iounmap(hdp->hd_address); return -EBUSY; } - } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) { - struct acpi_resource_fixed_mem32 *fixmem32; + } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { + struct acpi_resource_fixed_memory32 *fixmem32; fixmem32 = &res->data.fixed_memory32; if (!fixmem32) return -EINVAL; - hdp->hd_phys_address = fixmem32->range_base_address; - hdp->hd_address = ioremap(fixmem32->range_base_address, + hdp->hd_phys_address = fixmem32->address; + hdp->hd_address = ioremap(fixmem32->address, HPET_RANGE_SIZE); if (hpet_is_known(hdp)) { @@ -954,20 +954,20 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) iounmap(hdp->hd_address); return -EBUSY; } - } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { - struct acpi_resource_ext_irq *irqp; + } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { + struct acpi_resource_extended_irq *irqp; int i; irqp = &res->data.extended_irq; - if (irqp->number_of_interrupts > 0) { - hdp->hd_nirqs = irqp->number_of_interrupts; + if (irqp->interrupt_count > 0) { + hdp->hd_nirqs = irqp->interrupt_count; for (i = 0; i < hdp->hd_nirqs; i++) { int rc = acpi_register_gsi(irqp->interrupts[i], - irqp->edge_level, - irqp->active_high_low); + irqp->triggering, + irqp->polarity); if (rc < 0) return AE_ERROR; hdp->hd_irq[i] = rc; diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c index cb8f4198e9a3..e7af647800b6 100644 --- a/drivers/char/ip2/i2cmd.c +++ b/drivers/char/ip2/i2cmd.c @@ -139,7 +139,6 @@ static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW //static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST //static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD -static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW //static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO //static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 56e93a5a1e24..48fcfba37bfa 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -2906,65 +2906,16 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) rc = -EINVAL; break; case 3: // Trace device - if ( cmd == 1 ) { - rc = put_user(iiSendPendingMail, pIndex++ ); - rc = put_user(i2InitChannels, pIndex++ ); - rc = put_user(i2QueueNeeds, pIndex++ ); - rc = put_user(i2QueueCommands, pIndex++ ); - rc = put_user(i2GetStatus, pIndex++ ); - rc = put_user(i2Input, pIndex++ ); - rc = put_user(i2InputFlush, pIndex++ ); - rc = put_user(i2Output, pIndex++ ); - rc = put_user(i2FlushOutput, pIndex++ ); - rc = put_user(i2DrainWakeup, pIndex++ ); - rc = put_user(i2DrainOutput, pIndex++ ); - rc = put_user(i2OutputFree, pIndex++ ); - rc = put_user(i2StripFifo, pIndex++ ); - rc = put_user(i2StuffFifoBypass, pIndex++ ); - rc = put_user(i2StuffFifoFlow, pIndex++ ); - rc = put_user(i2StuffFifoInline, pIndex++ ); - rc = put_user(i2ServiceBoard, pIndex++ ); - rc = put_user(serviceOutgoingFifo, pIndex++ ); - // rc = put_user(ip2_init, pIndex++ ); - rc = put_user(ip2_init_board, pIndex++ ); - rc = put_user(find_eisa_board, pIndex++ ); - rc = put_user(set_irq, pIndex++ ); - rc = put_user(ip2_interrupt, pIndex++ ); - rc = put_user(ip2_poll, pIndex++ ); - rc = put_user(service_all_boards, pIndex++ ); - rc = put_user(do_input, pIndex++ ); - rc = put_user(do_status, pIndex++ ); -#ifndef IP2DEBUG_OPEN - rc = put_user(0, pIndex++ ); -#else - rc = put_user(open_sanity_check, pIndex++ ); -#endif - rc = put_user(ip2_open, pIndex++ ); - rc = put_user(ip2_close, pIndex++ ); - rc = put_user(ip2_hangup, pIndex++ ); - rc = put_user(ip2_write, pIndex++ ); - rc = put_user(ip2_putchar, pIndex++ ); - rc = put_user(ip2_flush_chars, pIndex++ ); - rc = put_user(ip2_write_room, pIndex++ ); - rc = put_user(ip2_chars_in_buf, pIndex++ ); - rc = put_user(ip2_flush_buffer, pIndex++ ); - - //rc = put_user(ip2_wait_until_sent, pIndex++ ); - rc = put_user(0, pIndex++ ); - - rc = put_user(ip2_throttle, pIndex++ ); - rc = put_user(ip2_unthrottle, pIndex++ ); - rc = put_user(ip2_ioctl, pIndex++ ); - rc = put_user(0, pIndex++ ); - rc = put_user(get_serial_info, pIndex++ ); - rc = put_user(set_serial_info, pIndex++ ); - rc = put_user(ip2_set_termios, pIndex++ ); - rc = put_user(ip2_set_line_discipline, pIndex++ ); - rc = put_user(set_params, pIndex++ ); - } else { + /* + * akpm: This used to write a whole bunch of function addresses + * to userspace, which generated lots of put_user() warnings. + * I killed it all. Just return "success" and don't do + * anything. + */ + if (cmd == 1) + rc = 0; + else rc = -EINVAL; - } - break; default: diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0097f06fa67b..d745004281d0 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -481,7 +481,7 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len) } if ((addr->channel == IPMI_BMC_CHANNEL) - || (addr->channel >= IPMI_NUM_CHANNELS) + || (addr->channel >= IPMI_MAX_CHANNELS) || (addr->channel < 0)) return -EINVAL; @@ -1321,7 +1321,7 @@ static int i_ipmi_request(ipmi_user_t user, unsigned char ipmb_seq; long seqid; - if (addr->channel >= IPMI_NUM_CHANNELS) { + if (addr->channel >= IPMI_MAX_CHANNELS) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index c67ef3e47ad5..e59b638766ef 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1270,36 +1270,36 @@ static int try_init_port(int intf_num, struct smi_info **new_info) return 0; } -static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset) +static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset) { return readb((io->addr)+(offset * io->regspacing)); } -static void mem_outb(struct si_sm_io *io, unsigned int offset, +static void intf_mem_outb(struct si_sm_io *io, unsigned int offset, unsigned char b) { writeb(b, (io->addr)+(offset * io->regspacing)); } -static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset) +static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset) { return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) && 0xff; } -static void mem_outw(struct si_sm_io *io, unsigned int offset, +static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, unsigned char b) { writeb(b << io->regshift, (io->addr)+(offset * io->regspacing)); } -static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset) +static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset) { return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) && 0xff; } -static void mem_outl(struct si_sm_io *io, unsigned int offset, +static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, unsigned char b) { writel(b << io->regshift, (io->addr)+(offset * io->regspacing)); @@ -1349,16 +1349,16 @@ static int mem_setup(struct smi_info *info) upon the register size. */ switch (info->io.regsize) { case 1: - info->io.inputb = mem_inb; - info->io.outputb = mem_outb; + info->io.inputb = intf_mem_inb; + info->io.outputb = intf_mem_outb; break; case 2: - info->io.inputb = mem_inw; - info->io.outputb = mem_outw; + info->io.inputb = intf_mem_inw; + info->io.outputb = intf_mem_outw; break; case 4: - info->io.inputb = mem_inl; - info->io.outputb = mem_outl; + info->io.inputb = intf_mem_inl; + info->io.outputb = intf_mem_outl; break; #ifdef readq case 8: @@ -1580,11 +1580,6 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) if (! is_new_interface(-1, addr_space, spmi->addr.address)) return -ENODEV; - if (! spmi->addr.register_bit_width) { - acpi_failure = 1; - return -ENODEV; - } - /* Figure out the interface type. */ switch (spmi->InterfaceType) { @@ -1634,9 +1629,6 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) regspacings[intf_num] = spmi->addr.register_bit_width / 8; info->io.regspacing = spmi->addr.register_bit_width / 8; } else { - /* Some broken systems get this wrong and set the value - * to zero. Assume it is the default spacing. If that - * is wrong, too bad, the vendor should fix the tables. */ regspacings[intf_num] = DEFAULT_REGSPACING; info->io.regspacing = DEFAULT_REGSPACING; } diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h index 217ff09f2fa1..89bd94eb45be 100644 --- a/drivers/char/rio/cirrus.h +++ b/drivers/char/rio/cirrus.h @@ -40,148 +40,6 @@ #endif #define _cirrus_h 1 -#ifdef RTA -#define TO_UART RX -#define TO_DRIVER TX -#endif - -#ifdef HOST -#define TO_UART TX -#define TO_DRIVER RX -#endif -#ifdef RTA -/* Miscellaneous defines for CIRRUS addresses and related logic for - interrupts etc. -*/ -#define MAP(a) ((short *)(cirrus_base + (a))) -#define outp(a,b) (*MAP (a) =(b)) -#define inp(a) ((*MAP (a)) & 0xff) -#define CIRRUS_FIRST (short*)0x7300 -#define CIRRUS_SECOND (short*)0x7200 -#define CIRRUS_THIRD (short*)0x7100 -#define CIRRUS_FOURTH (short*)0x7000 -#define PORTS_ON_CIRRUS 4 -#define CIRRUS_FIFO_SIZE 12 -#define SPACE 0x20 -#define TAB 0x09 -#define LINE_FEED 0x0a -#define CARRIAGE_RETURN 0x0d -#define BACKSPACE 0x08 -#define SPACES_IN_TABS 8 -#define SEND_ESCAPE 0x00 -#define START_BREAK 0x81 -#define TIMER_TICK 0x82 -#define STOP_BREAK 0x83 -#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH))) -#define txack1 ((short *)0x7104) -#define rxack1 ((short *)0x7102) -#define mdack1 ((short *)0x7106) -#define txack2 ((short *)0x7006) -#define rxack2 ((short *)0x7004) -#define mdack2 ((short *)0x7100) -#define int_latch ((short *) 0x7800) -#define int_status ((short *) 0x7c00) -#define tx1_pending 0x20 -#define rx1_pending 0x10 -#define md1_pending 0x40 -#define tx2_pending 0x02 -#define rx2_pending 0x01 -#define md2_pending 0x40 -#define module1_bits 0x07 -#define module1_modern 0x08 -#define module2_bits 0x70 -#define module2_modern 0x80 -#define module_blank 0xf -#define rs232_d25 0x0 -#define rs232_rj45 0x1 -#define rs422_d25 0x3 -#define parallel 0x5 - -#define CLK0 0x00 -#define CLK1 0x01 -#define CLK2 0x02 -#define CLK3 0x03 -#define CLK4 0x04 - -#define CIRRUS_REVC 0x42 -#define CIRRUS_REVE 0x44 - -#define TURNON 1 -#define TURNOFF 0 - -/* The list of CIRRUS registers. - NB. These registers are relative values on 8 bit boundaries whereas - on the RTA's the CIRRUS registers are on word boundaries. Use pointer - arithmetic (short *) to obtain the real addresses required */ -#define ccr 0x05 /* Channel Command Register */ -#define ier 0x06 /* Interrupt Enable Register */ -#define cor1 0x08 /* Channel Option Register 1 */ -#define cor2 0x09 /* Channel Option Register 2 */ -#define cor3 0x0a /* Channel Option Register 3 */ -#define cor4 0x1e /* Channel Option Register 4 */ -#define cor5 0x1f /* Channel Option Register 5 */ - -#define ccsr 0x0b /* Channel Control Status Register */ -#define rdcr 0x0e /* Receive Data Count Register */ -#define tdcr 0x12 /* Transmit Data Count Register */ -#define mcor1 0x15 /* Modem Change Option Register 1 */ -#define mcor2 0x16 /* Modem Change Option Regsiter 2 */ - -#define livr 0x18 /* Local Interrupt Vector Register */ -#define schr1 0x1a /* Special Character Register 1 */ -#define schr2 0x1b /* Special Character Register 2 */ -#define schr3 0x1c /* Special Character Register 3 */ -#define schr4 0x1d /* Special Character Register 4 */ - -#define rtr 0x20 /* Receive Timer Register */ -#define rtpr 0x21 /* Receive Timeout Period Register */ -#define lnc 0x24 /* Lnext character */ - -#define rivr 0x43 /* Receive Interrupt Vector Register */ -#define tivr 0x42 /* Transmit Interrupt Vector Register */ -#define mivr 0x41 /* Modem Interrupt Vector Register */ -#define gfrcr 0x40 /* Global Firmware Revision code Reg */ -#define ricr 0x44 /* Receive Interrupting Channel Reg */ -#define ticr 0x45 /* Transmit Interrupting Channel Reg */ -#define micr 0x46 /* Modem Interrupting Channel Register */ - -#define gcr 0x4b /* Global configuration register */ -#define misr 0x4c /* Modem interrupt status register */ - -#define rbusr 0x59 -#define tbusr 0x5a -#define mbusr 0x5b - -#define eoir 0x60 /* End Of Interrupt Register */ -#define rdsr 0x62 /* Receive Data / Status Register */ -#define tdr 0x63 /* Transmit Data Register */ -#define svrr 0x67 /* Service Request Register */ - -#define car 0x68 /* Channel Access Register */ -#define mir 0x69 /* Modem Interrupt Register */ -#define tir 0x6a /* Transmit Interrupt Register */ -#define rir 0x6b /* Receive Interrupt Register */ -#define msvr1 0x6c /* Modem Signal Value Register 1 */ -#define msvr2 0x6d /* Modem Signal Value Register 2 */ -#define psvr 0x6f /* Printer Signal Value Register */ - -#define tbpr 0x72 /* Transmit Baud Rate Period Register */ -#define tcor 0x76 /* Transmit Clock Option Register */ - -#define rbpr 0x78 /* Receive Baud Rate Period Register */ -#define rber 0x7a /* Receive Baud Rate Extension Register */ -#define rcor 0x7c /* Receive Clock Option Register */ -#define ppr 0x7e /* Prescalar Period Register */ - -/* Misc registers used for forcing the 1400 out of its reset woes */ -#define airl 0x6d -#define airm 0x6e -#define airh 0x6f -#define btcr 0x66 -#define mtcr 0x6c -#define tber 0x74 - -#endif /* #ifdef RTA */ /* Bit fields for particular registers */ diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h index 5b600c32ac02..d55c2f6a9877 100644 --- a/drivers/char/rio/defaults.h +++ b/drivers/char/rio/defaults.h @@ -45,13 +45,6 @@ static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1"; #define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ #define SECOND (int) 15625 /* Low priority ticks */ -#ifdef RTA -#define RX_LIMIT (ushort) 3 -#endif -#ifdef HOST -#define RX_LIMIT (ushort) 1 -#endif - #define LINK_TIMEOUT (int) (POLL_PERIOD / 2) diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h index bfba5b0c033e..48d68ca7f825 100644 --- a/drivers/char/rio/link.h +++ b/drivers/char/rio/link.h @@ -102,30 +102,14 @@ /* ** LED stuff */ -#if defined(RTA) -#define LED_OFF ((ushort) 0) /* LED off */ -#define LED_RED ((ushort) 1) /* LED Red */ -#define LED_GREEN ((ushort) 2) /* LED Green */ -#define LED_ORANGE ((ushort) 4) /* LED Orange */ -#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */ -#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */ -#define LED_SET_COLOUR(colour) (link->led = (colour)) -#define LED_OR_COLOUR(colour) (link->led |= (colour)) -#define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time))) -#else #define LED_SET_COLOUR(colour) #define LED_OR_COLOUR(colour) #define LED_TIMEOUT(time) -#endif /* RTA */ struct LPB { WORD link_number; /* Link Number */ Channel_ptr in_ch; /* Link In Channel */ Channel_ptr out_ch; /* Link Out Channel */ -#ifdef RTA - uchar stat_led; /* Port open leds */ - uchar led; /* True, light led! */ -#endif BYTE attached_serial[4]; /* Attached serial number */ BYTE attached_host_serial[4]; /* Serial number of Host who @@ -144,30 +128,12 @@ struct LPB { WORD WaitNoBoot; /* Secs to hold off booting */ PKT_ptr add_packet_list; /* Add packets to here */ PKT_ptr remove_packet_list; /* Send packets from here */ -#ifdef RTA -#ifdef DCIRRUS -#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1) -#else -#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1) -#endif - PKT_ptr_ptr rd_add; /* Add a new Packet here */ - Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */ - PKT_ptr_ptr rd_add_st_qbb; /* Pointer to start of the Q's buf */ - PKT_ptr_ptr rd_add_end_qbb; /* Pointer to the end of the Q's buf */ - PKT_ptr_ptr rd_remove; /* Remove a Packet here */ - Q_BUF_ptr rd_remove_qb; /* Pointer to the remove Q buf */ - PKT_ptr_ptr rd_remove_st_qbb; /* Pointer to the start of the Q buf */ - PKT_ptr_ptr rd_remove_end_qbb; /* Pointer to the end of the Q buf */ - ushort pkts_in_q; /* Packets in queue */ -#endif Channel_ptr lrt_fail_chan; /* Lrt's failure channel */ Channel_ptr ltt_fail_chan; /* Ltt's failure channel */ -#if defined (HOST) || defined (INKERNEL) /* RUP structure for HOST to driver communications */ struct RUP rup; -#endif struct RUP link_rup; /* RUP for the link (POLL, topology etc.) */ WORD attached_link; /* Number of attached link */ diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h index 36aad4c9cb3a..79b853140ae5 100644 --- a/drivers/char/rio/list.h +++ b/drivers/char/rio/list.h @@ -44,8 +44,6 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9"; #define PKT_IN_USE 0x1 -#ifdef INKERNEL - #define ZERO_PTR (ushort) 0x8000 #define CaD PortP->Caddr @@ -54,143 +52,5 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9"; ** to by the TxAdd pointer has PKT_IN_USE clear in its address. */ -#ifndef linux -#if defined( MIPS ) && !defined( MIPSEISA ) -/* May the shoes of the Devil dance on your grave for creating this */ -#define can_add_transmit(PacketP,PortP) \ - (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ - & (PKT_IN_USE<<2))) - -#elif defined(MIPSEISA) || defined(nx6000) || \ - defined(drs6000) || defined(UWsparc) - -#define can_add_transmit(PacketP,PortP) \ - (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ - & PKT_IN_USE)) - -#else -#define can_add_transmit(PacketP,PortP) \ - (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \ - & PKT_IN_USE)) -#endif - -/* -** To add a packet to the queue, you set the PKT_IN_USE bit in the address, -** and then move the TxAdd pointer along one position to point to the next -** packet pointer. You must wrap the pointer from the end back to the start. -*/ -#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) -# define add_transmit(PortP) \ - WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\ - if (PortP->TxAdd == PortP->TxEnd)\ - PortP->TxAdd = PortP->TxStart;\ - else\ - PortP->TxAdd++;\ - WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd)); -#elif defined(AIX) -# define add_transmit(PortP) \ - {\ - register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\ - WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\ - if (PortP->TxAddO == PortP->TxEndO )\ - PortP->TxAddO = PortP->TxStartO;\ - else\ - PortP->TxAddO += sizeof(ushort);\ - WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\ - } -#else -# define add_transmit(PortP) \ - *PortP->TxAdd |= PKT_IN_USE;\ - if (PortP->TxAdd == PortP->TxEnd)\ - PortP->TxAdd = PortP->TxStart;\ - else\ - PortP->TxAdd++;\ - PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd); -#endif - -/* -** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set -** for the next packet on the queue. It will also set PacketP to point to the -** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, -** then can_remove_receive() returns 0. -*/ -#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) -# define can_remove_receive(PacketP,PortP) \ - ((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \ - (PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0) -#elif defined(AIX) -# define can_remove_receive(PacketP,PortP) \ - ((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \ - (PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0) -#else -# define can_remove_receive(PacketP,PortP) \ - ((*PortP->RxRemove & PKT_IN_USE) ? \ - (PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0) -#endif - - -/* -** Will God see it within his heart to forgive us for this thing that -** we have created? To remove a packet from the receive queue you clear -** its PKT_IN_USE bit, and then bump the pointers. Once the pointers -** get to the end, they must be wrapped back to the start. -*/ -#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) -# define remove_receive(PortP) \ - WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\ - if (PortP->RxRemove == PortP->RxEnd)\ - PortP->RxRemove = PortP->RxStart;\ - else\ - PortP->RxRemove++;\ - WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove)); -#elif defined(AIX) -# define remove_receive(PortP) \ - {\ - register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\ - WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\ - if (PortP->RxRemoveO == PortP->RxEndO)\ - PortP->RxRemoveO = PortP->RxStartO;\ - else\ - PortP->RxRemoveO += sizeof(ushort);\ - WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\ - } -#else -# define remove_receive(PortP) \ - *PortP->RxRemove &= ~PKT_IN_USE;\ - if (PortP->RxRemove == PortP->RxEnd)\ - PortP->RxRemove = PortP->RxStart;\ - else\ - PortP->RxRemove++;\ - PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove); -#endif -#endif - - -#else /* !IN_KERNEL */ - -#define ZERO_PTR NULL - - -#ifdef HOST -/* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE)) */ -#define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\ - if (phb->tx_remove == phb->tx_end)\ - phb->tx_remove = phb->tx_start;\ - else\ - phb->tx_remove++; -#define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE) -#define add_receive(pkt,phb) *phb->rx_add = pkt;\ - *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\ - if (phb->rx_add == phb->rx_end)\ - phb->rx_add = phb->rx_start;\ - else\ - phb->rx_add++; -#endif -#endif - -#ifdef RTA -#define splx(oldspl) if ((oldspl) == 0) spl0() -#endif - #endif /* ifndef _list.h */ /*********** end of file ***********/ diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h index fe4e00567065..e24acc1d1844 100644 --- a/drivers/char/rio/parmmap.h +++ b/drivers/char/rio/parmmap.h @@ -78,14 +78,9 @@ struct PARM_MAP { WORD idle_count; /* Idle time counter */ WORD busy_count; /* Busy counter */ WORD idle_control; /* Control Idle Process */ -#if defined(HOST) || defined(INKERNEL) WORD tx_intr; /* TX interrupt pending */ WORD rx_intr; /* RX interrupt pending */ WORD rup_intr; /* RUP interrupt pending */ -#endif -#if defined(RTA) - WORD dying_count; /* Count of processes dead */ -#endif }; #endif diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h index 3baebf8513af..2663ca0306e2 100644 --- a/drivers/char/rio/phb.h +++ b/drivers/char/rio/phb.h @@ -44,17 +44,6 @@ #endif - /************************************************* - * Set the LIMIT values. - ************************************************/ -#ifdef RTA -#define RX_LIMIT (ushort) 3 -#endif -#ifdef HOST -#define RX_LIMIT (ushort) 1 -#endif - - /************************************************* * Handshake asserted. Deasserted by the LTT(s) ************************************************/ @@ -69,11 +58,7 @@ /************************************************* * Maximum number of PHB's ************************************************/ -#if defined (HOST) || defined (INKERNEL) #define MAX_PHB ((ushort) 128) /* range 0-127 */ -#else -#define MAX_PHB ((ushort) 8) /* range 0-7 */ -#endif /************************************************* * Defines for the mode fields @@ -139,141 +124,23 @@ * the start. The pointer tx_add points to a SPACE to put a Packet. * The pointer tx_remove points to the next Packet to remove *************************************************************************/ -#ifndef INKERNEL -#define src_unit u2.s2.unit -#define src_port u2.s2.port -#define dest_unit u1.s1.unit -#define dest_port u1.s1.port -#endif -#ifdef HOST -#define tx_start u3.s1.tx_start_ptr_ptr -#define tx_add u3.s1.tx_add_ptr_ptr -#define tx_end u3.s1.tx_end_ptr_ptr -#define tx_remove u3.s1.tx_remove_ptr_ptr -#define rx_start u4.s1.rx_start_ptr_ptr -#define rx_add u4.s1.rx_add_ptr_ptr -#define rx_end u4.s1.rx_end_ptr_ptr -#define rx_remove u4.s1.rx_remove_ptr_ptr -#endif typedef struct PHB PHB; struct PHB { -#ifdef RTA - ushort port; -#endif -#ifdef INKERNEL WORD source; -#else - union { - ushort source; /* Complete source */ - struct { - unsigned char unit; /* Source unit */ - unsigned char port; /* Source port */ - } s2; - } u2; -#endif WORD handshake; WORD status; NUMBER timeout; /* Maximum of 1.9 seconds */ WORD link; /* Send down this link */ -#ifdef INKERNEL WORD destination; -#else - union { - ushort destination; /* Complete destination */ - struct { - unsigned char unit; /* Destination unit */ - unsigned char port; /* Destination port */ - } s1; - } u1; -#endif -#ifdef RTA - ushort tx_pkts_added; - ushort tx_pkts_removed; - Q_BUF_ptr tx_q_start; /* Start of the Q list chain */ - short num_tx_q_bufs; /* Number of Q buffers in the chain */ - PKT_ptr_ptr tx_add; /* Add a new Packet here */ - Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */ - PKT_ptr_ptr tx_add_st_qbb; /* Pointer to start of the Q's buf */ - PKT_ptr_ptr tx_add_end_qbb; /* Pointer to the end of the Q's buf */ - PKT_ptr_ptr tx_remove; /* Remove a Packet here */ - Q_BUF_ptr tx_remove_qb; /* Pointer to the remove Q buf */ - PKT_ptr_ptr tx_remove_st_qbb; /* Pointer to the start of the Q buf */ - PKT_ptr_ptr tx_remove_end_qbb; /* Pointer to the end of the Q buf */ -#endif -#ifdef INKERNEL PKT_ptr_ptr tx_start; PKT_ptr_ptr tx_end; PKT_ptr_ptr tx_add; PKT_ptr_ptr tx_remove; -#endif -#ifdef HOST - union { - struct { - PKT_ptr_ptr tx_start_ptr_ptr; - PKT_ptr_ptr tx_end_ptr_ptr; - PKT_ptr_ptr tx_add_ptr_ptr; - PKT_ptr_ptr tx_remove_ptr_ptr; - } s1; - struct { - ushort *tx_start_ptr; - ushort *tx_end_ptr; - ushort *tx_add_ptr; - ushort *tx_remove_ptr; - } s2; - } u3; -#endif -#ifdef RTA - ushort rx_pkts_added; - ushort rx_pkts_removed; - Q_BUF_ptr rx_q_start; /* Start of the Q list chain */ - short num_rx_q_bufs; /* Number of Q buffers in the chain */ - PKT_ptr_ptr rx_add; /* Add a new Packet here */ - Q_BUF_ptr rx_add_qb; /* Pointer to the add Q buf */ - PKT_ptr_ptr rx_add_st_qbb; /* Pointer to start of the Q's buf */ - PKT_ptr_ptr rx_add_end_qbb; /* Pointer to the end of the Q's buf */ - PKT_ptr_ptr rx_remove; /* Remove a Packet here */ - Q_BUF_ptr rx_remove_qb; /* Pointer to the remove Q buf */ - PKT_ptr_ptr rx_remove_st_qbb; /* Pointer to the start of the Q buf */ - PKT_ptr_ptr rx_remove_end_qbb; /* Pointer to the end of the Q buf */ -#endif -#ifdef INKERNEL PKT_ptr_ptr rx_start; PKT_ptr_ptr rx_end; PKT_ptr_ptr rx_add; PKT_ptr_ptr rx_remove; -#endif -#ifdef HOST - union { - struct { - PKT_ptr_ptr rx_start_ptr_ptr; - PKT_ptr_ptr rx_end_ptr_ptr; - PKT_ptr_ptr rx_add_ptr_ptr; - PKT_ptr_ptr rx_remove_ptr_ptr; - } s1; - struct { - ushort *rx_start_ptr; - ushort *rx_end_ptr; - ushort *rx_add_ptr; - ushort *rx_remove_ptr; - } s2; - } u4; -#endif - -#ifdef RTA /* some fields for the remotes */ - ushort flush_count; /* Count of write flushes */ - ushort txmode; /* Modes for tx */ - ushort rxmode; /* Modes for rx */ - ushort portmode; /* Generic modes */ - ushort column; /* TAB3 column count */ - ushort tx_subscript; /* (TX) Subscript into data field */ - ushort rx_subscript; /* (RX) Subscript into data field */ - PKT_ptr rx_incomplete; /* Hold an incomplete packet here */ - ushort modem_bits; /* Modem bits to mask */ - ushort lastModem; /* Modem control lines. */ - ushort addr; /* Address for sub commands */ - ushort MonitorTstate; /* TRUE if monitoring tstop */ -#endif }; diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h index 882fd429ac2e..7011e52e82db 100644 --- a/drivers/char/rio/pkt.h +++ b/drivers/char/rio/pkt.h @@ -70,39 +70,12 @@ #define CONTROL_DATA_WNDW (DATA_WNDW << 8) struct PKT { -#ifdef INKERNEL BYTE dest_unit; /* Destination Unit Id */ BYTE dest_port; /* Destination POrt */ BYTE src_unit; /* Source Unit Id */ BYTE src_port; /* Source POrt */ -#else - union { - ushort destination; /* Complete destination */ - struct { - unsigned char unit; /* Destination unit */ - unsigned char port; /* Destination port */ - } s1; - } u1; - union { - ushort source; /* Complete source */ - struct { - unsigned char unit; /* Source unit */ - unsigned char port; /* Source port */ - } s2; - } u2; -#endif -#ifdef INKERNEL BYTE len; BYTE control; -#else - union { - ushort control; - struct { - unsigned char len; - unsigned char control; - } s3; - } u3; -#endif BYTE data[PKT_MAX_DATA_LEN]; /* Actual data :-) */ WORD csum; /* C-SUM */ diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h index acd9e8e5307d..391ffc335535 100644 --- a/drivers/char/rio/qbuf.h +++ b/drivers/char/rio/qbuf.h @@ -46,11 +46,7 @@ static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1"; -#ifdef HOST -#define PKTS_PER_BUFFER 1 -#else #define PKTS_PER_BUFFER (220 / PKT_LENGTH) -#endif typedef struct Q_BUF Q_BUF; struct Q_BUF { diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h index 9b67e2468bec..46084d5c7e98 100644 --- a/drivers/char/rio/riotypes.h +++ b/drivers/char/rio/riotypes.h @@ -43,9 +43,6 @@ #endif #endif -#ifdef INKERNEL - -#if !defined(MIPSAT) typedef unsigned short NUMBER_ptr; typedef unsigned short WORD_ptr; typedef unsigned short BYTE_ptr; @@ -65,69 +62,6 @@ typedef unsigned short RUP_ptr; typedef unsigned short short_ptr; typedef unsigned short u_short_ptr; typedef unsigned short ushort_ptr; -#else -/* MIPSAT types */ -typedef char RIO_POINTER[8]; -typedef RIO_POINTER NUMBER_ptr; -typedef RIO_POINTER WORD_ptr; -typedef RIO_POINTER BYTE_ptr; -typedef RIO_POINTER char_ptr; -typedef RIO_POINTER Channel_ptr; -typedef RIO_POINTER FREE_LIST_ptr_ptr; -typedef RIO_POINTER FREE_LIST_ptr; -typedef RIO_POINTER LPB_ptr; -typedef RIO_POINTER Process_ptr; -typedef RIO_POINTER PHB_ptr; -typedef RIO_POINTER PKT_ptr; -typedef RIO_POINTER PKT_ptr_ptr; -typedef RIO_POINTER Q_BUF_ptr; -typedef RIO_POINTER Q_BUF_ptr_ptr; -typedef RIO_POINTER ROUTE_STR_ptr; -typedef RIO_POINTER RUP_ptr; -typedef RIO_POINTER short_ptr; -typedef RIO_POINTER u_short_ptr; -typedef RIO_POINTER ushort_ptr; -#endif - -#else /* not INKERNEL */ -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; -typedef short NUMBER; -typedef short *NUMBER_ptr; -typedef unsigned short *WORD_ptr; -typedef unsigned char *BYTE_ptr; -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; -typedef unsigned short ERROR; -typedef unsigned long ID; -typedef char *char_ptr; -typedef Channel *Channel_ptr; -typedef struct FREE_LIST *FREE_LIST_ptr; -typedef struct FREE_LIST **FREE_LIST_ptr_ptr; -typedef struct LPB *LPB_ptr; -typedef struct Process *Process_ptr; -typedef struct PHB *PHB_ptr; -typedef struct PKT *PKT_ptr; -typedef struct PKT **PKT_ptr_ptr; -typedef struct Q_BUF *Q_BUF_ptr; -typedef struct Q_BUF **Q_BUF_ptr_ptr; -typedef struct ROUTE_STR *ROUTE_STR_ptr; -typedef struct RUP *RUP_ptr; -typedef short *short_ptr; -typedef u_short *u_short_ptr; -typedef ushort *ushort_ptr; -typedef struct PKT PKT; -typedef struct LPB LPB; -typedef struct RUP RUP; -#endif - #endif /* __riotypes__ */ diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h index 8d44fec91dd5..f74f67c6f702 100644 --- a/drivers/char/rio/rup.h +++ b/drivers/char/rio/rup.h @@ -43,12 +43,7 @@ #endif #endif -#if defined( HOST ) || defined( INKERNEL ) #define MAX_RUP ((short) 16) -#endif -#ifdef RTA -#define MAX_RUP ((short) 1) -#endif #define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h index 31494054b213..6f754e19015d 100644 --- a/drivers/char/rio/sam.h +++ b/drivers/char/rio/sam.h @@ -43,10 +43,6 @@ #endif -#if !defined( HOST ) && !defined( INKERNEL ) -#define RTA 1 -#endif - #define NUM_FREE_LIST_UNITS 500 #ifndef FALSE diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0949dcef0697..7edc6a4dbdc4 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -433,7 +433,7 @@ static void rp_do_receive(struct r_port *info, count += ToRecv; } /* Push the data up to the tty layer */ - ld->receive_buf(tty, cbuf, fbuf, count); + ld->receive_buf(tty, chead, fhead, count); done: tty_ldisc_deref(ld); } diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 80a5b840e22f..fee68cc895f8 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -103,6 +103,7 @@ #include <linux/serial.h> #include <linux/generic_serial.h> +#include <linux/tty_flip.h> #include "ser_a2232.h" #include "ser_a2232fw.h" diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 64bf89cb574f..c2490e270f1f 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -931,7 +931,7 @@ static int sx_set_real_termios (void *ptr) case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; default: - printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE); + printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); break; } @@ -958,7 +958,7 @@ static int sx_set_real_termios (void *ptr) } else { set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", + sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty)); @@ -973,7 +973,7 @@ static int sx_set_real_termios (void *ptr) } else { clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", + sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty)); /* port->c_dcd = sx_get_CD (port); */ diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 07c9be6a6bbf..a85a60a93deb 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -2630,7 +2630,7 @@ static int get_interface(struct slgt_info *info, int __user *if_mode) static int set_interface(struct slgt_info *info, int if_mode) { unsigned long flags; - unsigned char val; + unsigned short val; DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode)); spin_lock_irqsave(&info->lock,flags); diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 41a94bc79f67..eb2eb3e12d6a 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -250,12 +250,17 @@ tipar_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode) - TIPAR_MINOR; - if (minor > tp_count - 1) + if (tp_count == 0 || minor > tp_count - 1) return -ENXIO; if (test_and_set_bit(minor, &opened)) return -EBUSY; + if (!table[minor].dev) { + printk(KERN_ERR "%s: NULL device for minor %u\n", + __FUNCTION__, minor); + return -ENXIO; + } parport_claim_or_block(table[minor].dev); init_ti_parallel(minor); parport_release(table[minor].dev); @@ -510,16 +515,20 @@ tipar_init_module(void) err = PTR_ERR(tipar_class); goto out_chrdev; } - if (parport_register_driver(&tipar_driver)) { + if (parport_register_driver(&tipar_driver) || tp_count == 0) { printk(KERN_ERR "tipar: unable to register with parport\n"); err = -EIO; - goto out; + goto out_class; } err = 0; goto out; +out_class: + class_destroy(tipar_class); + out_chrdev: + devfs_remove("ticables/par"); unregister_chrdev(TIPAR_MAJOR, "tipar"); out: return err; diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index bc56df8a3474..4c272189cd42 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -34,7 +34,6 @@ #include <linux/kernel.h> /* printk() */ #include <linux/fs.h> /* everything... */ #include <linux/errno.h> /* error codes */ -#include <linux/delay.h> /* udelay */ #include <linux/slab.h> #include <linux/ioport.h> #include <linux/interrupt.h> @@ -156,6 +155,8 @@ This directory exports the following interfaces. There operation is documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4. alarms : current_ref : +received_ref_clk3a : +received_ref_clk3b : enable_clk3a_output : enable_clk3b_output : enable_clka0_output : @@ -165,7 +166,7 @@ enable_clkb1_output : filter_select : hardware_switching : hardware_switching_mode : -interrupt_switch : +telclock_version : mode_select : refalign : reset : @@ -173,7 +174,6 @@ select_amcb1_transmit_clock : select_amcb2_transmit_clock : select_redundant_clock : select_ref_frequency : -test_mode : All sysfs interfaces are integers in hex format, i.e echo 99 > refalign has the same effect as echo 0x99 > refalign. @@ -226,7 +226,7 @@ static int tlclk_release(struct inode *inode, struct file *filp) return 0; } -ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, +static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { if (count < sizeof(struct tlclk_alarms)) @@ -242,7 +242,7 @@ ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, return sizeof(struct tlclk_alarms); } -ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count, +static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { return 0; @@ -278,21 +278,21 @@ static ssize_t show_current_ref(struct device *d, static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL); -static ssize_t show_interrupt_switch(struct device *d, +static ssize_t show_telclock_version(struct device *d, struct device_attribute *attr, char *buf) { unsigned long ret_val; unsigned long flags; spin_lock_irqsave(&event_lock, flags); - ret_val = inb(TLCLK_REG6); + ret_val = inb(TLCLK_REG5); spin_unlock_irqrestore(&event_lock, flags); return sprintf(buf, "0x%lX\n", ret_val); } -static DEVICE_ATTR(interrupt_switch, S_IRUGO, - show_interrupt_switch, NULL); +static DEVICE_ATTR(telclock_version, S_IRUGO, + show_telclock_version, NULL); static ssize_t show_alarms(struct device *d, struct device_attribute *attr, char *buf) @@ -309,6 +309,50 @@ static ssize_t show_alarms(struct device *d, static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t store_received_ref_clk3a(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, ": tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG1, 0xef, val); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL, + store_received_ref_clk3a); + + +static ssize_t store_received_ref_clk3b(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned long tmp; + unsigned char val; + unsigned long flags; + + sscanf(buf, "%lX", &tmp); + dev_dbg(d, ": tmp = 0x%lX\n", tmp); + + val = (unsigned char)tmp; + spin_lock_irqsave(&event_lock, flags); + SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1); + spin_unlock_irqrestore(&event_lock, flags); + + return strnlen(buf, count); +} + +static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL, + store_received_ref_clk3b); + + static ssize_t store_enable_clk3b_output(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { @@ -436,26 +480,6 @@ static ssize_t store_enable_clka0_output(struct device *d, static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL, store_enable_clka0_output); -static ssize_t store_test_mode(struct device *d, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long flags; - unsigned long tmp; - unsigned char val; - - sscanf(buf, "%lX", &tmp); - dev_dbg(d, "tmp = 0x%lX\n", tmp); - - val = (unsigned char)tmp; - spin_lock_irqsave(&event_lock, flags); - SET_PORT_BITS(TLCLK_REG4, 0xfd, 2); - spin_unlock_irqrestore(&event_lock, flags); - - return strnlen(buf, count); -} - -static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode); - static ssize_t store_select_amcb2_transmit_clock(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { @@ -475,7 +499,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d, SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38); switch (val) { case CLK_8_592MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); + SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); break; case CLK_11_184MHz: SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); @@ -484,7 +508,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d, SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); break; case CLK_44_736MHz: - SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); + SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); break; } } else @@ -653,9 +677,7 @@ static ssize_t store_refalign (struct device *d, dev_dbg(d, "tmp = 0x%lX\n", tmp); spin_lock_irqsave(&event_lock, flags); SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); - udelay(2); SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08); - udelay(2); SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); spin_unlock_irqrestore(&event_lock, flags); @@ -706,15 +728,16 @@ static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset); static struct attribute *tlclk_sysfs_entries[] = { &dev_attr_current_ref.attr, - &dev_attr_interrupt_switch.attr, + &dev_attr_telclock_version.attr, &dev_attr_alarms.attr, + &dev_attr_received_ref_clk3a.attr, + &dev_attr_received_ref_clk3b.attr, &dev_attr_enable_clk3a_output.attr, &dev_attr_enable_clk3b_output.attr, &dev_attr_enable_clkb1_output.attr, &dev_attr_enable_clka1_output.attr, &dev_attr_enable_clkb0_output.attr, &dev_attr_enable_clka0_output.attr, - &dev_attr_test_mode.attr, &dev_attr_select_amcb1_transmit_clock.attr, &dev_attr_select_amcb2_transmit_clock.attr, &dev_attr_select_redundant_clock.attr, diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index aedf7a8e6da7..537aa45d8c67 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c @@ -191,7 +191,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, const char *name = ""; char data[40] = ""; int i, n_len = 0, d_len = 0; - u32 event_id, event_data_size; + u32 event_id; switch(event->event_type) { case PREBOOT: @@ -220,8 +220,7 @@ static int get_event_name(char *dest, struct tcpa_event *event, } break; case EVENT_TAG: - event_id = be32_to_cpu(event_entry); - event_data_size = be32_to_cpu(&event_entry[4]); + event_id = be32_to_cpu(*((u32 *)event_entry)); /* ToDo Row data -> Base64 */ @@ -376,7 +375,7 @@ static int read_log(struct tpm_bios_log *log) { struct acpi_tcpa *buff; acpi_status status; - void *virt; + struct acpi_table_header *virt; if (log->bios_event_log != NULL) { printk(KERN_ERR @@ -413,7 +412,7 @@ static int read_log(struct tpm_bios_log *log) 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); + acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); memcpy(log->bios_event_log, virt, buff->log_max_len); @@ -487,26 +486,35 @@ struct file_operations tpm_binary_bios_measurements_ops = { .release = tpm_bios_measurements_release, }; +static int is_bad(void *p) +{ + if (!p) + return 1; + if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV)) + return 1; + return 0; +} + 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) + if (is_bad(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) + if (is_bad(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) + if (is_bad(ascii_file)) goto out_bin; ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL); @@ -538,3 +546,4 @@ void tpm_bios_log_teardown(struct dentry **lst) securityfs_remove(lst[i]); } EXPORT_SYMBOL_GPL(tpm_bios_log_teardown); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 8198dbb7370f..ec7590951af5 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -441,7 +441,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, if ((ioh << 8 | iol) != tpm_inf.base) { dev_err(&dev->dev, - "Could not set IO-ports to %04x\n", + "Could not set IO-ports to 0x%lx\n", tpm_inf.base); release_region(tpm_inf.base, TPM_INF_PORT_LEN); return -EIO; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index eb8b5be4e249..a23816d3e9a1 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -253,6 +253,7 @@ static void tty_buffer_free_all(struct tty_struct *tty) static void tty_buffer_init(struct tty_struct *tty) { + spin_lock_init(&tty->buf.lock); tty->buf.head = NULL; tty->buf.tail = NULL; tty->buf.free = NULL; @@ -266,6 +267,9 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) p->used = 0; p->size = size; p->next = NULL; + p->active = 0; + p->commit = 0; + p->read = 0; p->char_buf_ptr = (char *)(p->data); p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; /* printk("Flip create %p\n", p); */ @@ -296,6 +300,8 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) *tbh = t->next; t->next = NULL; t->used = 0; + t->commit = 0; + t->read = 0; /* DEBUG ONLY */ memset(t->data, '*', size); /* printk("Flip recycle %p\n", t); */ @@ -312,25 +318,37 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) int tty_buffer_request_room(struct tty_struct *tty, size_t size) { - struct tty_buffer *b = tty->buf.tail, *n; - int left = 0; + struct tty_buffer *b, *n; + int left; + unsigned long flags; + + spin_lock_irqsave(&tty->buf.lock, flags); /* OPTIMISATION: We could keep a per tty "zero" sized buffer to remove this conditional if its worth it. This would be invisible to the callers */ - if(b != NULL) + if ((b = tty->buf.tail) != NULL) { left = b->size - b->used; - if(left >= size) - return size; - /* This is the slow path - looking for new buffers to use */ - n = tty_buffer_find(tty, size); - if(n == NULL) - return left; - if(b != NULL) - b->next = n; - else - tty->buf.head = n; - tty->buf.tail = n; + b->active = 1; + } else + left = 0; + + if (left < size) { + /* This is the slow path - looking for new buffers to use */ + if ((n = tty_buffer_find(tty, size)) != NULL) { + if (b != NULL) { + b->next = n; + b->active = 0; + b->commit = b->used; + } else + tty->buf.head = n; + tty->buf.tail = n; + n->active = 1; + } else + size = left; + } + + spin_unlock_irqrestore(&tty->buf.lock, flags); return size; } @@ -396,10 +414,12 @@ EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size) { int space = tty_buffer_request_room(tty, size); - struct tty_buffer *tb = tty->buf.tail; - *chars = tb->char_buf_ptr + tb->used; - memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); - tb->used += space; + if (likely(space)) { + struct tty_buffer *tb = tty->buf.tail; + *chars = tb->char_buf_ptr + tb->used; + memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); + tb->used += space; + } return space; } @@ -416,10 +436,12 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size) { int space = tty_buffer_request_room(tty, size); - struct tty_buffer *tb = tty->buf.tail; - *chars = tb->char_buf_ptr + tb->used; - *flags = tb->flag_buf_ptr + tb->used; - tb->used += space; + if (likely(space)) { + struct tty_buffer *tb = tty->buf.tail; + *chars = tb->char_buf_ptr + tb->used; + *flags = tb->flag_buf_ptr + tb->used; + tb->used += space; + } return space; } @@ -2735,6 +2757,9 @@ static void flush_to_ldisc(void *private_) unsigned long flags; struct tty_ldisc *disc; struct tty_buffer *tbuf; + int count; + char *char_buf; + unsigned char *flag_buf; disc = tty_ldisc_ref(tty); if (disc == NULL) /* !TTY_LDISC */ @@ -2747,20 +2772,24 @@ static void flush_to_ldisc(void *private_) schedule_delayed_work(&tty->buf.work, 1); goto out; } - spin_lock_irqsave(&tty->read_lock, flags); + spin_lock_irqsave(&tty->buf.lock, flags); while((tbuf = tty->buf.head) != NULL) { + while ((count = tbuf->commit - tbuf->read) != 0) { + char_buf = tbuf->char_buf_ptr + tbuf->read; + flag_buf = tbuf->flag_buf_ptr + tbuf->read; + tbuf->read += count; + spin_unlock_irqrestore(&tty->buf.lock, flags); + disc->receive_buf(tty, char_buf, flag_buf, count); + spin_lock_irqsave(&tty->buf.lock, flags); + } + if (tbuf->active) + break; tty->buf.head = tbuf->next; if (tty->buf.head == NULL) tty->buf.tail = NULL; - spin_unlock_irqrestore(&tty->read_lock, flags); - /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */ - disc->receive_buf(tty, tbuf->char_buf_ptr, - tbuf->flag_buf_ptr, - tbuf->used); - spin_lock_irqsave(&tty->read_lock, flags); tty_buffer_free(tty, tbuf); } - spin_unlock_irqrestore(&tty->read_lock, flags); + spin_unlock_irqrestore(&tty->buf.lock, flags); out: tty_ldisc_deref(disc); } @@ -2852,6 +2881,14 @@ EXPORT_SYMBOL(tty_get_baud_rate); void tty_flip_buffer_push(struct tty_struct *tty) { + unsigned long flags; + spin_lock_irqsave(&tty->buf.lock, flags); + if (tty->buf.tail != NULL) { + tty->buf.tail->active = 0; + tty->buf.tail->commit = tty->buf.tail->used; + } + spin_unlock_irqrestore(&tty->buf.lock, flags); + if (tty->low_latency) flush_to_ldisc((void *) tty); else diff --git a/drivers/char/vt.c b/drivers/char/vt.c index f1d9cb7feae6..0900d1dbee59 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -3213,6 +3213,7 @@ void getconsxy(struct vc_data *vc, unsigned char *p) void putconsxy(struct vc_data *vc, unsigned char *p) { + hide_cursor(vc); gotoxy(vc, p[0], p[1]); set_cursor(vc); } diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 37c9e13ad3ac..8d6b249ad66b 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -49,29 +49,37 @@ * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ */ -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/timer.h> -#include <linux/jiffies.h> -#include <linux/config.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/reboot.h> +#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */ +#include <linux/module.h> /* For module specific items */ +#include <linux/moduleparam.h> /* For new moduleparam's */ +#include <linux/types.h> /* For standard types (like size_t) */ +#include <linux/errno.h> /* For the -ENODEV/... values */ +#include <linux/kernel.h> /* For printk/panic/... */ +#include <linux/delay.h> /* For mdelay function */ +#include <linux/timer.h> /* For timer related operations */ +#include <linux/jiffies.h> /* For jiffies stuff */ +#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ +#include <linux/watchdog.h> /* For the watchdog specific items */ +#include <linux/notifier.h> /* For notifier support */ +#include <linux/reboot.h> /* For reboot_notifier stuff */ +#include <linux/init.h> /* For __init/__exit/... */ +#include <linux/fs.h> /* For file operations */ +#include <linux/ioport.h> /* For io-port access */ +#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ #include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */ -#include <asm/uaccess.h> -#include <asm/io.h> +#include <linux/slab.h> /* For kmalloc */ -#define WD_VER "1.16 (06/12/2004)" -#define PFX "pcwd: " +#include <asm/uaccess.h> /* For copy_to_user/put_user/... */ +#include <asm/io.h> /* For inb/outb/... */ + +/* Module and version information */ +#define WATCHDOG_VERSION "1.16" +#define WATCHDOG_DATE "03 Jan 2006" +#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" +#define WATCHDOG_NAME "pcwd" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" +#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")" /* * It should be noted that PCWD_REVISION_B was removed because A and B @@ -85,36 +93,38 @@ /* * These are the defines that describe the control status bits for the - * PC Watchdog card, revision A. - */ + * PCI-PC Watchdog card. +*/ +/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ #define WD_WDRST 0x01 /* Previously reset state */ #define WD_T110 0x02 /* Temperature overheat sense */ #define WD_HRTBT 0x04 /* Heartbeat sense */ #define WD_RLY2 0x08 /* External relay triggered */ #define WD_SRLY2 0x80 /* Software external relay triggered */ - -/* - * These are the defines that describe the control status bits for the - * PC Watchdog card, revision C. - */ +/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ +/* Port 2 : Control Status #2 */ +#define WD_WDIS 0x10 /* Watchdog Disabled */ +#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ +#define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */ +#define WD_WCMD 0x80 /* Watchdog Command Mode */ /* max. time we give an ISA watchdog card to process a command */ /* 500ms for each 4 bit response (according to spec.) */ #define ISA_COMMAND_TIMEOUT 1000 /* Watchdog's internal commands */ -#define CMD_ISA_IDLE 0x00 -#define CMD_ISA_VERSION_INTEGER 0x01 -#define CMD_ISA_VERSION_TENTH 0x02 -#define CMD_ISA_VERSION_HUNDRETH 0x03 -#define CMD_ISA_VERSION_MINOR 0x04 -#define CMD_ISA_SWITCH_SETTINGS 0x05 -#define CMD_ISA_DELAY_TIME_2SECS 0x0A -#define CMD_ISA_DELAY_TIME_4SECS 0x0B -#define CMD_ISA_DELAY_TIME_8SECS 0x0C +#define CMD_ISA_IDLE 0x00 +#define CMD_ISA_VERSION_INTEGER 0x01 +#define CMD_ISA_VERSION_TENTH 0x02 +#define CMD_ISA_VERSION_HUNDRETH 0x03 +#define CMD_ISA_VERSION_MINOR 0x04 +#define CMD_ISA_SWITCH_SETTINGS 0x05 +#define CMD_ISA_DELAY_TIME_2SECS 0x0A +#define CMD_ISA_DELAY_TIME_4SECS 0x0B +#define CMD_ISA_DELAY_TIME_8SECS 0x0C /* * We are using an kernel timer to do the pinging of the watchdog @@ -130,15 +140,17 @@ static int cards_found; /* internal variables */ static atomic_t open_allowed = ATOMIC_INIT(1); static char expect_close; -static struct timer_list timer; -static unsigned long next_heartbeat; static int temp_panic; -static int revision; /* The card's revision */ -static int supports_temp; /* Wether or not the card has a temperature device */ -static int command_mode; /* Wether or not the card is in command mode */ -static int initial_status; /* The card's boot status */ -static int current_readport; /* The cards I/O address */ -static spinlock_t io_lock; +static struct { /* this is private data for each ISA-PC watchdog card */ + int revision; /* The card's revision */ + int supports_temp; /* Wether or not the card has a temperature device */ + int command_mode; /* Wether or not the card is in command mode */ + int boot_status; /* The card's boot status */ + int io_addr; /* The cards I/O address */ + spinlock_t io_lock; /* the lock for io operations */ + struct timer_list timer; /* The timer that pings the watchdog */ + unsigned long next_heartbeat; /* the next_heartbeat for the timer */ +} pcwd_private; /* module parameters */ #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ @@ -161,14 +173,14 @@ static int send_isa_command(int cmd) int port0, last_port0; /* Double read for stabilising */ /* The WCMD bit must be 1 and the command is only 4 bits in size */ - control_status = (cmd & 0x0F) | 0x80; - outb_p(control_status, current_readport + 2); + control_status = (cmd & 0x0F) | WD_WCMD; + outb_p(control_status, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); - port0 = inb_p(current_readport); + port0 = inb_p(pcwd_private.io_addr); for (i = 0; i < 25; ++i) { last_port0 = port0; - port0 = inb_p(current_readport); + port0 = inb_p(pcwd_private.io_addr); if (port0 == last_port0) break; /* Data is stable */ @@ -184,7 +196,7 @@ static int set_command_mode(void) int i, found=0, count=0; /* Set the card into command mode */ - spin_lock(&io_lock); + spin_lock(&pcwd_private.io_lock); while ((!found) && (count < 3)) { i = send_isa_command(CMD_ISA_IDLE); @@ -192,15 +204,15 @@ static int set_command_mode(void) found = 1; else if (i == 0xF3) { /* Card does not like what we've done to it */ - outb_p(0x00, current_readport + 2); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(1200); /* Spec says wait 1ms */ - outb_p(0x00, current_readport + 2); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); } count++; } - spin_unlock(&io_lock); - command_mode = found; + spin_unlock(&pcwd_private.io_lock); + pcwd_private.command_mode = found; return(found); } @@ -208,12 +220,95 @@ static int set_command_mode(void) static void unset_command_mode(void) { /* Set the card into normal mode */ - spin_lock(&io_lock); - outb_p(0x00, current_readport + 2); + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); + + pcwd_private.command_mode = 0; +} + +static inline void pcwd_check_temperature_support(void) +{ + if (inb(pcwd_private.io_addr) != 0xF0) + pcwd_private.supports_temp = 1; +} + +static inline char *get_firmware(void) +{ + int one, ten, hund, minor; + char *ret; + + ret = kmalloc(6, GFP_KERNEL); + if(ret == NULL) + return NULL; + + if (set_command_mode()) { + one = send_isa_command(CMD_ISA_VERSION_INTEGER); + ten = send_isa_command(CMD_ISA_VERSION_TENTH); + hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); + minor = send_isa_command(CMD_ISA_VERSION_MINOR); + sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); + } + else + sprintf(ret, "ERROR"); + + unset_command_mode(); + return(ret); +} + +static inline int pcwd_get_option_switches(void) +{ + int option_switches=0; + + if (set_command_mode()) { + /* Get switch settings */ + option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS); + } + + unset_command_mode(); + return(option_switches); +} + +static void pcwd_show_card_info(void) +{ + char *firmware; + int option_switches; + + /* Get some extra info from the hardware (in command/debug/diag mode) */ + if (pcwd_private.revision == PCWD_REVISION_A) + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); + else if (pcwd_private.revision == PCWD_REVISION_C) { + firmware = get_firmware(); + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", + pcwd_private.io_addr, firmware); + kfree(firmware); + option_switches = pcwd_get_option_switches(); + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + /* Reprogram internal heartbeat to 2 seconds */ + if (set_command_mode()) { + send_isa_command(CMD_ISA_DELAY_TIME_2SECS); + unset_command_mode(); + } + } + + if (pcwd_private.supports_temp) + printk(KERN_INFO PFX "Temperature Option Detected\n"); + + if (pcwd_private.boot_status & WDIOF_CARDRESET) + printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); + + if (pcwd_private.boot_status & WDIOF_OVERHEAT) { + printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); + printk(KERN_EMERG PFX "CPU Overheat\n"); + } - command_mode = 0; + if (pcwd_private.boot_status == 0) + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); } static void pcwd_timer_ping(unsigned long data) @@ -222,25 +317,25 @@ static void pcwd_timer_ping(unsigned long data) /* If we got a heartbeat pulse within the WDT_INTERVAL * we agree to ping the WDT */ - if(time_before(jiffies, next_heartbeat)) { + if(time_before(jiffies, pcwd_private.next_heartbeat)) { /* Ping the watchdog */ - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) { + spin_lock(&pcwd_private.io_lock); + if (pcwd_private.revision == PCWD_REVISION_A) { /* Rev A cards are reset by setting the WD_WDRST bit in register 1 */ - wdrst_stat = inb_p(current_readport); + wdrst_stat = inb_p(pcwd_private.io_addr); wdrst_stat &= 0x0F; wdrst_stat |= WD_WDRST; - outb_p(wdrst_stat, current_readport + 1); + outb_p(wdrst_stat, pcwd_private.io_addr + 1); } else { /* Re-trigger watchdog by writing to port 0 */ - outb_p(0x00, current_readport); + outb_p(0x00, pcwd_private.io_addr); } /* Re-set the timer interval */ - mod_timer(&timer, jiffies + WDT_INTERVAL); + mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL); - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); } else { printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } @@ -250,19 +345,19 @@ static int pcwd_start(void) { int stat_reg; - next_heartbeat = jiffies + (heartbeat * HZ); + pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); /* Start the timer */ - mod_timer(&timer, jiffies + WDT_INTERVAL); + mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL); /* Enable the port */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 3); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if (stat_reg & 0x10) { + stat_reg = inb_p(pcwd_private.io_addr + 2); + spin_unlock(&pcwd_private.io_lock); + if (stat_reg & WD_WDIS) { printk(KERN_INFO PFX "Could not start watchdog\n"); return -EIO; } @@ -275,18 +370,18 @@ static int pcwd_stop(void) int stat_reg; /* Stop the timer */ - del_timer(&timer); + del_timer(&pcwd_private.timer); /* Disable the board */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0xA5, current_readport + 3); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0xA5, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - outb_p(0xA5, current_readport + 3); + outb_p(0xA5, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if ((stat_reg & 0x10) == 0) { + stat_reg = inb_p(pcwd_private.io_addr + 2); + spin_unlock(&pcwd_private.io_lock); + if ((stat_reg & WD_WDIS) == 0) { printk(KERN_INFO PFX "Could not stop watchdog\n"); return -EIO; } @@ -297,7 +392,7 @@ static int pcwd_stop(void) static int pcwd_keepalive(void) { /* user land ping */ - next_heartbeat = jiffies + (heartbeat * HZ); + pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); return 0; } @@ -315,23 +410,23 @@ static int pcwd_get_status(int *status) int card_status; *status=0; - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) + spin_lock(&pcwd_private.io_lock); + if (pcwd_private.revision == PCWD_REVISION_A) /* Rev A cards return status information from * the base register, which is used for the * temperature in other cards. */ - card_status = inb(current_readport); + card_status = inb(pcwd_private.io_addr); else { /* Rev C cards return card status in the base * address + 1 register. And use different bits * to indicate a card initiated reset, and an * over-temperature condition. And the reboot * status can be reset. */ - card_status = inb(current_readport + 1); + card_status = inb(pcwd_private.io_addr + 1); } - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); - if (revision == PCWD_REVISION_A) { + if (pcwd_private.revision == PCWD_REVISION_A) { if (card_status & WD_WDRST) *status |= WDIOF_CARDRESET; @@ -360,10 +455,10 @@ static int pcwd_get_status(int *status) static int pcwd_clear_status(void) { - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 1); /* clear reset status */ - spin_unlock(&io_lock); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */ + spin_unlock(&pcwd_private.io_lock); } return 0; } @@ -371,20 +466,20 @@ static int pcwd_clear_status(void) static int pcwd_get_temperature(int *temperature) { /* check that port 0 gives temperature info and no command results */ - if (command_mode) + if (pcwd_private.command_mode) return -1; *temperature = 0; - if (!supports_temp) + if (!pcwd_private.supports_temp) return -ENODEV; /* * Convert celsius to fahrenheit, since this was * the decided 'standard' for this return value. */ - spin_lock(&io_lock); - *temperature = ((inb(current_readport)) * 9 / 5) + 32; - spin_unlock(&io_lock); + spin_lock(&pcwd_private.io_lock); + *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; + spin_unlock(&pcwd_private.io_lock); return 0; } @@ -425,7 +520,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, return put_user(status, argp); case WDIOC_GETBOOTSTATUS: - return put_user(initial_status, argp); + return put_user(pcwd_private.boot_status, argp); case WDIOC_GETTEMP: if (pcwd_get_temperature(&temperature)) @@ -434,7 +529,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, return put_user(temperature, argp); case WDIOC_SETOPTIONS: - if (revision == PCWD_REVISION_C) + if (pcwd_private.revision == PCWD_REVISION_C) { if(copy_from_user(&rv, argp, sizeof(int))) return -EFAULT; @@ -550,7 +645,7 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count, static int pcwd_temp_open(struct inode *inode, struct file *file) { - if (!supports_temp) + if (!pcwd_private.supports_temp) return -ENODEV; return nonseekable_open(inode, file); @@ -616,68 +711,24 @@ static struct notifier_block pcwd_notifier = { * Init & exit routines */ -static inline void get_support(void) -{ - if (inb(current_readport) != 0xF0) - supports_temp = 1; -} - static inline int get_revision(void) { int r = PCWD_REVISION_C; - spin_lock(&io_lock); + spin_lock(&pcwd_private.io_lock); /* REV A cards use only 2 io ports; test * presumes a floating bus reads as 0xff. */ - if ((inb(current_readport + 2) == 0xFF) || - (inb(current_readport + 3) == 0xFF)) + if ((inb(pcwd_private.io_addr + 2) == 0xFF) || + (inb(pcwd_private.io_addr + 3) == 0xFF)) r=PCWD_REVISION_A; - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); return r; } -static inline char *get_firmware(void) -{ - int one, ten, hund, minor; - char *ret; - - ret = kmalloc(6, GFP_KERNEL); - if(ret == NULL) - return NULL; - - if (set_command_mode()) { - one = send_isa_command(CMD_ISA_VERSION_INTEGER); - ten = send_isa_command(CMD_ISA_VERSION_TENTH); - hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); - minor = send_isa_command(CMD_ISA_VERSION_MINOR); - sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); - } - else - sprintf(ret, "ERROR"); - - unset_command_mode(); - return(ret); -} - -static inline int get_option_switches(void) -{ - int rv=0; - - if (set_command_mode()) { - /* Get switch settings */ - rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS); - } - - unset_command_mode(); - return(rv); -} - static int __devinit pcwatchdog_init(int base_addr) { int ret; - char *firmware; - int option_switches; cards_found++; if (cards_found == 1) @@ -692,104 +743,66 @@ static int __devinit pcwatchdog_init(int base_addr) printk(KERN_ERR PFX "No I/O-Address for card detected\n"); return -ENODEV; } - current_readport = base_addr; + pcwd_private.io_addr = base_addr; /* Check card's revision */ - revision = get_revision(); + pcwd_private.revision = get_revision(); - if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { + if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", - current_readport); - current_readport = 0x0000; + pcwd_private.io_addr); + pcwd_private.io_addr = 0x0000; return -EIO; } /* Initial variables */ - supports_temp = 0; + pcwd_private.supports_temp = 0; temp_panic = 0; - initial_status = 0x0000; + pcwd_private.boot_status = 0x0000; /* get the boot_status */ - pcwd_get_status(&initial_status); + pcwd_get_status(&pcwd_private.boot_status); /* clear the "card caused reboot" flag */ pcwd_clear_status(); - init_timer(&timer); - timer.function = pcwd_timer_ping; - timer.data = 0; + init_timer(&pcwd_private.timer); + pcwd_private.timer.function = pcwd_timer_ping; + pcwd_private.timer.data = 0; /* Disable the board */ pcwd_stop(); /* Check whether or not the card supports the temperature device */ - get_support(); - - /* Get some extra info from the hardware (in command/debug/diag mode) */ - if (revision == PCWD_REVISION_A) - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport); - else if (revision == PCWD_REVISION_C) { - firmware = get_firmware(); - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", - current_readport, firmware); - kfree(firmware); - option_switches = get_option_switches(); - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", - option_switches, - ((option_switches & 0x10) ? "ON" : "OFF"), - ((option_switches & 0x08) ? "ON" : "OFF")); - - /* Reprogram internal heartbeat to 2 seconds */ - if (set_command_mode()) { - send_isa_command(CMD_ISA_DELAY_TIME_2SECS); - unset_command_mode(); - } - } else { - /* Should NEVER happen, unless get_revision() fails. */ - printk(KERN_INFO PFX "Unable to get revision\n"); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; - return -1; - } + pcwd_check_temperature_support(); - if (supports_temp) - printk(KERN_INFO PFX "Temperature Option Detected\n"); - - if (initial_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); - - if (initial_status & WDIOF_OVERHEAT) { - printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); - printk(KERN_EMERG PFX "CPU Overheat\n"); - } - - if (initial_status == 0) - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + /* Show info about the card itself */ + pcwd_show_card_info(); /* Check that the heartbeat value is within it's range ; if not reset to the default */ - if (pcwd_set_heartbeat(heartbeat)) { - pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); - printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", - WATCHDOG_HEARTBEAT); + if (pcwd_set_heartbeat(heartbeat)) { + pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); + printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", + WATCHDOG_HEARTBEAT); } ret = register_reboot_notifier(&pcwd_notifier); if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } - if (supports_temp) { + if (pcwd_private.supports_temp) { ret = misc_register(&temp_miscdev); if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", TEMP_MINOR, ret); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } } @@ -798,11 +811,11 @@ static int __devinit pcwatchdog_init(int base_addr) if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); - if (supports_temp) + if (pcwd_private.supports_temp) misc_deregister(&temp_miscdev); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } @@ -820,11 +833,12 @@ static void __devexit pcwatchdog_exit(void) /* Deregister */ misc_deregister(&pcwd_miscdev); - if (supports_temp) + if (pcwd_private.supports_temp) misc_deregister(&temp_miscdev); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; + cards_found--; } /* @@ -887,7 +901,7 @@ static int __init pcwd_init_module(void) { int i, found = 0; - spin_lock_init(&io_lock); + spin_lock_init(&pcwd_private.io_lock); for (i = 0; pcwd_ioports[i] != 0; i++) { if (pcwd_checkcard(pcwd_ioports[i])) { @@ -906,7 +920,7 @@ static int __init pcwd_init_module(void) static void __exit pcwd_cleanup_module(void) { - if (current_readport) + if (pcwd_private.io_addr) pcwatchdog_exit(); return; } diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index b474ea52d6e8..522a9370db94 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -93,23 +93,25 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, { int ret = -ENOIOCTLCMD; int time; + void __user *argp = (void __user *)arg; + int __user *p = argp; switch (cmd) { case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: - ret = put_user(0, (int __user *)arg); + ret = put_user(0, p); break; case WDIOC_GETBOOTSTATUS: - ret = put_user(boot_status, (int __user *)arg); + ret = put_user(boot_status, p); break; case WDIOC_SETTIMEOUT: - ret = get_user(time, (int __user *)arg); + ret = get_user(time, p); if (ret) break; @@ -123,7 +125,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg); + ret = put_user(pre_margin / OSCR_FREQ, p); break; case WDIOC_KEEPALIVE: diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c index 951764614ebf..837b1ec3ffe3 100644 --- a/drivers/char/watchdog/sbc_epx_c3.c +++ b/drivers/char/watchdog/sbc_epx_c3.c @@ -25,6 +25,7 @@ #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -91,7 +92,7 @@ static int epx_c3_release(struct inode *inode, struct file *file) return 0; } -static ssize_t epx_c3_write(struct file *file, const char *data, +static ssize_t epx_c3_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { /* Refresh the timer. */ @@ -104,6 +105,7 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; + int __user *argp = (void __user *)arg; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -113,20 +115,19 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &ident, sizeof(ident))) + if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); + return put_user(0, argp); case WDIOC_KEEPALIVE: epx_c3_pet(); return 0; case WDIOC_GETTIMEOUT: - return put_user(WATCHDOG_TIMEOUT,(int *)arg); - case WDIOC_SETOPTIONS: { - if (get_user(options, (int *)arg)) + return put_user(WATCHDOG_TIMEOUT, argp); + case WDIOC_SETOPTIONS: + if (get_user(options, argp)) return -EFAULT; if (options & WDIOS_DISABLECARD) { @@ -140,7 +141,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, } return retval; - } default: return -ENOIOCTLCMD; } @@ -181,11 +181,14 @@ static int __init watchdog_init(void) { int ret; + if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog")) + return -EBUSY; + ret = register_reboot_notifier(&epx_c3_notifier); if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier " "(err=%d)\n", ret); - return ret; + goto out; } ret = misc_register(&epx_c3_miscdev); @@ -193,18 +196,23 @@ static int __init watchdog_init(void) printk(KERN_ERR PFX "cannot register miscdev on minor=%d " "(err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&epx_c3_notifier); - return ret; + goto out; } printk(banner); return 0; + +out: + release_region(EPXC3_WATCHDOG_CTL_REG, 2); + return ret; } static void __exit watchdog_exit(void) { misc_deregister(&epx_c3_miscdev); unregister_reboot_notifier(&epx_c3_notifier); + release_region(EPXC3_WATCHDOG_CTL_REG, 2); } module_init(watchdog_init); diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig new file mode 100644 index 000000000000..18a455651121 --- /dev/null +++ b/drivers/edac/Kconfig @@ -0,0 +1,101 @@ +# +# EDAC Kconfig +# Copyright (c) 2003 Linux Networx +# Licensed and distributed under the GPL +# +# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $ +# + +menu 'EDAC - error detection and reporting (RAS)' + +config EDAC + tristate "EDAC core system error reporting" + depends on X86 + help + EDAC is designed to report errors in the core system. + These are low-level errors that are reported in the CPU or + supporting chipset: memory errors, cache errors, PCI errors, + thermal throttling, etc.. If unsure, select 'Y'. + + +comment "Reporting subsystems" + depends on EDAC + +config EDAC_DEBUG + bool "Debugging" + depends on EDAC + help + This turns on debugging information for the entire EDAC + sub-system. You can insert module with "debug_level=x", current + there're four debug levels (x=0,1,2,3 from low to high). + Usually you should select 'N'. + +config EDAC_MM_EDAC + tristate "Main Memory EDAC (Error Detection And Correction) reporting" + depends on EDAC + default y + help + Some systems are able to detect and correct errors in main + memory. EDAC can report statistics on memory error + detection and correction (EDAC - or commonly referred to ECC + errors). EDAC will also try to decode where these errors + occurred so that a particular failing memory module can be + replaced. If unsure, select 'Y'. + + +config EDAC_AMD76X + tristate "AMD 76x (760, 762, 768)" + depends on EDAC_MM_EDAC && PCI && X86_32 + help + Support for error detection and correction on the AMD 76x + series of chipsets used with the Athlon processor. + +config EDAC_E7XXX + tristate "Intel e7xxx (e7205, e7500, e7501, e7505)" + depends on EDAC_MM_EDAC && PCI + help + Support for error detection and correction on the Intel + E7205, E7500, E7501 and E7505 server chipsets. + +config EDAC_E752X + tristate "Intel e752x (e7520, e7525, e7320)" + depends on EDAC_MM_EDAC && PCI + help + Support for error detection and correction on the Intel + E7520, E7525, E7320 server chipsets. + +config EDAC_I82875P + tristate "Intel 82875p (D82875P, E7210)" + depends on EDAC_MM_EDAC && PCI + help + Support for error detection and correction on the Intel + DP82785P and E7210 server chipsets. + +config EDAC_I82860 + tristate "Intel 82860" + depends on EDAC_MM_EDAC && PCI + help + Support for error detection and correction on the Intel + 82860 chipset. + +config EDAC_R82600 + tristate "Radisys 82600 embedded chipset" + depends on EDAC_MM_EDAC + help + Support for error detection and correction on the Radisys + 82600 embedded chipset. + +choice + prompt "Error detecting method" + depends on EDAC + default EDAC_POLL + +config EDAC_POLL + bool "Poll for errors" + depends on EDAC + help + Poll the chipset periodically to detect errors. + +endchoice + +endmenu diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile new file mode 100644 index 000000000000..93137fdab4b3 --- /dev/null +++ b/drivers/edac/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the Linux kernel EDAC drivers. +# +# Copyright 02 Jul 2003, Linux Networx (http://lnxi.com) +# This file may be distributed under the terms of the +# GNU General Public License. +# +# $Id: Makefile,v 1.4.2.3 2005/07/08 22:05:38 dsp_llnl Exp $ + + +obj-$(CONFIG_EDAC_MM_EDAC) += edac_mc.o +obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o +obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o +obj-$(CONFIG_EDAC_E752X) += e752x_edac.o +obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o +obj-$(CONFIG_EDAC_I82860) += i82860_edac.o +obj-$(CONFIG_EDAC_R82600) += r82600_edac.o + diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c new file mode 100644 index 000000000000..2fcc8120b53c --- /dev/null +++ b/drivers/edac/amd76x_edac.c @@ -0,0 +1,356 @@ +/* + * AMD 76x Memory Controller kernel module + * (C) 2003 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh + * Based on work by Dan Hollis <goemon at anime dot net> and others. + * http://www.anime.net/~goemon/linux-ecc/ + * + * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $ + * + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/pci.h> +#include <linux/pci_ids.h> + +#include <linux/slab.h> + +#include "edac_mc.h" + + +#define AMD76X_NR_CSROWS 8 +#define AMD76X_NR_CHANS 1 +#define AMD76X_NR_DIMMS 4 + + +/* AMD 76x register addresses - device 0 function 0 - PCI bridge */ +#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b) + * + * 31:16 reserved + * 15:14 SERR enabled: x1=ue 1x=ce + * 13 reserved + * 12 diag: disabled, enabled + * 11:10 mode: dis, EC, ECC, ECC+scrub + * 9:8 status: x1=ue 1x=ce + * 7:4 UE cs row + * 3:0 CE cs row + */ +#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b) + * + * 31:26 clock disable 5 - 0 + * 25 SDRAM init + * 24 reserved + * 23 mode register service + * 22:21 suspend to RAM + * 20 burst refresh enable + * 19 refresh disable + * 18 reserved + * 17:16 cycles-per-refresh + * 15:8 reserved + * 7:0 x4 mode enable 7 - 0 + */ +#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b) + * + * 31:23 chip-select base + * 22:16 reserved + * 15:7 chip-select mask + * 6:3 reserved + * 2:1 address mode + * 0 chip-select enable + */ + + +struct amd76x_error_info { + u32 ecc_mode_status; +}; + + +enum amd76x_chips { + AMD761 = 0, + AMD762 +}; + + +struct amd76x_dev_info { + const char *ctl_name; +}; + + +static const struct amd76x_dev_info amd76x_devs[] = { + [AMD761] = {.ctl_name = "AMD761"}, + [AMD762] = {.ctl_name = "AMD762"}, +}; + + +/** + * amd76x_get_error_info - fetch error information + * @mci: Memory controller + * @info: Info to fill in + * + * Fetch and store the AMD76x ECC status. Clear pending status + * on the chip so that further errors will be reported + */ + +static void amd76x_get_error_info (struct mem_ctl_info *mci, + struct amd76x_error_info *info) +{ + pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS, + &info->ecc_mode_status); + + if (info->ecc_mode_status & BIT(8)) + pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, + (u32) BIT(8), (u32) BIT(8)); + + if (info->ecc_mode_status & BIT(9)) + pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, + (u32) BIT(9), (u32) BIT(9)); +} + + +/** + * amd76x_process_error_info - Error check + * @mci: Memory controller + * @info: Previously fetched information from chip + * @handle_errors: 1 if we should do recovery + * + * Process the chip state and decide if an error has occurred. + * A return of 1 indicates an error. Also if handle_errors is true + * then attempt to handle and clean up after the error + */ + +static int amd76x_process_error_info (struct mem_ctl_info *mci, + struct amd76x_error_info *info, int handle_errors) +{ + int error_found; + u32 row; + + error_found = 0; + + /* + * Check for an uncorrectable error + */ + if (info->ecc_mode_status & BIT(8)) { + error_found = 1; + + if (handle_errors) { + row = (info->ecc_mode_status >> 4) & 0xf; + edac_mc_handle_ue(mci, + mci->csrows[row].first_page, 0, row, + mci->ctl_name); + } + } + + /* + * Check for a correctable error + */ + if (info->ecc_mode_status & BIT(9)) { + error_found = 1; + + if (handle_errors) { + row = info->ecc_mode_status & 0xf; + edac_mc_handle_ce(mci, + mci->csrows[row].first_page, 0, 0, row, 0, + mci->ctl_name); + } + } + return error_found; +} + +/** + * amd76x_check - Poll the controller + * @mci: Memory controller + * + * Called by the poll handlers this function reads the status + * from the controller and checks for errors. + */ + +static void amd76x_check(struct mem_ctl_info *mci) +{ + struct amd76x_error_info info; + debugf3("MC: " __FILE__ ": %s()\n", __func__); + amd76x_get_error_info(mci, &info); + amd76x_process_error_info(mci, &info, 1); +} + + +/** + * amd76x_probe1 - Perform set up for detected device + * @pdev; PCI device detected + * @dev_idx: Device type index + * + * We have found an AMD76x and now need to set up the memory + * controller status reporting. We configure and set up the + * memory controller reporting and claim the device. + */ + +static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + struct mem_ctl_info *mci = NULL; + enum edac_type ems_modes[] = { + EDAC_NONE, + EDAC_EC, + EDAC_SECDED, + EDAC_SECDED + }; + u32 ems; + u32 ems_mode; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); + ems_mode = (ems >> 10) & 0x3; + + mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); + + if (mci == NULL) { + rc = -ENOMEM; + goto fail; + } + + debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + + mci->pdev = pci_dev_get(pdev); + mci->mtype_cap = MEM_FLAG_RDDR; + + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; + mci->edac_cap = ems_mode ? + (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; + + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.4.2.5 $"; + mci->ctl_name = amd76x_devs[dev_idx].ctl_name; + mci->edac_check = amd76x_check; + mci->ctl_page_to_phys = NULL; + + for (index = 0; index < mci->nr_csrows; index++) { + struct csrow_info *csrow = &mci->csrows[index]; + u32 mba; + u32 mba_base; + u32 mba_mask; + u32 dms; + + /* find the DRAM Chip Select Base address and mask */ + pci_read_config_dword(mci->pdev, + AMD76X_MEM_BASE_ADDR + (index * 4), + &mba); + + if (!(mba & BIT(0))) + continue; + + mba_base = mba & 0xff800000UL; + mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; + + pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS, + &dms); + + csrow->first_page = mba_base >> PAGE_SHIFT; + csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + csrow->nr_pages - 1; + csrow->page_mask = mba_mask >> PAGE_SHIFT; + csrow->grain = csrow->nr_pages << PAGE_SHIFT; + csrow->mtype = MEM_RDDR; + csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; + csrow->edac_mode = ems_modes[ems_mode]; + } + + /* clear counters */ + pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8), + (u32) (0x3 << 8)); + + if (edac_mc_add_mc(mci)) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", __func__); + goto fail; + } + + /* get this far and it's successful */ + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + return 0; + +fail: + if (mci) { + if(mci->pdev) + pci_dev_put(mci->pdev); + edac_mc_free(mci); + } + return rc; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit amd76x_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* don't need to call pci_device_enable() */ + return amd76x_probe1(pdev, ent->driver_data); +} + + +/** + * amd76x_remove_one - driver shutdown + * @pdev: PCI device being handed back + * + * Called when the driver is unloaded. Find the matching mci + * structure for the device then delete the mci and free the + * resources. + */ + +static void __devexit amd76x_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + + debugf0(__FILE__ ": %s()\n", __func__); + + if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) + return; + if (edac_mc_del_mc(mci)) + return; + pci_dev_put(mci->pdev); + edac_mc_free(mci); +} + + +static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD762}, + {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD761}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl); + + +static struct pci_driver amd76x_driver = { + .name = BS_MOD_STR, + .probe = amd76x_init_one, + .remove = __devexit_p(amd76x_remove_one), + .id_table = amd76x_pci_tbl, +}; + +static int __init amd76x_init(void) +{ + return pci_register_driver(&amd76x_driver); +} + +static void __exit amd76x_exit(void) +{ + pci_unregister_driver(&amd76x_driver); +} + +module_init(amd76x_init); +module_exit(amd76x_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); +MODULE_DESCRIPTION("MC support for AMD 76x memory controllers"); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c new file mode 100644 index 000000000000..c454ded2b060 --- /dev/null +++ b/drivers/edac/e752x_edac.c @@ -0,0 +1,1071 @@ +/* + * Intel e752x Memory Controller kernel module + * (C) 2004 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * See "enum e752x_chips" below for supported chipsets + * + * Written by Tom Zimmerman + * + * Contributors: + * Thayne Harbaugh at realmsys.com (?) + * Wang Zhenyu at intel.com + * Dave Jiang at mvista.com + * + * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $ + * + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/pci.h> +#include <linux/pci_ids.h> + +#include <linux/slab.h> + +#include "edac_mc.h" + + +#ifndef PCI_DEVICE_ID_INTEL_7520_0 +#define PCI_DEVICE_ID_INTEL_7520_0 0x3590 +#endif /* PCI_DEVICE_ID_INTEL_7520_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR +#define PCI_DEVICE_ID_INTEL_7520_1_ERR 0x3591 +#endif /* PCI_DEVICE_ID_INTEL_7520_1_ERR */ + +#ifndef PCI_DEVICE_ID_INTEL_7525_0 +#define PCI_DEVICE_ID_INTEL_7525_0 0x359E +#endif /* PCI_DEVICE_ID_INTEL_7525_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR +#define PCI_DEVICE_ID_INTEL_7525_1_ERR 0x3593 +#endif /* PCI_DEVICE_ID_INTEL_7525_1_ERR */ + +#ifndef PCI_DEVICE_ID_INTEL_7320_0 +#define PCI_DEVICE_ID_INTEL_7320_0 0x3592 +#endif /* PCI_DEVICE_ID_INTEL_7320_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR +#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593 +#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */ + +#define E752X_NR_CSROWS 8 /* number of csrows */ + + +/* E752X register addresses - device 0 function 0 */ +#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ +#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ + /* + * 31:30 Device width row 7 + * 01=x8 10=x4 11=x8 DDR2 + * 27:26 Device width row 6 + * 23:22 Device width row 5 + * 19:20 Device width row 4 + * 15:14 Device width row 3 + * 11:10 Device width row 2 + * 7:6 Device width row 1 + * 3:2 Device width row 0 + */ +#define E752X_DRC 0x7C /* DRAM controller mode reg (32b) */ + /* FIXME:IS THIS RIGHT? */ + /* + * 22 Number channels 0=1,1=2 + * 19:18 DRB Granularity 32/64MB + */ +#define E752X_DRM 0x80 /* Dimm mapping register */ +#define E752X_DDRCSR 0x9A /* DDR control and status reg (16b) */ + /* + * 14:12 1 single A, 2 single B, 3 dual + */ +#define E752X_TOLM 0xC4 /* DRAM top of low memory reg (16b) */ +#define E752X_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */ +#define E752X_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */ +#define E752X_REMAPOFFSET 0xCA /* DRAM remap limit offset reg (16b) */ + +/* E752X register addresses - device 0 function 1 */ +#define E752X_FERR_GLOBAL 0x40 /* Global first error register (32b) */ +#define E752X_NERR_GLOBAL 0x44 /* Global next error register (32b) */ +#define E752X_HI_FERR 0x50 /* Hub interface first error reg (8b) */ +#define E752X_HI_NERR 0x52 /* Hub interface next error reg (8b) */ +#define E752X_HI_ERRMASK 0x54 /* Hub interface error mask reg (8b) */ +#define E752X_HI_SMICMD 0x5A /* Hub interface SMI command reg (8b) */ +#define E752X_SYSBUS_FERR 0x60 /* System buss first error reg (16b) */ +#define E752X_SYSBUS_NERR 0x62 /* System buss next error reg (16b) */ +#define E752X_SYSBUS_ERRMASK 0x64 /* System buss error mask reg (16b) */ +#define E752X_SYSBUS_SMICMD 0x6A /* System buss SMI command reg (16b) */ +#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */ +#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */ +#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */ +#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */ +#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */ +#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */ +#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */ +#define E752X_DRAM_SMICMD 0x8A /* DRAM SMI command register (8b) */ +#define E752X_DRAM_RETR_ADD 0xAC /* DRAM Retry address register (32b) */ +#define E752X_DRAM_SEC1_ADD 0xA0 /* DRAM first correctable memory */ + /* error address register (32b) */ + /* + * 31 Reserved + * 30:2 CE address (64 byte block 34:6) + * 1 Reserved + * 0 HiLoCS + */ +#define E752X_DRAM_SEC2_ADD 0xC8 /* DRAM first correctable memory */ + /* error address register (32b) */ + /* + * 31 Reserved + * 30:2 CE address (64 byte block 34:6) + * 1 Reserved + * 0 HiLoCS + */ +#define E752X_DRAM_DED_ADD 0xA4 /* DRAM first uncorrectable memory */ + /* error address register (32b) */ + /* + * 31 Reserved + * 30:2 CE address (64 byte block 34:6) + * 1 Reserved + * 0 HiLoCS + */ +#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */ + /* error address register (32b) */ + /* + * 31 Reserved + * 30:2 CE address (64 byte block 34:6) + * 1 Reserved + * 0 HiLoCS + */ +#define E752X_DRAM_SEC1_SYNDROME 0xC4 /* DRAM first correctable memory */ + /* error syndrome register (16b) */ +#define E752X_DRAM_SEC2_SYNDROME 0xC6 /* DRAM second correctable memory */ + /* error syndrome register (16b) */ +#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */ + +/* ICH5R register addresses - device 30 function 0 */ +#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */ +#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */ +#define ICH5R_PCI_BRIDGE_CTL 0x3E /* PCI bridge control register (16b) */ + +enum e752x_chips { + E7520 = 0, + E7525 = 1, + E7320 = 2 +}; + + +struct e752x_pvt { + struct pci_dev *bridge_ck; + struct pci_dev *dev_d0f0; + struct pci_dev *dev_d0f1; + u32 tolm; + u32 remapbase; + u32 remaplimit; + int mc_symmetric; + u8 map[8]; + int map_type; + const struct e752x_dev_info *dev_info; +}; + + +struct e752x_dev_info { + u16 err_dev; + const char *ctl_name; +}; + +struct e752x_error_info { + u32 ferr_global; + u32 nerr_global; + u8 hi_ferr; + u8 hi_nerr; + u16 sysbus_ferr; + u16 sysbus_nerr; + u8 buf_ferr; + u8 buf_nerr; + u16 dram_ferr; + u16 dram_nerr; + u32 dram_sec1_add; + u32 dram_sec2_add; + u16 dram_sec1_syndrome; + u16 dram_sec2_syndrome; + u32 dram_ded_add; + u32 dram_scrb_add; + u32 dram_retr_add; +}; + +static const struct e752x_dev_info e752x_devs[] = { + [E7520] = { + .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, + .ctl_name = "E7520"}, + [E7525] = { + .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, + .ctl_name = "E7525"}, + [E7320] = { + .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, + .ctl_name = "E7320"}, +}; + + +static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, + unsigned long page) +{ + u32 remap; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + if (page < pvt->tolm) + return page; + if ((page >= 0x100000) && (page < pvt->remapbase)) + return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) + return remap; + printk(KERN_ERR "Invalid page %lx - out of range\n", page); + return pvt->tolm - 1; +} + +static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, + u32 sec1_add, u16 sec1_syndrome) +{ + u32 page; + int row; + int channel; + int i; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + /* convert the addr to 4k page */ + page = sec1_add >> (PAGE_SHIFT - 4); + + /* FIXME - check for -1 */ + if (pvt->mc_symmetric) { + /* chip select are bits 14 & 13 */ + row = ((page >> 1) & 3); + printk(KERN_WARNING + "Test row %d Table %d %d %d %d %d %d %d %d\n", + row, pvt->map[0], pvt->map[1], pvt->map[2], + pvt->map[3], pvt->map[4], pvt->map[5], + pvt->map[6], pvt->map[7]); + + /* test for channel remapping */ + for (i = 0; i < 8; i++) { + if (pvt->map[i] == row) + break; + } + printk(KERN_WARNING "Test computed row %d\n", i); + if (i < 8) + row = i; + else + printk(KERN_WARNING + "MC%d: row %d not found in remap table\n", + mci->mc_idx, row); + } else + row = edac_mc_find_csrow_by_page(mci, page); + /* 0 = channel A, 1 = channel B */ + channel = !(error_one & 1); + + if (!pvt->map_type) + row = 7 - row; + edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel, + "e752x CE"); +} + + +static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, + u32 sec1_add, u16 sec1_syndrome, int *error_found, + int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_process_ce(mci, error_one, sec1_add, sec1_syndrome); +} + +static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, + u32 scrb_add) +{ + u32 error_2b, block_page; + int row; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + if (error_one & 0x0202) { + error_2b = ded_add; + /* convert to 4k address */ + block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, + "e752x UE from Read"); + } + if (error_one & 0x0404) { + error_2b = scrb_add; + /* convert to 4k address */ + block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, + "e752x UE from Scruber"); + } +} + +static inline void process_ue(struct mem_ctl_info *mci, u16 error_one, + u32 ded_add, u32 scrb_add, int *error_found, int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_process_ue(mci, error_one, ded_add, scrb_add); +} + +static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, + int *error_found, int handle_error) +{ + *error_found = 1; + + if (!handle_error) + return; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + edac_mc_handle_ue_no_info(mci, "e752x UE log memory write"); +} + +static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, + u32 retry_add) +{ + u32 error_1b, page; + int row; + struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; + + error_1b = retry_add; + page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ + row = pvt->mc_symmetric ? + ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ + edac_mc_find_csrow_by_page(mci, page); + printk(KERN_WARNING + "MC%d: CE page 0x%lx, row %d : Memory read retry\n", + mci->mc_idx, (long unsigned int) page, row); +} + +static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error, + u32 retry_add, int *error_found, int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_process_ded_retry(mci, error, retry_add); +} + +static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error, + int *error_found, int handle_error) +{ + *error_found = 1; + + if (handle_error) + printk(KERN_WARNING "MC%d: Memory threshold CE\n", + mci->mc_idx); +} + +static char *global_message[11] = { + "PCI Express C1", "PCI Express C", "PCI Express B1", + "PCI Express B", "PCI Express A1", "PCI Express A", + "DMA Controler", "HUB Interface", "System Bus", + "DRAM Controler", "Internal Buffer" +}; + +static char *fatal_message[2] = { "Non-Fatal ", "Fatal " }; + +static void do_global_error(int fatal, u32 errors) +{ + int i; + + for (i = 0; i < 11; i++) { + if (errors & (1 << i)) + printk(KERN_WARNING "%sError %s\n", + fatal_message[fatal], global_message[i]); + } +} + +static inline void global_error(int fatal, u32 errors, int *error_found, + int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_global_error(fatal, errors); +} + +static char *hub_message[7] = { + "HI Address or Command Parity", "HI Illegal Access", + "HI Internal Parity", "Out of Range Access", + "HI Data Parity", "Enhanced Config Access", + "Hub Interface Target Abort" +}; + +static void do_hub_error(int fatal, u8 errors) +{ + int i; + + for (i = 0; i < 7; i++) { + if (errors & (1 << i)) + printk(KERN_WARNING "%sError %s\n", + fatal_message[fatal], hub_message[i]); + } +} + +static inline void hub_error(int fatal, u8 errors, int *error_found, + int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_hub_error(fatal, errors); +} + +static char *membuf_message[4] = { + "Internal PMWB to DRAM parity", + "Internal PMWB to System Bus Parity", + "Internal System Bus or IO to PMWB Parity", + "Internal DRAM to PMWB Parity" +}; + +static void do_membuf_error(u8 errors) +{ + int i; + + for (i = 0; i < 4; i++) { + if (errors & (1 << i)) + printk(KERN_WARNING "Non-Fatal Error %s\n", + membuf_message[i]); + } +} + +static inline void membuf_error(u8 errors, int *error_found, int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_membuf_error(errors); +} + +#if 0 +char *sysbus_message[10] = { + "Addr or Request Parity", + "Data Strobe Glitch", + "Addr Strobe Glitch", + "Data Parity", + "Addr Above TOM", + "Non DRAM Lock Error", + "MCERR", "BINIT", + "Memory Parity", + "IO Subsystem Parity" +}; +#endif /* 0 */ + +static void do_sysbus_error(int fatal, u32 errors) +{ + int i; + + for (i = 0; i < 10; i++) { + if (errors & (1 << i)) + printk(KERN_WARNING "%sError System Bus %s\n", + fatal_message[fatal], global_message[i]); + } +} + +static inline void sysbus_error(int fatal, u32 errors, int *error_found, + int handle_error) +{ + *error_found = 1; + + if (handle_error) + do_sysbus_error(fatal, errors); +} + +static void e752x_check_hub_interface (struct e752x_error_info *info, + int *error_found, int handle_error) +{ + u8 stat8; + + //pci_read_config_byte(dev,E752X_HI_FERR,&stat8); + stat8 = info->hi_ferr; + if(stat8 & 0x7f) { /* Error, so process */ + stat8 &= 0x7f; + if(stat8 & 0x2b) + hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) + hub_error(0, stat8 & 0x54, error_found, handle_error); + } + //pci_read_config_byte(dev,E752X_HI_NERR,&stat8); + stat8 = info->hi_nerr; + if(stat8 & 0x7f) { /* Error, so process */ + stat8 &= 0x7f; + if (stat8 & 0x2b) + hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) + hub_error(0, stat8 & 0x54, error_found, handle_error); + } +} + +static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found, + int handle_error) +{ + u32 stat32, error32; + + //pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32); + stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16); + + if (stat32 == 0) + return; /* no errors */ + + error32 = (stat32 >> 16) & 0x3ff; + stat32 = stat32 & 0x3ff; + if(stat32 & 0x083) + sysbus_error(1, stat32 & 0x083, error_found, handle_error); + if(stat32 & 0x37c) + sysbus_error(0, stat32 & 0x37c, error_found, handle_error); + if(error32 & 0x083) + sysbus_error(1, error32 & 0x083, error_found, handle_error); + if(error32 & 0x37c) + sysbus_error(0, error32 & 0x37c, error_found, handle_error); +} + +static void e752x_check_membuf (struct e752x_error_info *info, int *error_found, + int handle_error) +{ + u8 stat8; + + stat8 = info->buf_ferr; + if (stat8 & 0x0f) { /* Error, so process */ + stat8 &= 0x0f; + membuf_error(stat8, error_found, handle_error); + } + stat8 = info->buf_nerr; + if (stat8 & 0x0f) { /* Error, so process */ + stat8 &= 0x0f; + membuf_error(stat8, error_found, handle_error); + } +} + +static void e752x_check_dram (struct mem_ctl_info *mci, + struct e752x_error_info *info, int *error_found, int handle_error) +{ + u16 error_one, error_next; + + error_one = info->dram_ferr; + error_next = info->dram_nerr; + + /* decode and report errors */ + if(error_one & 0x0101) /* check first error correctable */ + process_ce(mci, error_one, info->dram_sec1_add, + info->dram_sec1_syndrome, error_found, + handle_error); + + if(error_next & 0x0101) /* check next error correctable */ + process_ce(mci, error_next, info->dram_sec2_add, + info->dram_sec2_syndrome, error_found, + handle_error); + + if(error_one & 0x4040) + process_ue_no_info_wr(mci, error_found, handle_error); + + if(error_next & 0x4040) + process_ue_no_info_wr(mci, error_found, handle_error); + + if(error_one & 0x2020) + process_ded_retry(mci, error_one, info->dram_retr_add, + error_found, handle_error); + + if(error_next & 0x2020) + process_ded_retry(mci, error_next, info->dram_retr_add, + error_found, handle_error); + + if(error_one & 0x0808) + process_threshold_ce(mci, error_one, error_found, + handle_error); + + if(error_next & 0x0808) + process_threshold_ce(mci, error_next, error_found, + handle_error); + + if(error_one & 0x0606) + process_ue(mci, error_one, info->dram_ded_add, + info->dram_scrb_add, error_found, handle_error); + + if(error_next & 0x0606) + process_ue(mci, error_next, info->dram_ded_add, + info->dram_scrb_add, error_found, handle_error); +} + +static void e752x_get_error_info (struct mem_ctl_info *mci, + struct e752x_error_info *info) +{ + struct pci_dev *dev; + struct e752x_pvt *pvt; + + memset(info, 0, sizeof(*info)); + pvt = (struct e752x_pvt *) mci->pvt_info; + dev = pvt->dev_d0f1; + + pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global); + + if (info->ferr_global) { + pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr); + pci_read_config_word(dev, E752X_SYSBUS_FERR, + &info->sysbus_ferr); + pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr); + pci_read_config_word(dev, E752X_DRAM_FERR, + &info->dram_ferr); + pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD, + &info->dram_sec1_add); + pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME, + &info->dram_sec1_syndrome); + pci_read_config_dword(dev, E752X_DRAM_DED_ADD, + &info->dram_ded_add); + pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD, + &info->dram_scrb_add); + pci_read_config_dword(dev, E752X_DRAM_RETR_ADD, + &info->dram_retr_add); + + if (info->hi_ferr & 0x7f) + pci_write_config_byte(dev, E752X_HI_FERR, + info->hi_ferr); + + if (info->sysbus_ferr) + pci_write_config_word(dev, E752X_SYSBUS_FERR, + info->sysbus_ferr); + + if (info->buf_ferr & 0x0f) + pci_write_config_byte(dev, E752X_BUF_FERR, + info->buf_ferr); + + if (info->dram_ferr) + pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR, + info->dram_ferr, info->dram_ferr); + + pci_write_config_dword(dev, E752X_FERR_GLOBAL, + info->ferr_global); + } + + pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global); + + if (info->nerr_global) { + pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr); + pci_read_config_word(dev, E752X_SYSBUS_NERR, + &info->sysbus_nerr); + pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr); + pci_read_config_word(dev, E752X_DRAM_NERR, + &info->dram_nerr); + pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD, + &info->dram_sec2_add); + pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME, + &info->dram_sec2_syndrome); + + if (info->hi_nerr & 0x7f) + pci_write_config_byte(dev, E752X_HI_NERR, + info->hi_nerr); + + if (info->sysbus_nerr) + pci_write_config_word(dev, E752X_SYSBUS_NERR, + info->sysbus_nerr); + + if (info->buf_nerr & 0x0f) + pci_write_config_byte(dev, E752X_BUF_NERR, + info->buf_nerr); + + if (info->dram_nerr) + pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR, + info->dram_nerr, info->dram_nerr); + + pci_write_config_dword(dev, E752X_NERR_GLOBAL, + info->nerr_global); + } +} + +static int e752x_process_error_info (struct mem_ctl_info *mci, + struct e752x_error_info *info, int handle_errors) +{ + u32 error32, stat32; + int error_found; + + error_found = 0; + error32 = (info->ferr_global >> 18) & 0x3ff; + stat32 = (info->ferr_global >> 4) & 0x7ff; + + if (error32) + global_error(1, error32, &error_found, handle_errors); + + if (stat32) + global_error(0, stat32, &error_found, handle_errors); + + error32 = (info->nerr_global >> 18) & 0x3ff; + stat32 = (info->nerr_global >> 4) & 0x7ff; + + if (error32) + global_error(1, error32, &error_found, handle_errors); + + if (stat32) + global_error(0, stat32, &error_found, handle_errors); + + e752x_check_hub_interface(info, &error_found, handle_errors); + e752x_check_sysbus(info, &error_found, handle_errors); + e752x_check_membuf(info, &error_found, handle_errors); + e752x_check_dram(mci, info, &error_found, handle_errors); + return error_found; +} + +static void e752x_check(struct mem_ctl_info *mci) +{ + struct e752x_error_info info; + debugf3("MC: " __FILE__ ": %s()\n", __func__); + e752x_get_error_info(mci, &info); + e752x_process_error_info(mci, &info, 1); +} + +static int e752x_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + u16 pci_data, stat; + u32 stat32; + u16 stat16; + u8 stat8; + struct mem_ctl_info *mci = NULL; + struct e752x_pvt *pvt = NULL; + u16 ddrcsr; + u32 drc; + int drc_chan; /* Number of channels 0=1chan,1=2chan */ + int drc_drbg; /* DRB granularity 0=64mb,1=128mb */ + int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + u32 dra; + unsigned long last_cumul_size; + struct pci_dev *pres_dev; + struct pci_dev *dev = NULL; + + debugf0("MC: " __FILE__ ": %s(): mci\n", __func__); + debugf0("Starting Probe1\n"); + + /* enable device 0 function 1 */ + pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8); + stat8 |= (1 << 5); + pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); + + /* need to find out the number of channels */ + pci_read_config_dword(pdev, E752X_DRC, &drc); + pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr); + /* FIXME: should check >>12 or 0xf, true for all? */ + /* Dual channel = 1, Single channel = 0 */ + drc_chan = (((ddrcsr >> 12) & 3) == 3); + drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ + drc_ddim = (drc >> 20) & 0x3; + + mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1); + + if (mci == NULL) { + rc = -ENOMEM; + goto fail; + } + + debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + + mci->mtype_cap = MEM_FLAG_RDDR; + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | + EDAC_FLAG_S4ECD4ED; + /* FIXME - what if different memory types are in different csrows? */ + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.5.2.11 $"; + mci->pdev = pdev; + + debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + pvt = (struct e752x_pvt *) mci->pvt_info; + pvt->dev_info = &e752x_devs[dev_idx]; + pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (pvt->bridge_ck == NULL) + pvt->bridge_ck = pci_scan_single_device(pdev->bus, + PCI_DEVFN(0, 1)); + if (pvt->bridge_ck == NULL) { + printk(KERN_ERR "MC: error reporting device not found:" + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); + goto fail; + } + pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); + + debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__); + mci->ctl_name = pvt->dev_info->ctl_name; + mci->edac_check = e752x_check; + mci->ctl_page_to_phys = ctl_page_to_phys; + + /* find out the device types */ + pci_read_config_dword(pdev, E752X_DRA, &dra); + + /* + * The dram row boundary (DRB) reg values are boundary address for + * each DRAM row with a granularity of 64 or 128MB (single/dual + * channel operation). DRB regs are cumulative; therefore DRB7 will + * contain the total memory contained in all eight rows. + */ + for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { + u8 value; + u32 cumul_size; + /* mem_dev 0=x8, 1=x4 */ + int mem_dev = (dra >> (index * 4 + 2)) & 0x3; + struct csrow_info *csrow = &mci->csrows[index]; + + mem_dev = (mem_dev == 2); + pci_read_config_byte(mci->pdev, E752X_DRB + index, &value); + /* convert a 128 or 64 MiB DRB to a page size. */ + cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); + debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", + __func__, index, cumul_size); + if (cumul_size == last_cumul_size) + continue; /* not populated */ + + csrow->first_page = last_cumul_size; + csrow->last_page = cumul_size - 1; + csrow->nr_pages = cumul_size - last_cumul_size; + last_cumul_size = cumul_size; + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; + + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + csrow->edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + csrow->edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + csrow->edac_mode = EDAC_NONE; + } + + /* Fill in the memory map table */ + { + u8 value; + u8 last = 0; + u8 row = 0; + for (index = 0; index < 8; index += 2) { + + pci_read_config_byte(mci->pdev, E752X_DRB + index, + &value); + /* test if there is a dimm in this slot */ + if (value == last) { + /* no dimm in the slot, so flag it as empty */ + pvt->map[index] = 0xff; + pvt->map[index + 1] = 0xff; + } else { /* there is a dimm in the slot */ + pvt->map[index] = row; + row++; + last = value; + /* test the next value to see if the dimm is + double sided */ + pci_read_config_byte(mci->pdev, + E752X_DRB + index + 1, + &value); + pvt->map[index + 1] = (value == last) ? + 0xff : /* the dimm is single sided, + so flag as empty */ + row; /* this is a double sided dimm + to save the next row # */ + row++; + last = value; + } + } + } + + /* set the map type. 1 = normal, 0 = reversed */ + pci_read_config_byte(mci->pdev, E752X_DRM, &stat8); + pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); + + mci->edac_cap |= EDAC_FLAG_NONE; + + debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n", + __func__); + /* load the top of low memory, remap base, and remap limit vars */ + pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data); + pvt->tolm = ((u32) pci_data) << 4; + pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data); + pvt->remapbase = ((u32) pci_data) << 14; + pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data); + pvt->remaplimit = ((u32) pci_data) << 14; + printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); + + if (edac_mc_add_mc(mci)) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", + __func__); + goto fail; + } + + /* Walk through the PCI table and clear errors */ + switch (dev_idx) { + case E7520: + dev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_7520_0, NULL); + break; + case E7525: + dev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_7525_0, NULL); + break; + case E7320: + dev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_7320_0, NULL); + break; + } + + + pvt->dev_d0f0 = dev; + for (pres_dev = dev; + ((struct pci_dev *) pres_dev->global_list.next != dev); + pres_dev = (struct pci_dev *) pres_dev->global_list.next) { + pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32); + stat = (u16) (stat32 >> 16); + /* clear any error bits */ + if (stat32 & ((1 << 6) + (1 << 8))) + pci_write_config_word(pres_dev, PCI_STATUS, stat); + } + /* find the error reporting device and clear errors */ + dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); + /* Turn off error disable & SMI in case the BIOS turned it on */ + pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00); + pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00); + pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00); + pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00); + pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00); + pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); + pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); + pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); + /* clear other MCH errors */ + pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32); + pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32); + pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32); + pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32); + pci_read_config_byte(dev, E752X_HI_FERR, &stat8); + pci_write_config_byte(dev, E752X_HI_FERR, stat8); + pci_read_config_byte(dev, E752X_HI_NERR, &stat8); + pci_write_config_byte(dev, E752X_HI_NERR, stat8); + pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32); + pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32); + pci_read_config_byte(dev, E752X_BUF_FERR, &stat8); + pci_write_config_byte(dev, E752X_BUF_FERR, stat8); + pci_read_config_byte(dev, E752X_BUF_NERR, &stat8); + pci_write_config_byte(dev, E752X_BUF_NERR, stat8); + pci_read_config_word(dev, E752X_DRAM_FERR, &stat16); + pci_write_config_word(dev, E752X_DRAM_FERR, stat16); + pci_read_config_word(dev, E752X_DRAM_NERR, &stat16); + pci_write_config_word(dev, E752X_DRAM_NERR, stat16); + + /* get this far and it's successful */ + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + return 0; + +fail: + if (mci) { + if (pvt->dev_d0f0) + pci_dev_put(pvt->dev_d0f0); + if (pvt->dev_d0f1) + pci_dev_put(pvt->dev_d0f1); + if (pvt->bridge_ck) + pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); + } + return rc; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit e752x_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* wake up and enable device */ + if(pci_enable_device(pdev) < 0) + return -EIO; + return e752x_probe1(pdev, ent->driver_data); +} + + +static void __devexit e752x_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + struct e752x_pvt *pvt; + + debugf0(__FILE__ ": %s()\n", __func__); + + if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) + return; + + if (edac_mc_del_mc(mci)) + return; + + pvt = (struct e752x_pvt *) mci->pvt_info; + pci_dev_put(pvt->dev_d0f0); + pci_dev_put(pvt->dev_d0f1); + pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); +} + + +static const struct pci_device_id e752x_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7520}, + {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7525}, + {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7320}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); + + +static struct pci_driver e752x_driver = { + .name = BS_MOD_STR, + .probe = e752x_init_one, + .remove = __devexit_p(e752x_remove_one), + .id_table = e752x_pci_tbl, +}; + + +static int __init e752x_init(void) +{ + int pci_rc; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + pci_rc = pci_register_driver(&e752x_driver); + return (pci_rc < 0) ? pci_rc : 0; +} + + +static void __exit e752x_exit(void) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + pci_unregister_driver(&e752x_driver); +} + + +module_init(e752x_init); +module_exit(e752x_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n"); +MODULE_DESCRIPTION("MC support for Intel e752x memory controllers"); diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c new file mode 100644 index 000000000000..d5e320dfc66f --- /dev/null +++ b/drivers/edac/e7xxx_edac.c @@ -0,0 +1,558 @@ +/* + * Intel e7xxx Memory Controller kernel module + * (C) 2003 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * See "enum e7xxx_chips" below for supported chipsets + * + * Written by Thayne Harbaugh + * Based on work by Dan Hollis <goemon at anime dot net> and others. + * http://www.anime.net/~goemon/linux-ecc/ + * + * Contributors: + * Eric Biederman (Linux Networx) + * Tom Zimmerman (Linux Networx) + * Jim Garlick (Lawrence Livermore National Labs) + * Dave Peterson (Lawrence Livermore National Labs) + * That One Guy (Some other place) + * Wang Zhenyu (intel.com) + * + * $Id: edac_e7xxx.c,v 1.5.2.9 2005/10/05 00:43:44 dsp_llnl Exp $ + * + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/slab.h> +#include "edac_mc.h" + + +#ifndef PCI_DEVICE_ID_INTEL_7205_0 +#define PCI_DEVICE_ID_INTEL_7205_0 0x255d +#endif /* PCI_DEVICE_ID_INTEL_7205_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7205_1_ERR +#define PCI_DEVICE_ID_INTEL_7205_1_ERR 0x2551 +#endif /* PCI_DEVICE_ID_INTEL_7205_1_ERR */ + +#ifndef PCI_DEVICE_ID_INTEL_7500_0 +#define PCI_DEVICE_ID_INTEL_7500_0 0x2540 +#endif /* PCI_DEVICE_ID_INTEL_7500_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7500_1_ERR +#define PCI_DEVICE_ID_INTEL_7500_1_ERR 0x2541 +#endif /* PCI_DEVICE_ID_INTEL_7500_1_ERR */ + +#ifndef PCI_DEVICE_ID_INTEL_7501_0 +#define PCI_DEVICE_ID_INTEL_7501_0 0x254c +#endif /* PCI_DEVICE_ID_INTEL_7501_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7501_1_ERR +#define PCI_DEVICE_ID_INTEL_7501_1_ERR 0x2541 +#endif /* PCI_DEVICE_ID_INTEL_7501_1_ERR */ + +#ifndef PCI_DEVICE_ID_INTEL_7505_0 +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 +#endif /* PCI_DEVICE_ID_INTEL_7505_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_7505_1_ERR +#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551 +#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */ + + +#define E7XXX_NR_CSROWS 8 /* number of csrows */ +#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */ + + +/* E7XXX register addresses - device 0 function 0 */ +#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */ +#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */ + /* + * 31 Device width row 7 0=x8 1=x4 + * 27 Device width row 6 + * 23 Device width row 5 + * 19 Device width row 4 + * 15 Device width row 3 + * 11 Device width row 2 + * 7 Device width row 1 + * 3 Device width row 0 + */ +#define E7XXX_DRC 0x7C /* DRAM controller mode reg (32b) */ + /* + * 22 Number channels 0=1,1=2 + * 19:18 DRB Granularity 32/64MB + */ +#define E7XXX_TOLM 0xC4 /* DRAM top of low memory reg (16b) */ +#define E7XXX_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */ +#define E7XXX_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */ + +/* E7XXX register addresses - device 0 function 1 */ +#define E7XXX_DRAM_FERR 0x80 /* DRAM first error register (8b) */ +#define E7XXX_DRAM_NERR 0x82 /* DRAM next error register (8b) */ +#define E7XXX_DRAM_CELOG_ADD 0xA0 /* DRAM first correctable memory */ + /* error address register (32b) */ + /* + * 31:28 Reserved + * 27:6 CE address (4k block 33:12) + * 5:0 Reserved + */ +#define E7XXX_DRAM_UELOG_ADD 0xB0 /* DRAM first uncorrectable memory */ + /* error address register (32b) */ + /* + * 31:28 Reserved + * 27:6 CE address (4k block 33:12) + * 5:0 Reserved + */ +#define E7XXX_DRAM_CELOG_SYNDROME 0xD0 /* DRAM first correctable memory */ + /* error syndrome register (16b) */ + +enum e7xxx_chips { + E7500 = 0, + E7501, + E7505, + E7205, +}; + + +struct e7xxx_pvt { + struct pci_dev *bridge_ck; + u32 tolm; + u32 remapbase; + u32 remaplimit; + const struct e7xxx_dev_info *dev_info; +}; + + +struct e7xxx_dev_info { + u16 err_dev; + const char *ctl_name; +}; + + +struct e7xxx_error_info { + u8 dram_ferr; + u8 dram_nerr; + u32 dram_celog_add; + u16 dram_celog_syndrome; + u32 dram_uelog_add; +}; + +static const struct e7xxx_dev_info e7xxx_devs[] = { + [E7500] = { + .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, + .ctl_name = "E7500"}, + [E7501] = { + .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, + .ctl_name = "E7501"}, + [E7505] = { + .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, + .ctl_name = "E7505"}, + [E7205] = { + .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, + .ctl_name = "E7205"}, +}; + + +/* FIXME - is this valid for both SECDED and S4ECD4ED? */ +static inline int e7xxx_find_channel(u16 syndrome) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + if ((syndrome & 0xff00) == 0) + return 0; + if ((syndrome & 0x00ff) == 0) + return 1; + if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0) + return 0; + return 1; +} + + +static unsigned long +ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) +{ + u32 remap; + struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + if ((page < pvt->tolm) || + ((page >= 0x100000) && (page < pvt->remapbase))) + return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) + return remap; + printk(KERN_ERR "Invalid page %lx - out of range\n", page); + return pvt->tolm - 1; +} + + +static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +{ + u32 error_1b, page; + u16 syndrome; + int row; + int channel; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + /* read the error address */ + error_1b = info->dram_celog_add; + /* FIXME - should use PAGE_SHIFT */ + page = error_1b >> 6; /* convert the address to 4k page */ + /* read the syndrome */ + syndrome = info->dram_celog_syndrome; + /* FIXME - check for -1 */ + row = edac_mc_find_csrow_by_page(mci, page); + /* convert syndrome to channel */ + channel = e7xxx_find_channel(syndrome); + edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, + "e7xxx CE"); +} + + +static void process_ce_no_info(struct mem_ctl_info *mci) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); +} + + +static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +{ + u32 error_2b, block_page; + int row; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + /* read the error address */ + error_2b = info->dram_uelog_add; + /* FIXME - should use PAGE_SHIFT */ + block_page = error_2b >> 6; /* convert to 4k address */ + row = edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE"); +} + + +static void process_ue_no_info(struct mem_ctl_info *mci) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); +} + + +static void e7xxx_get_error_info (struct mem_ctl_info *mci, + struct e7xxx_error_info *info) +{ + struct e7xxx_pvt *pvt; + + pvt = (struct e7xxx_pvt *) mci->pvt_info; + pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR, + &info->dram_ferr); + pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR, + &info->dram_nerr); + + if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) { + pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD, + &info->dram_celog_add); + pci_read_config_word(pvt->bridge_ck, + E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome); + } + + if ((info->dram_ferr & 2) || (info->dram_nerr & 2)) + pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD, + &info->dram_uelog_add); + + if (info->dram_ferr & 3) + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, + 0x03); + + if (info->dram_nerr & 3) + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, + 0x03); +} + + +static int e7xxx_process_error_info (struct mem_ctl_info *mci, + struct e7xxx_error_info *info, int handle_errors) +{ + int error_found; + + error_found = 0; + + /* decode and report errors */ + if (info->dram_ferr & 1) { /* check first error correctable */ + error_found = 1; + + if (handle_errors) + process_ce(mci, info); + } + + if (info->dram_ferr & 2) { /* check first error uncorrectable */ + error_found = 1; + + if (handle_errors) + process_ue(mci, info); + } + + if (info->dram_nerr & 1) { /* check next error correctable */ + error_found = 1; + + if (handle_errors) { + if (info->dram_ferr & 1) + process_ce_no_info(mci); + else + process_ce(mci, info); + } + } + + if (info->dram_nerr & 2) { /* check next error uncorrectable */ + error_found = 1; + + if (handle_errors) { + if (info->dram_ferr & 2) + process_ue_no_info(mci); + else + process_ue(mci, info); + } + } + + return error_found; +} + + +static void e7xxx_check(struct mem_ctl_info *mci) +{ + struct e7xxx_error_info info; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + e7xxx_get_error_info(mci, &info); + e7xxx_process_error_info(mci, &info, 1); +} + + +static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + u16 pci_data; + struct mem_ctl_info *mci = NULL; + struct e7xxx_pvt *pvt = NULL; + u32 drc; + int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */ + int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */ + int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + u32 dra; + unsigned long last_cumul_size; + + + debugf0("MC: " __FILE__ ": %s(): mci\n", __func__); + + /* need to find out the number of channels */ + pci_read_config_dword(pdev, E7XXX_DRC, &drc); + /* only e7501 can be single channel */ + if (dev_idx == E7501) { + drc_chan = ((drc >> 22) & 0x1); + drc_drbg = (drc >> 18) & 0x3; + } + drc_ddim = (drc >> 20) & 0x3; + + mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1); + + if (mci == NULL) { + rc = -ENOMEM; + goto fail; + } + + debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + + mci->mtype_cap = MEM_FLAG_RDDR; + mci->edac_ctl_cap = + EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; + /* FIXME - what if different memory types are in different csrows? */ + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.5.2.9 $"; + mci->pdev = pdev; + + debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + pvt = (struct e7xxx_pvt *) mci->pvt_info; + pvt->dev_info = &e7xxx_devs[dev_idx]; + pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (!pvt->bridge_ck) { + printk(KERN_ERR + "MC: error reporting device not found:" + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); + goto fail; + } + + debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__); + mci->ctl_name = pvt->dev_info->ctl_name; + + mci->edac_check = e7xxx_check; + mci->ctl_page_to_phys = ctl_page_to_phys; + + /* find out the device types */ + pci_read_config_dword(pdev, E7XXX_DRA, &dra); + + /* + * The dram row boundary (DRB) reg values are boundary address + * for each DRAM row with a granularity of 32 or 64MB (single/dual + * channel operation). DRB regs are cumulative; therefore DRB7 will + * contain the total memory contained in all eight rows. + */ + for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { + u8 value; + u32 cumul_size; + /* mem_dev 0=x8, 1=x4 */ + int mem_dev = (dra >> (index * 4 + 3)) & 0x1; + struct csrow_info *csrow = &mci->csrows[index]; + + pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value); + /* convert a 64 or 32 MiB DRB to a page size. */ + cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); + debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", + __func__, index, cumul_size); + if (cumul_size == last_cumul_size) + continue; /* not populated */ + + csrow->first_page = last_cumul_size; + csrow->last_page = cumul_size - 1; + csrow->nr_pages = cumul_size - last_cumul_size; + last_cumul_size = cumul_size; + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; + + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + csrow->edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + csrow->edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + csrow->edac_mode = EDAC_NONE; + } + + mci->edac_cap |= EDAC_FLAG_NONE; + + debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n", + __func__); + /* load the top of low memory, remap base, and remap limit vars */ + pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data); + pvt->tolm = ((u32) pci_data) << 4; + pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data); + pvt->remapbase = ((u32) pci_data) << 14; + pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data); + pvt->remaplimit = ((u32) pci_data) << 14; + printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); + + /* clear any pending errors, or initial state bits */ + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); + + if (edac_mc_add_mc(mci) != 0) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", + __func__); + goto fail; + } + + /* get this far and it's successful */ + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + return 0; + +fail: + if (mci != NULL) { + if(pvt != NULL && pvt->bridge_ck) + pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); + } + + return rc; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit +e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* wake up and enable device */ + return pci_enable_device(pdev) ? + -EIO : e7xxx_probe1(pdev, ent->driver_data); +} + + +static void __devexit e7xxx_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + struct e7xxx_pvt *pvt; + + debugf0(__FILE__ ": %s()\n", __func__); + + if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) && + edac_mc_del_mc(mci)) { + pvt = (struct e7xxx_pvt *) mci->pvt_info; + pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); + } +} + + +static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7205}, + {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7500}, + {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7501}, + {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7505}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); + + +static struct pci_driver e7xxx_driver = { + .name = BS_MOD_STR, + .probe = e7xxx_init_one, + .remove = __devexit_p(e7xxx_remove_one), + .id_table = e7xxx_pci_tbl, +}; + + +static int __init e7xxx_init(void) +{ + return pci_register_driver(&e7xxx_driver); +} + + +static void __exit e7xxx_exit(void) +{ + pci_unregister_driver(&e7xxx_driver); +} + +module_init(e7xxx_init); +module_exit(e7xxx_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" + "Based on.work by Dan Hollis et al"); +MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers"); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c new file mode 100644 index 000000000000..b10ee4698b1d --- /dev/null +++ b/drivers/edac/edac_mc.c @@ -0,0 +1,2208 @@ +/* + * edac_mc kernel module + * (C) 2005 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh + * Based on work by Dan Hollis <goemon at anime dot net> and others. + * http://www.anime.net/~goemon/linux-ecc/ + * + * Modified by Dave Peterson and Doug Thompson + * + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/smp.h> +#include <linux/init.h> +#include <linux/sysctl.h> +#include <linux/highmem.h> +#include <linux/timer.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/sysdev.h> +#include <linux/ctype.h> + +#include <asm/uaccess.h> +#include <asm/page.h> +#include <asm/edac.h> + +#include "edac_mc.h" + +#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__ + +#ifdef CONFIG_EDAC_DEBUG +/* Values of 0 to 4 will generate output */ +int edac_debug_level = 1; +EXPORT_SYMBOL(edac_debug_level); +#endif + +/* EDAC Controls, setable by module parameter, and sysfs */ +static int log_ue = 1; +static int log_ce = 1; +static int panic_on_ue = 1; +static int poll_msec = 1000; + +static int check_pci_parity = 0; /* default YES check PCI parity */ +static int panic_on_pci_parity; /* default no panic on PCI Parity */ +static atomic_t pci_parity_count = ATOMIC_INIT(0); + +/* lock to memory controller's control array */ +static DECLARE_MUTEX(mem_ctls_mutex); +static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); + +/* Structure of the whitelist and blacklist arrays */ +struct edac_pci_device_list { + unsigned int vendor; /* Vendor ID */ + unsigned int device; /* Deviice ID */ +}; + + +#define MAX_LISTED_PCI_DEVICES 32 + +/* List of PCI devices (vendor-id:device-id) that should be skipped */ +static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES]; +static int pci_blacklist_count; + +/* List of PCI devices (vendor-id:device-id) that should be scanned */ +static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES]; +static int pci_whitelist_count ; + +/* START sysfs data and methods */ + +static const char *mem_types[] = { + [MEM_EMPTY] = "Empty", + [MEM_RESERVED] = "Reserved", + [MEM_UNKNOWN] = "Unknown", + [MEM_FPM] = "FPM", + [MEM_EDO] = "EDO", + [MEM_BEDO] = "BEDO", + [MEM_SDR] = "Unbuffered-SDR", + [MEM_RDR] = "Registered-SDR", + [MEM_DDR] = "Unbuffered-DDR", + [MEM_RDDR] = "Registered-DDR", + [MEM_RMBS] = "RMBS" +}; + +static const char *dev_types[] = { + [DEV_UNKNOWN] = "Unknown", + [DEV_X1] = "x1", + [DEV_X2] = "x2", + [DEV_X4] = "x4", + [DEV_X8] = "x8", + [DEV_X16] = "x16", + [DEV_X32] = "x32", + [DEV_X64] = "x64" +}; + +static const char *edac_caps[] = { + [EDAC_UNKNOWN] = "Unknown", + [EDAC_NONE] = "None", + [EDAC_RESERVED] = "Reserved", + [EDAC_PARITY] = "PARITY", + [EDAC_EC] = "EC", + [EDAC_SECDED] = "SECDED", + [EDAC_S2ECD2ED] = "S2ECD2ED", + [EDAC_S4ECD4ED] = "S4ECD4ED", + [EDAC_S8ECD8ED] = "S8ECD8ED", + [EDAC_S16ECD16ED] = "S16ECD16ED" +}; + + +/* sysfs object: /sys/devices/system/edac */ +static struct sysdev_class edac_class = { + set_kset_name("edac"), +}; + +/* sysfs objects: + * /sys/devices/system/edac/mc + * /sys/devices/system/edac/pci + */ +static struct kobject edac_memctrl_kobj; +static struct kobject edac_pci_kobj; + +/* + * /sys/devices/system/edac/mc; + * data structures and methods + */ +static ssize_t memctrl_string_show(void *ptr, char *buffer) +{ + char *value = (char*) ptr; + return sprintf(buffer, "%s\n", value); +} + +static ssize_t memctrl_int_show(void *ptr, char *buffer) +{ + int *value = (int*) ptr; + return sprintf(buffer, "%d\n", *value); +} + +static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) +{ + int *value = (int*) ptr; + + if (isdigit(*buffer)) + *value = simple_strtoul(buffer, NULL, 0); + + return count; +} + +struct memctrl_dev_attribute { + struct attribute attr; + void *value; + ssize_t (*show)(void *,char *); + ssize_t (*store)(void *, const char *, size_t); +}; + +/* Set of show/store abstract level functions for memory control object */ +static ssize_t +memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer) +{ + struct memctrl_dev_attribute *memctrl_dev; + memctrl_dev = (struct memctrl_dev_attribute*)attr; + + if (memctrl_dev->show) + return memctrl_dev->show(memctrl_dev->value, buffer); + return -EIO; +} + +static ssize_t +memctrl_dev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct memctrl_dev_attribute *memctrl_dev; + memctrl_dev = (struct memctrl_dev_attribute*)attr; + + if (memctrl_dev->store) + return memctrl_dev->store(memctrl_dev->value, buffer, count); + return -EIO; +} + +static struct sysfs_ops memctrlfs_ops = { + .show = memctrl_dev_show, + .store = memctrl_dev_store +}; + +#define MEMCTRL_ATTR(_name,_mode,_show,_store) \ +struct memctrl_dev_attribute attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .value = &_name, \ + .show = _show, \ + .store = _store, \ +}; + +#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \ +struct memctrl_dev_attribute attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .value = _data, \ + .show = _show, \ + .store = _store, \ +}; + +/* cwrow<id> attribute f*/ +MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL); + +/* csrow<id> control files */ +MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); +MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); +MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); +MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); + + +/* Base Attributes of the memory ECC object */ +static struct memctrl_dev_attribute *memctrl_attr[] = { + &attr_panic_on_ue, + &attr_log_ue, + &attr_log_ce, + &attr_poll_msec, + &attr_mc_version, + NULL, +}; + +/* Main MC kobject release() function */ +static void edac_memctrl_master_release(struct kobject *kobj) +{ + debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__); +} + +static struct kobj_type ktype_memctrl = { + .release = edac_memctrl_master_release, + .sysfs_ops = &memctrlfs_ops, + .default_attrs = (struct attribute **) memctrl_attr, +}; + + +/* Initialize the main sysfs entries for edac: + * /sys/devices/system/edac + * + * and children + * + * Return: 0 SUCCESS + * !0 FAILURE + */ +static int edac_sysfs_memctrl_setup(void) +{ + int err=0; + + debugf1("MC: " __FILE__ ": %s()\n", __func__); + + /* create the /sys/devices/system/edac directory */ + err = sysdev_class_register(&edac_class); + if (!err) { + /* Init the MC's kobject */ + memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); + kobject_init(&edac_memctrl_kobj); + + edac_memctrl_kobj.parent = &edac_class.kset.kobj; + edac_memctrl_kobj.ktype = &ktype_memctrl; + + /* generate sysfs "..../edac/mc" */ + err = kobject_set_name(&edac_memctrl_kobj,"mc"); + if (!err) { + /* FIXME: maybe new sysdev_create_subdir() */ + err = kobject_register(&edac_memctrl_kobj); + if (err) { + debugf1("Failed to register '.../edac/mc'\n"); + } else { + debugf1("Registered '.../edac/mc' kobject\n"); + } + } + } else { + debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err); + } + + return err; +} + +/* + * MC teardown: + * the '..../edac/mc' kobject followed by '..../edac' itself + */ +static void edac_sysfs_memctrl_teardown(void) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* Unregister the MC's kobject */ + kobject_unregister(&edac_memctrl_kobj); + + /* release the master edac mc kobject */ + kobject_put(&edac_memctrl_kobj); + + /* Unregister the 'edac' object */ + sysdev_class_unregister(&edac_class); +} + +/* + * /sys/devices/system/edac/pci; + * data structures and methods + */ + +struct list_control { + struct edac_pci_device_list *list; + int *count; +}; + +/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */ +static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) +{ + struct list_control *listctl; + struct edac_pci_device_list *list; + char *p = buffer; + int len=0; + int i; + + listctl = ptr; + list = listctl->list; + + for (i = 0; i < *(listctl->count); i++, list++ ) { + if (len > 0) + len += snprintf(p + len, (PAGE_SIZE-len), ","); + + len += snprintf(p + len, + (PAGE_SIZE-len), + "%x:%x", + list->vendor,list->device); + } + + len += snprintf(p + len,(PAGE_SIZE-len), "\n"); + + return (ssize_t) len; +} + +/** + * + * Scan string from **s to **e looking for one 'vendor:device' tuple + * where each field is a hex value + * + * return 0 if an entry is NOT found + * return 1 if an entry is found + * fill in *vendor_id and *device_id with values found + * + * In both cases, make sure *s has been moved forward toward *e + */ +static int parse_one_device(const char **s,const char **e, + unsigned int *vendor_id, unsigned int *device_id) +{ + const char *runner, *p; + + /* if null byte, we are done */ + if (!**s) { + (*s)++; /* keep *s moving */ + return 0; + } + + /* skip over newlines & whitespace */ + if ((**s == '\n') || isspace(**s)) { + (*s)++; + return 0; + } + + if (!isxdigit(**s)) { + (*s)++; + return 0; + } + + /* parse vendor_id */ + runner = *s; + while (runner < *e) { + /* scan for vendor:device delimiter */ + if (*runner == ':') { + *vendor_id = simple_strtol((char*) *s, (char**) &p, 16); + runner = p + 1; + break; + } + runner++; + } + + if (!isxdigit(*runner)) { + *s = ++runner; + return 0; + } + + /* parse device_id */ + if (runner < *e) { + *device_id = simple_strtol((char*)runner, (char**)&p, 16); + runner = p; + } + + *s = runner; + + return 1; +} + +static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, + size_t count) +{ + struct list_control *listctl; + struct edac_pci_device_list *list; + unsigned int vendor_id, device_id; + const char *s, *e; + int *index; + + s = (char*)buffer; + e = s + count; + + listctl = ptr; + list = listctl->list; + index = listctl->count; + + *index = 0; + while (*index < MAX_LISTED_PCI_DEVICES) { + + if (parse_one_device(&s,&e,&vendor_id,&device_id)) { + list[ *index ].vendor = vendor_id; + list[ *index ].device = device_id; + (*index)++; + } + + /* check for all data consume */ + if (s >= e) + break; + } + + return count; +} + +static ssize_t edac_pci_int_show(void *ptr, char *buffer) +{ + int *value = ptr; + return sprintf(buffer,"%d\n",*value); +} + +static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count) +{ + int *value = ptr; + + if (isdigit(*buffer)) + *value = simple_strtoul(buffer,NULL,0); + + return count; +} + +struct edac_pci_dev_attribute { + struct attribute attr; + void *value; + ssize_t (*show)(void *,char *); + ssize_t (*store)(void *, const char *,size_t); +}; + +/* Set of show/store abstract level functions for PCI Parity object */ +static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, + char *buffer) +{ + struct edac_pci_dev_attribute *edac_pci_dev; + edac_pci_dev= (struct edac_pci_dev_attribute*)attr; + + if (edac_pci_dev->show) + return edac_pci_dev->show(edac_pci_dev->value, buffer); + return -EIO; +} + +static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct edac_pci_dev_attribute *edac_pci_dev; + edac_pci_dev= (struct edac_pci_dev_attribute*)attr; + + if (edac_pci_dev->show) + return edac_pci_dev->store(edac_pci_dev->value, buffer, count); + return -EIO; +} + +static struct sysfs_ops edac_pci_sysfs_ops = { + .show = edac_pci_dev_show, + .store = edac_pci_dev_store +}; + + +#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \ +struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .value = &_name, \ + .show = _show, \ + .store = _store, \ +}; + +#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \ +struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .value = _data, \ + .show = _show, \ + .store = _store, \ +}; + +static struct list_control pci_whitelist_control = { + .list = pci_whitelist, + .count = &pci_whitelist_count +}; + +static struct list_control pci_blacklist_control = { + .list = pci_blacklist, + .count = &pci_blacklist_count +}; + +/* whitelist attribute */ +EDAC_PCI_STRING_ATTR(pci_parity_whitelist, + &pci_whitelist_control, + S_IRUGO|S_IWUSR, + edac_pci_list_string_show, + edac_pci_list_string_store); + +EDAC_PCI_STRING_ATTR(pci_parity_blacklist, + &pci_blacklist_control, + S_IRUGO|S_IWUSR, + edac_pci_list_string_show, + edac_pci_list_string_store); + +/* PCI Parity control files */ +EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); +EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); +EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL); + +/* Base Attributes of the memory ECC object */ +static struct edac_pci_dev_attribute *edac_pci_attr[] = { + &edac_pci_attr_check_pci_parity, + &edac_pci_attr_panic_on_pci_parity, + &edac_pci_attr_pci_parity_count, + &edac_pci_attr_pci_parity_whitelist, + &edac_pci_attr_pci_parity_blacklist, + NULL, +}; + +/* No memory to release */ +static void edac_pci_release(struct kobject *kobj) +{ + debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__); +} + +static struct kobj_type ktype_edac_pci = { + .release = edac_pci_release, + .sysfs_ops = &edac_pci_sysfs_ops, + .default_attrs = (struct attribute **) edac_pci_attr, +}; + +/** + * edac_sysfs_pci_setup() + * + */ +static int edac_sysfs_pci_setup(void) +{ + int err; + + debugf1("MC: " __FILE__ ": %s()\n", __func__); + + memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); + + kobject_init(&edac_pci_kobj); + edac_pci_kobj.parent = &edac_class.kset.kobj; + edac_pci_kobj.ktype = &ktype_edac_pci; + + err = kobject_set_name(&edac_pci_kobj, "pci"); + if (!err) { + /* Instanstiate the csrow object */ + /* FIXME: maybe new sysdev_create_subdir() */ + err = kobject_register(&edac_pci_kobj); + if (err) + debugf1("Failed to register '.../edac/pci'\n"); + else + debugf1("Registered '.../edac/pci' kobject\n"); + } + return err; +} + + +static void edac_sysfs_pci_teardown(void) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + kobject_unregister(&edac_pci_kobj); + kobject_put(&edac_pci_kobj); +} + +/* EDAC sysfs CSROW data structures and methods */ + +/* Set of more detailed csrow<id> attribute show/store functions */ +static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data) +{ + ssize_t size = 0; + + if (csrow->nr_channels > 0) { + size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n", + csrow->channels[0].label); + } + return size; +} + +static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data) +{ + ssize_t size = 0; + + if (csrow->nr_channels > 0) { + size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", + csrow->channels[1].label); + } + return size; +} + +static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, + const char *data, size_t size) +{ + ssize_t max_size = 0; + + if (csrow->nr_channels > 0) { + max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1); + strncpy(csrow->channels[0].label, data, max_size); + csrow->channels[0].label[max_size] = '\0'; + } + return size; +} + +static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, + const char *data, size_t size) +{ + ssize_t max_size = 0; + + if (csrow->nr_channels > 1) { + max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1); + strncpy(csrow->channels[1].label, data, max_size); + csrow->channels[1].label[max_size] = '\0'; + } + return max_size; +} + +static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%u\n", csrow->ue_count); +} + +static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%u\n", csrow->ce_count); +} + +static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data) +{ + ssize_t size = 0; + + if (csrow->nr_channels > 0) { + size = sprintf(data,"%u\n", csrow->channels[0].ce_count); + } + return size; +} + +static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data) +{ + ssize_t size = 0; + + if (csrow->nr_channels > 1) { + size = sprintf(data,"%u\n", csrow->channels[1].ce_count); + } + return size; +} + +static ssize_t csrow_size_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages)); +} + +static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%s\n", mem_types[csrow->mtype]); +} + +static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%s\n", dev_types[csrow->dtype]); +} + +static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data) +{ + return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]); +} + +struct csrowdev_attribute { + struct attribute attr; + ssize_t (*show)(struct csrow_info *,char *); + ssize_t (*store)(struct csrow_info *, const char *,size_t); +}; + +#define to_csrow(k) container_of(k, struct csrow_info, kobj) +#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr) + +/* Set of show/store higher level functions for csrow objects */ +static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr, + char *buffer) +{ + struct csrow_info *csrow = to_csrow(kobj); + struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); + + if (csrowdev_attr->show) + return csrowdev_attr->show(csrow, buffer); + return -EIO; +} + +static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct csrow_info *csrow = to_csrow(kobj); + struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr); + + if (csrowdev_attr->store) + return csrowdev_attr->store(csrow, buffer, count); + return -EIO; +} + +static struct sysfs_ops csrowfs_ops = { + .show = csrowdev_show, + .store = csrowdev_store +}; + +#define CSROWDEV_ATTR(_name,_mode,_show,_store) \ +struct csrowdev_attribute attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +}; + +/* cwrow<id>/attribute files */ +CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL); +CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL); +CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL); +CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL); +CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL); +CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL); +CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL); +CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL); + +/* control/attribute files */ +CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR, + csrow_ch0_dimm_label_show, + csrow_ch0_dimm_label_store); +CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR, + csrow_ch1_dimm_label_show, + csrow_ch1_dimm_label_store); + + +/* Attributes of the CSROW<id> object */ +static struct csrowdev_attribute *csrow_attr[] = { + &attr_dev_type, + &attr_mem_type, + &attr_edac_mode, + &attr_size_mb, + &attr_ue_count, + &attr_ce_count, + &attr_ch0_ce_count, + &attr_ch1_ce_count, + &attr_ch0_dimm_label, + &attr_ch1_dimm_label, + NULL, +}; + + +/* No memory to release */ +static void edac_csrow_instance_release(struct kobject *kobj) +{ + debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__); +} + +static struct kobj_type ktype_csrow = { + .release = edac_csrow_instance_release, + .sysfs_ops = &csrowfs_ops, + .default_attrs = (struct attribute **) csrow_attr, +}; + +/* Create a CSROW object under specifed edac_mc_device */ +static int edac_create_csrow_object(struct kobject *edac_mci_kobj, + struct csrow_info *csrow, int index ) +{ + int err = 0; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + memset(&csrow->kobj, 0, sizeof(csrow->kobj)); + + /* generate ..../edac/mc/mc<id>/csrow<index> */ + + kobject_init(&csrow->kobj); + csrow->kobj.parent = edac_mci_kobj; + csrow->kobj.ktype = &ktype_csrow; + + /* name this instance of csrow<id> */ + err = kobject_set_name(&csrow->kobj,"csrow%d",index); + if (!err) { + /* Instanstiate the csrow object */ + err = kobject_register(&csrow->kobj); + if (err) + debugf0("Failed to register CSROW%d\n",index); + else + debugf0("Registered CSROW%d\n",index); + } + + return err; +} + +/* sysfs data structures and methods for the MCI kobjects */ + +static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, + const char *data, size_t count ) +{ + int row, chan; + + mci->ue_noinfo_count = 0; + mci->ce_noinfo_count = 0; + mci->ue_count = 0; + mci->ce_count = 0; + for (row = 0; row < mci->nr_csrows; row++) { + struct csrow_info *ri = &mci->csrows[row]; + + ri->ue_count = 0; + ri->ce_count = 0; + for (chan = 0; chan < ri->nr_channels; chan++) + ri->channels[chan].ce_count = 0; + } + mci->start_time = jiffies; + + return count; +} + +static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%d\n", mci->ue_count); +} + +static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%d\n", mci->ce_count); +} + +static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%d\n", mci->ce_noinfo_count); +} + +static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%d\n", mci->ue_noinfo_count); +} + +static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ); +} + +static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver); +} + +static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) +{ + return sprintf(data,"%s\n", mci->ctl_name); +} + +static int mci_output_edac_cap(char *buf, unsigned long edac_cap) +{ + char *p = buf; + int bit_idx; + + for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) { + if ((edac_cap >> bit_idx) & 0x1) + p += sprintf(p, "%s ", edac_caps[bit_idx]); + } + + return p - buf; +} + +static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data) +{ + char *p = data; + + p += mci_output_edac_cap(p,mci->edac_ctl_cap); + p += sprintf(p, "\n"); + + return p - data; +} + +static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci, + char *data) +{ + char *p = data; + + p += mci_output_edac_cap(p,mci->edac_cap); + p += sprintf(p, "\n"); + + return p - data; +} + +static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap) +{ + char *p = buf; + int bit_idx; + + for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) { + if ((mtype_cap >> bit_idx) & 0x1) + p += sprintf(p, "%s ", mem_types[bit_idx]); + } + + return p - buf; +} + +static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data) +{ + char *p = data; + + p += mci_output_mtype_cap(p,mci->mtype_cap); + p += sprintf(p, "\n"); + + return p - data; +} + +static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) +{ + int total_pages, csrow_idx; + + for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows; + csrow_idx++) { + struct csrow_info *csrow = &mci->csrows[csrow_idx]; + + if (!csrow->nr_pages) + continue; + total_pages += csrow->nr_pages; + } + + return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages)); +} + +struct mcidev_attribute { + struct attribute attr; + ssize_t (*show)(struct mem_ctl_info *,char *); + ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); +}; + +#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj) +#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr) + +static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, + char *buffer) +{ + struct mem_ctl_info *mem_ctl_info = to_mci(kobj); + struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); + + if (mcidev_attr->show) + return mcidev_attr->show(mem_ctl_info, buffer); + return -EIO; +} + +static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct mem_ctl_info *mem_ctl_info = to_mci(kobj); + struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); + + if (mcidev_attr->store) + return mcidev_attr->store(mem_ctl_info, buffer, count); + return -EIO; +} + +static struct sysfs_ops mci_ops = { + .show = mcidev_show, + .store = mcidev_store +}; + +#define MCIDEV_ATTR(_name,_mode,_show,_store) \ +struct mcidev_attribute mci_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +}; + +/* Control file */ +MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store); + +/* Attribute files */ +MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL); +MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL); +MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL); +MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL); +MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL); +MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL); +MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL); +MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL); +MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL); +MCIDEV_ATTR(edac_current_capability,S_IRUGO, + mci_edac_current_capability_show,NULL); +MCIDEV_ATTR(supported_mem_type,S_IRUGO, + mci_supported_mem_type_show,NULL); + + +static struct mcidev_attribute *mci_attr[] = { + &mci_attr_reset_counters, + &mci_attr_module_name, + &mci_attr_mc_name, + &mci_attr_edac_capability, + &mci_attr_edac_current_capability, + &mci_attr_supported_mem_type, + &mci_attr_size_mb, + &mci_attr_seconds_since_reset, + &mci_attr_ue_noinfo_count, + &mci_attr_ce_noinfo_count, + &mci_attr_ue_count, + &mci_attr_ce_count, + NULL +}; + + +/* + * Release of a MC controlling instance + */ +static void edac_mci_instance_release(struct kobject *kobj) +{ + struct mem_ctl_info *mci; + mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj); + + debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n", + __func__, mci->mc_idx); + + kfree(mci); +} + +static struct kobj_type ktype_mci = { + .release = edac_mci_instance_release, + .sysfs_ops = &mci_ops, + .default_attrs = (struct attribute **) mci_attr, +}; + +#define EDAC_DEVICE_SYMLINK "device" + +/* + * Create a new Memory Controller kobject instance, + * mc<id> under the 'mc' directory + * + * Return: + * 0 Success + * !0 Failure + */ +static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) +{ + int i; + int err; + struct csrow_info *csrow; + struct kobject *edac_mci_kobj=&mci->edac_mci_kobj; + + debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx); + + memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj)); + kobject_init(edac_mci_kobj); + + /* set the name of the mc<id> object */ + err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx); + if (err) + return err; + + /* link to our parent the '..../edac/mc' object */ + edac_mci_kobj->parent = &edac_memctrl_kobj; + edac_mci_kobj->ktype = &ktype_mci; + + /* register the mc<id> kobject */ + err = kobject_register(edac_mci_kobj); + if (err) + return err; + + /* create a symlink for the device */ + err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, + EDAC_DEVICE_SYMLINK); + if (err) { + kobject_unregister(edac_mci_kobj); + return err; + } + + /* Make directories for each CSROW object + * under the mc<id> kobject + */ + for (i = 0; i < mci->nr_csrows; i++) { + + csrow = &mci->csrows[i]; + + /* Only expose populated CSROWs */ + if (csrow->nr_pages > 0) { + err = edac_create_csrow_object(edac_mci_kobj,csrow,i); + if (err) + goto fail; + } + } + + /* Mark this MCI instance as having sysfs entries */ + mci->sysfs_active = MCI_SYSFS_ACTIVE; + + return 0; + + + /* CSROW error: backout what has already been registered, */ +fail: + for ( i--; i >= 0; i--) { + if (csrow->nr_pages > 0) { + kobject_unregister(&mci->csrows[i].kobj); + kobject_put(&mci->csrows[i].kobj); + } + } + + kobject_unregister(edac_mci_kobj); + kobject_put(edac_mci_kobj); + + return err; +} + +/* + * remove a Memory Controller instance + */ +static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) +{ + int i; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* remove all csrow kobjects */ + for (i = 0; i < mci->nr_csrows; i++) { + if (mci->csrows[i].nr_pages > 0) { + kobject_unregister(&mci->csrows[i].kobj); + kobject_put(&mci->csrows[i].kobj); + } + } + + sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); + + kobject_unregister(&mci->edac_mci_kobj); + kobject_put(&mci->edac_mci_kobj); +} + +/* END OF sysfs data and methods */ + +#ifdef CONFIG_EDAC_DEBUG + +EXPORT_SYMBOL(edac_mc_dump_channel); + +void edac_mc_dump_channel(struct channel_info *chan) +{ + debugf4("\tchannel = %p\n", chan); + debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx); + debugf4("\tchannel->ce_count = %d\n", chan->ce_count); + debugf4("\tchannel->label = '%s'\n", chan->label); + debugf4("\tchannel->csrow = %p\n\n", chan->csrow); +} + + +EXPORT_SYMBOL(edac_mc_dump_csrow); + +void edac_mc_dump_csrow(struct csrow_info *csrow) +{ + debugf4("\tcsrow = %p\n", csrow); + debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); + debugf4("\tcsrow->first_page = 0x%lx\n", + csrow->first_page); + debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); + debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); + debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages); + debugf4("\tcsrow->nr_channels = %d\n", + csrow->nr_channels); + debugf4("\tcsrow->channels = %p\n", csrow->channels); + debugf4("\tcsrow->mci = %p\n\n", csrow->mci); +} + + +EXPORT_SYMBOL(edac_mc_dump_mci); + +void edac_mc_dump_mci(struct mem_ctl_info *mci) +{ + debugf3("\tmci = %p\n", mci); + debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap); + debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap); + debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap); + debugf4("\tmci->edac_check = %p\n", mci->edac_check); + debugf3("\tmci->nr_csrows = %d, csrows = %p\n", + mci->nr_csrows, mci->csrows); + debugf3("\tpdev = %p\n", mci->pdev); + debugf3("\tmod_name:ctl_name = %s:%s\n", + mci->mod_name, mci->ctl_name); + debugf3("\tpvt_info = %p\n\n", mci->pvt_info); +} + + +#endif /* CONFIG_EDAC_DEBUG */ + +/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. + * Adjust 'ptr' so that its alignment is at least as stringent as what the + * compiler would provide for X and return the aligned result. + * + * If 'size' is a constant, the compiler will optimize this whole function + * down to either a no-op or the addition of a constant to the value of 'ptr'. + */ +static inline char * align_ptr (void *ptr, unsigned size) +{ + unsigned align, r; + + /* Here we assume that the alignment of a "long long" is the most + * stringent alignment that the compiler will ever provide by default. + * As far as I know, this is a reasonable assumption. + */ + if (size > sizeof(long)) + align = sizeof(long long); + else if (size > sizeof(int)) + align = sizeof(long); + else if (size > sizeof(short)) + align = sizeof(int); + else if (size > sizeof(char)) + align = sizeof(short); + else + return (char *) ptr; + + r = size % align; + + if (r == 0) + return (char *) ptr; + + return (char *) (((unsigned long) ptr) + align - r); +} + + +EXPORT_SYMBOL(edac_mc_alloc); + +/** + * edac_mc_alloc: Allocate a struct mem_ctl_info structure + * @size_pvt: size of private storage needed + * @nr_csrows: Number of CWROWS needed for this MC + * @nr_chans: Number of channels for the MC + * + * Everything is kmalloc'ed as one big chunk - more efficient. + * Only can be used if all structures have the same lifetime - otherwise + * you have to allocate and initialize your own structures. + * + * Use edac_mc_free() to free mc structures allocated by this function. + * + * Returns: + * NULL allocation failed + * struct mem_ctl_info pointer + */ +struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, + unsigned nr_chans) +{ + struct mem_ctl_info *mci; + struct csrow_info *csi, *csrow; + struct channel_info *chi, *chp, *chan; + void *pvt; + unsigned size; + int row, chn; + + /* Figure out the offsets of the various items from the start of an mc + * structure. We want the alignment of each item to be at least as + * stringent as what the compiler would provide if we could simply + * hardcode everything into a single struct. + */ + mci = (struct mem_ctl_info *) 0; + csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi)); + chi = (struct channel_info *) + align_ptr(&csi[nr_csrows], sizeof(*chi)); + pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt); + size = ((unsigned long) pvt) + sz_pvt; + + if ((mci = kmalloc(size, GFP_KERNEL)) == NULL) + return NULL; + + /* Adjust pointers so they point within the memory we just allocated + * rather than an imaginary chunk of memory located at address 0. + */ + csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi)); + chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi)); + pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL; + + memset(mci, 0, size); /* clear all fields */ + + mci->csrows = csi; + mci->pvt_info = pvt; + mci->nr_csrows = nr_csrows; + + for (row = 0; row < nr_csrows; row++) { + csrow = &csi[row]; + csrow->csrow_idx = row; + csrow->mci = mci; + csrow->nr_channels = nr_chans; + chp = &chi[row * nr_chans]; + csrow->channels = chp; + + for (chn = 0; chn < nr_chans; chn++) { + chan = &chp[chn]; + chan->chan_idx = chn; + chan->csrow = csrow; + } + } + + return mci; +} + + +EXPORT_SYMBOL(edac_mc_free); + +/** + * edac_mc_free: Free a previously allocated 'mci' structure + * @mci: pointer to a struct mem_ctl_info structure + * + * Free up a previously allocated mci structure + * A MCI structure can be in 2 states after being allocated + * by edac_mc_alloc(). + * 1) Allocated in a MC driver's probe, but not yet committed + * 2) Allocated and committed, by a call to edac_mc_add_mc() + * edac_mc_add_mc() is the function that adds the sysfs entries + * thus, this free function must determine which state the 'mci' + * structure is in, then either free it directly or + * perform kobject cleanup by calling edac_remove_sysfs_mci_device(). + * + * VOID Return + */ +void edac_mc_free(struct mem_ctl_info *mci) +{ + /* only if sysfs entries for this mci instance exist + * do we remove them and defer the actual kfree via + * the kobject 'release()' callback. + * + * Otherwise, do a straight kfree now. + */ + if (mci->sysfs_active == MCI_SYSFS_ACTIVE) + edac_remove_sysfs_mci_device(mci); + else + kfree(mci); +} + + + +EXPORT_SYMBOL(edac_mc_find_mci_by_pdev); + +struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + struct list_head *item; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + list_for_each(item, &mc_devices) { + mci = list_entry(item, struct mem_ctl_info, link); + + if (mci->pdev == pdev) + return mci; + } + + return NULL; +} + +static int add_mc_to_global_list (struct mem_ctl_info *mci) +{ + struct list_head *item, *insert_before; + struct mem_ctl_info *p; + int i; + + if (list_empty(&mc_devices)) { + mci->mc_idx = 0; + insert_before = &mc_devices; + } else { + if (edac_mc_find_mci_by_pdev(mci->pdev)) { + printk(KERN_WARNING + "EDAC MC: %s (%s) %s %s already assigned %d\n", + mci->pdev->dev.bus_id, pci_name(mci->pdev), + mci->mod_name, mci->ctl_name, mci->mc_idx); + return 1; + } + + insert_before = NULL; + i = 0; + + list_for_each(item, &mc_devices) { + p = list_entry(item, struct mem_ctl_info, link); + + if (p->mc_idx != i) { + insert_before = item; + break; + } + + i++; + } + + mci->mc_idx = i; + + if (insert_before == NULL) + insert_before = &mc_devices; + } + + list_add_tail_rcu(&mci->link, insert_before); + return 0; +} + + + +EXPORT_SYMBOL(edac_mc_add_mc); + +/** + * edac_mc_add_mc: Insert the 'mci' structure into the mci global list + * @mci: pointer to the mci structure to be added to the list + * + * Return: + * 0 Success + * !0 Failure + */ + +/* FIXME - should a warning be printed if no error detection? correction? */ +int edac_mc_add_mc(struct mem_ctl_info *mci) +{ + int rc = 1; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); +#ifdef CONFIG_EDAC_DEBUG + if (edac_debug_level >= 3) + edac_mc_dump_mci(mci); + if (edac_debug_level >= 4) { + int i; + + for (i = 0; i < mci->nr_csrows; i++) { + int j; + edac_mc_dump_csrow(&mci->csrows[i]); + for (j = 0; j < mci->csrows[i].nr_channels; j++) + edac_mc_dump_channel(&mci->csrows[i]. + channels[j]); + } + } +#endif + down(&mem_ctls_mutex); + + if (add_mc_to_global_list(mci)) + goto finish; + + /* set load time so that error rate can be tracked */ + mci->start_time = jiffies; + + if (edac_create_sysfs_mci_device(mci)) { + printk(KERN_WARNING + "EDAC MC%d: failed to create sysfs device\n", + mci->mc_idx); + /* FIXME - should there be an error code and unwind? */ + goto finish; + } + + /* Report action taken */ + printk(KERN_INFO + "EDAC MC%d: Giving out device to %s %s: PCI %s\n", + mci->mc_idx, mci->mod_name, mci->ctl_name, + pci_name(mci->pdev)); + + + rc = 0; + +finish: + up(&mem_ctls_mutex); + return rc; +} + + + +static void complete_mc_list_del (struct rcu_head *head) +{ + struct mem_ctl_info *mci; + + mci = container_of(head, struct mem_ctl_info, rcu); + INIT_LIST_HEAD(&mci->link); + complete(&mci->complete); +} + +static void del_mc_from_global_list (struct mem_ctl_info *mci) +{ + list_del_rcu(&mci->link); + init_completion(&mci->complete); + call_rcu(&mci->rcu, complete_mc_list_del); + wait_for_completion(&mci->complete); +} + +EXPORT_SYMBOL(edac_mc_del_mc); + +/** + * edac_mc_del_mc: Remove the specified mci structure from global list + * @mci: Pointer to struct mem_ctl_info structure + * + * Returns: + * 0 Success + * 1 Failure + */ +int edac_mc_del_mc(struct mem_ctl_info *mci) +{ + int rc = 1; + + debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + down(&mem_ctls_mutex); + del_mc_from_global_list(mci); + printk(KERN_INFO + "EDAC MC%d: Removed device %d for %s %s: PCI %s\n", + mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name, + pci_name(mci->pdev)); + rc = 0; + up(&mem_ctls_mutex); + + return rc; +} + + +EXPORT_SYMBOL(edac_mc_scrub_block); + +void edac_mc_scrub_block(unsigned long page, unsigned long offset, + u32 size) +{ + struct page *pg; + void *virt_addr; + unsigned long flags = 0; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + /* ECC error page was not in our memory. Ignore it. */ + if(!pfn_valid(page)) + return; + + /* Find the actual page structure then map it and fix */ + pg = pfn_to_page(page); + + if (PageHighMem(pg)) + local_irq_save(flags); + + virt_addr = kmap_atomic(pg, KM_BOUNCE_READ); + + /* Perform architecture specific atomic scrub operation */ + atomic_scrub(virt_addr + offset, size); + + /* Unmap and complete */ + kunmap_atomic(virt_addr, KM_BOUNCE_READ); + + if (PageHighMem(pg)) + local_irq_restore(flags); +} + + +/* FIXME - should return -1 */ +EXPORT_SYMBOL(edac_mc_find_csrow_by_page); + +int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, + unsigned long page) +{ + struct csrow_info *csrows = mci->csrows; + int row, i; + + debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__, + page); + row = -1; + + for (i = 0; i < mci->nr_csrows; i++) { + struct csrow_info *csrow = &csrows[i]; + + if (csrow->nr_pages == 0) + continue; + + debugf3("MC%d: " __FILE__ + ": %s(): first(0x%lx) page(0x%lx)" + " last(0x%lx) mask(0x%lx)\n", mci->mc_idx, + __func__, csrow->first_page, page, + csrow->last_page, csrow->page_mask); + + if ((page >= csrow->first_page) && + (page <= csrow->last_page) && + ((page & csrow->page_mask) == + (csrow->first_page & csrow->page_mask))) { + row = i; + break; + } + } + + if (row == -1) + printk(KERN_ERR + "EDAC MC%d: could not look up page error address %lx\n", + mci->mc_idx, (unsigned long) page); + + return row; +} + + +EXPORT_SYMBOL(edac_mc_handle_ce); + +/* FIXME - setable log (warning/emerg) levels */ +/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ +void edac_mc_handle_ce(struct mem_ctl_info *mci, + unsigned long page_frame_number, + unsigned long offset_in_page, + unsigned long syndrome, int row, int channel, + const char *msg) +{ + unsigned long remapped_page; + + debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + + /* FIXME - maybe make panic on INTERNAL ERROR an option */ + if (row >= mci->nr_csrows || row < 0) { + /* something is wrong */ + printk(KERN_ERR + "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n", + mci->mc_idx, row, mci->nr_csrows); + edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); + return; + } + if (channel >= mci->csrows[row].nr_channels || channel < 0) { + /* something is wrong */ + printk(KERN_ERR + "EDAC MC%d: INTERNAL ERROR: channel out of range " + "(%d >= %d)\n", + mci->mc_idx, channel, mci->csrows[row].nr_channels); + edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); + return; + } + + if (log_ce) + /* FIXME - put in DIMM location */ + printk(KERN_WARNING + "EDAC MC%d: CE page 0x%lx, offset 0x%lx," + " grain %d, syndrome 0x%lx, row %d, channel %d," + " label \"%s\": %s\n", mci->mc_idx, + page_frame_number, offset_in_page, + mci->csrows[row].grain, syndrome, row, channel, + mci->csrows[row].channels[channel].label, msg); + + mci->ce_count++; + mci->csrows[row].ce_count++; + mci->csrows[row].channels[channel].ce_count++; + + if (mci->scrub_mode & SCRUB_SW_SRC) { + /* + * Some MC's can remap memory so that it is still available + * at a different address when PCI devices map into memory. + * MC's that can't do this lose the memory where PCI devices + * are mapped. This mapping is MC dependant and so we call + * back into the MC driver for it to map the MC page to + * a physical (CPU) page which can then be mapped to a virtual + * page - which can then be scrubbed. + */ + remapped_page = mci->ctl_page_to_phys ? + mci->ctl_page_to_phys(mci, page_frame_number) : + page_frame_number; + + edac_mc_scrub_block(remapped_page, offset_in_page, + mci->csrows[row].grain); + } +} + + +EXPORT_SYMBOL(edac_mc_handle_ce_no_info); + +void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, + const char *msg) +{ + if (log_ce) + printk(KERN_WARNING + "EDAC MC%d: CE - no information available: %s\n", + mci->mc_idx, msg); + mci->ce_noinfo_count++; + mci->ce_count++; +} + + +EXPORT_SYMBOL(edac_mc_handle_ue); + +void edac_mc_handle_ue(struct mem_ctl_info *mci, + unsigned long page_frame_number, + unsigned long offset_in_page, int row, + const char *msg) +{ + int len = EDAC_MC_LABEL_LEN * 4; + char labels[len + 1]; + char *pos = labels; + int chan; + int chars; + + debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + + /* FIXME - maybe make panic on INTERNAL ERROR an option */ + if (row >= mci->nr_csrows || row < 0) { + /* something is wrong */ + printk(KERN_ERR + "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n", + mci->mc_idx, row, mci->nr_csrows); + edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); + return; + } + + chars = snprintf(pos, len + 1, "%s", + mci->csrows[row].channels[0].label); + len -= chars; + pos += chars; + for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0); + chan++) { + chars = snprintf(pos, len + 1, ":%s", + mci->csrows[row].channels[chan].label); + len -= chars; + pos += chars; + } + + if (log_ue) + printk(KERN_EMERG + "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d," + " labels \"%s\": %s\n", mci->mc_idx, + page_frame_number, offset_in_page, + mci->csrows[row].grain, row, labels, msg); + + if (panic_on_ue) + panic + ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d," + " labels \"%s\": %s\n", mci->mc_idx, + page_frame_number, offset_in_page, + mci->csrows[row].grain, row, labels, msg); + + mci->ue_count++; + mci->csrows[row].ue_count++; +} + + +EXPORT_SYMBOL(edac_mc_handle_ue_no_info); + +void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, + const char *msg) +{ + if (panic_on_ue) + panic("EDAC MC%d: Uncorrected Error", mci->mc_idx); + + if (log_ue) + printk(KERN_WARNING + "EDAC MC%d: UE - no information available: %s\n", + mci->mc_idx, msg); + mci->ue_noinfo_count++; + mci->ue_count++; +} + + +#ifdef CONFIG_PCI + +static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) +{ + int where; + u16 status; + + where = secondary ? PCI_SEC_STATUS : PCI_STATUS; + pci_read_config_word(dev, where, &status); + + /* If we get back 0xFFFF then we must suspect that the card has been pulled but + the Linux PCI layer has not yet finished cleaning up. We don't want to report + on such devices */ + + if (status == 0xFFFF) { + u32 sanity; + pci_read_config_dword(dev, 0, &sanity); + if (sanity == 0xFFFFFFFF) + return 0; + } + status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | + PCI_STATUS_PARITY; + + if (status) + /* reset only the bits we are interested in */ + pci_write_config_word(dev, where, status); + + return status; +} + +typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); + +/* Clear any PCI parity errors logged by this device. */ +static void edac_pci_dev_parity_clear( struct pci_dev *dev ) +{ + u8 header_type; + + get_pci_parity_status(dev, 0); + + /* read the device TYPE, looking for bridges */ + pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) + get_pci_parity_status(dev, 1); +} + +/* + * PCI Parity polling + * + */ +static void edac_pci_dev_parity_test(struct pci_dev *dev) +{ + u16 status; + u8 header_type; + + /* read the STATUS register on this device + */ + status = get_pci_parity_status(dev, 0); + + debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); + + /* check the status reg for errors */ + if (status) { + if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) + printk(KERN_CRIT + "EDAC PCI- " + "Signaled System Error on %s\n", + pci_name (dev)); + + if (status & (PCI_STATUS_PARITY)) { + printk(KERN_CRIT + "EDAC PCI- " + "Master Data Parity Error on %s\n", + pci_name (dev)); + + atomic_inc(&pci_parity_count); + } + + if (status & (PCI_STATUS_DETECTED_PARITY)) { + printk(KERN_CRIT + "EDAC PCI- " + "Detected Parity Error on %s\n", + pci_name (dev)); + + atomic_inc(&pci_parity_count); + } + } + + /* read the device TYPE, looking for bridges */ + pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); + + debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { + /* On bridges, need to examine secondary status register */ + status = get_pci_parity_status(dev, 1); + + debugf2("PCI SEC_STATUS= 0x%04x %s\n", + status, dev->dev.bus_id ); + + /* check the secondary status reg for errors */ + if (status) { + if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) + printk(KERN_CRIT + "EDAC PCI-Bridge- " + "Signaled System Error on %s\n", + pci_name (dev)); + + if (status & (PCI_STATUS_PARITY)) { + printk(KERN_CRIT + "EDAC PCI-Bridge- " + "Master Data Parity Error on %s\n", + pci_name (dev)); + + atomic_inc(&pci_parity_count); + } + + if (status & (PCI_STATUS_DETECTED_PARITY)) { + printk(KERN_CRIT + "EDAC PCI-Bridge- " + "Detected Parity Error on %s\n", + pci_name (dev)); + + atomic_inc(&pci_parity_count); + } + } + } +} + +/* + * check_dev_on_list: Scan for a PCI device on a white/black list + * @list: an EDAC &edac_pci_device_list white/black list pointer + * @free_index: index of next free entry on the list + * @pci_dev: PCI Device pointer + * + * see if list contains the device. + * + * Returns: 0 not found + * 1 found on list + */ +static int check_dev_on_list(struct edac_pci_device_list *list, int free_index, + struct pci_dev *dev) +{ + int i; + int rc = 0; /* Assume not found */ + unsigned short vendor=dev->vendor; + unsigned short device=dev->device; + + /* Scan the list, looking for a vendor/device match + */ + for (i = 0; i < free_index; i++, list++ ) { + if ( (list->vendor == vendor ) && + (list->device == device )) { + rc = 1; + break; + } + } + + return rc; +} + +/* + * pci_dev parity list iterator + * Scan the PCI device list for one iteration, looking for SERRORs + * Master Parity ERRORS or Parity ERRORs on primary or secondary devices + */ +static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) +{ + struct pci_dev *dev=NULL; + + /* request for kernel access to the next PCI device, if any, + * and while we are looking at it have its reference count + * bumped until we are done with it + */ + while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + + /* if whitelist exists then it has priority, so only scan those + * devices on the whitelist + */ + if (pci_whitelist_count > 0 ) { + if (check_dev_on_list(pci_whitelist, + pci_whitelist_count, dev)) + fn(dev); + } else { + /* + * if no whitelist, then check if this devices is + * blacklisted + */ + if (!check_dev_on_list(pci_blacklist, + pci_blacklist_count, dev)) + fn(dev); + } + } +} + +static void do_pci_parity_check(void) +{ + unsigned long flags; + int before_count; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + if (!check_pci_parity) + return; + + before_count = atomic_read(&pci_parity_count); + + /* scan all PCI devices looking for a Parity Error on devices and + * bridges + */ + local_irq_save(flags); + edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); + local_irq_restore(flags); + + /* Only if operator has selected panic on PCI Error */ + if (panic_on_pci_parity) { + /* If the count is different 'after' from 'before' */ + if (before_count != atomic_read(&pci_parity_count)) + panic("EDAC: PCI Parity Error"); + } +} + + +static inline void clear_pci_parity_errors(void) +{ + /* Clear any PCI bus parity errors that devices initially have logged + * in their registers. + */ + edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); +} + + +#else /* CONFIG_PCI */ + + +static inline void do_pci_parity_check(void) +{ + /* no-op */ +} + + +static inline void clear_pci_parity_errors(void) +{ + /* no-op */ +} + + +#endif /* CONFIG_PCI */ + +/* + * Iterate over all MC instances and check for ECC, et al, errors + */ +static inline void check_mc_devices (void) +{ + unsigned long flags; + struct list_head *item; + struct mem_ctl_info *mci; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + /* during poll, have interrupts off */ + local_irq_save(flags); + + list_for_each(item, &mc_devices) { + mci = list_entry(item, struct mem_ctl_info, link); + + if (mci->edac_check != NULL) + mci->edac_check(mci); + } + + local_irq_restore(flags); +} + + +/* + * Check MC status every poll_msec. + * Check PCI status every poll_msec as well. + * + * This where the work gets done for edac. + * + * SMP safe, doesn't use NMI, and auto-rate-limits. + */ +static void do_edac_check(void) +{ + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + check_mc_devices(); + + do_pci_parity_check(); +} + + +/* + * EDAC thread state information + */ +struct bs_thread_info +{ + struct task_struct *task; + struct completion *event; + char *name; + void (*run)(void); +}; + +static struct bs_thread_info bs_thread; + +/* + * edac_kernel_thread + * This the kernel thread that processes edac operations + * in a normal thread environment + */ +static int edac_kernel_thread(void *arg) +{ + struct bs_thread_info *thread = (struct bs_thread_info *) arg; + + /* detach thread */ + daemonize(thread->name); + + current->exit_signal = SIGCHLD; + allow_signal(SIGKILL); + thread->task = current; + + /* indicate to starting task we have started */ + complete(thread->event); + + /* loop forever, until we are told to stop */ + while(thread->run != NULL) { + void (*run)(void); + + /* call the function to check the memory controllers */ + run = thread->run; + if (run) + run(); + + if (signal_pending(current)) + flush_signals(current); + + /* ensure we are interruptable */ + set_current_state(TASK_INTERRUPTIBLE); + + /* goto sleep for the interval */ + schedule_timeout((HZ * poll_msec) / 1000); + try_to_freeze(); + } + + /* notify waiter that we are exiting */ + complete(thread->event); + + return 0; +} + +/* + * edac_mc_init + * module initialization entry point + */ +static int __init edac_mc_init(void) +{ + int ret; + struct completion event; + + printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n"); + + /* + * Harvest and clear any boot/initialization PCI parity errors + * + * FIXME: This only clears errors logged by devices present at time of + * module initialization. We should also do an initial clear + * of each newly hotplugged device. + */ + clear_pci_parity_errors(); + + /* perform check for first time to harvest boot leftovers */ + do_edac_check(); + + /* Create the MC sysfs entires */ + if (edac_sysfs_memctrl_setup()) { + printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n"); + return -ENODEV; + } + + /* Create the PCI parity sysfs entries */ + if (edac_sysfs_pci_setup()) { + edac_sysfs_memctrl_teardown(); + printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n"); + return -ENODEV; + } + + /* Create our kernel thread */ + init_completion(&event); + bs_thread.event = &event; + bs_thread.name = "kedac"; + bs_thread.run = do_edac_check; + + /* create our kernel thread */ + ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL); + if (ret < 0) { + /* remove the sysfs entries */ + edac_sysfs_memctrl_teardown(); + edac_sysfs_pci_teardown(); + return -ENOMEM; + } + + /* wait for our kernel theard ack that it is up and running */ + wait_for_completion(&event); + + return 0; +} + + +/* + * edac_mc_exit() + * module exit/termination functioni + */ +static void __exit edac_mc_exit(void) +{ + struct completion event; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + init_completion(&event); + bs_thread.event = &event; + + /* As soon as ->run is set to NULL, the task could disappear, + * so we need to hold tasklist_lock until we have sent the signal + */ + read_lock(&tasklist_lock); + bs_thread.run = NULL; + send_sig(SIGKILL, bs_thread.task, 1); + read_unlock(&tasklist_lock); + wait_for_completion(&event); + + /* tear down the sysfs device */ + edac_sysfs_memctrl_teardown(); + edac_sysfs_pci_teardown(); +} + + + + +module_init(edac_mc_init); +module_exit(edac_mc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" + "Based on.work by Dan Hollis et al"); +MODULE_DESCRIPTION("Core library routines for MC reporting"); + +module_param(panic_on_ue, int, 0644); +MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); +module_param(check_pci_parity, int, 0644); +MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on"); +module_param(panic_on_pci_parity, int, 0644); +MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on"); +module_param(log_ue, int, 0644); +MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on"); +module_param(log_ce, int, 0644); +MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on"); +module_param(poll_msec, int, 0644); +MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds"); +#ifdef CONFIG_EDAC_DEBUG +module_param(edac_debug_level, int, 0644); +MODULE_PARM_DESC(edac_debug_level, "Debug level"); +#endif diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h new file mode 100644 index 000000000000..75ecf484a43a --- /dev/null +++ b/drivers/edac/edac_mc.h @@ -0,0 +1,448 @@ +/* + * MC kernel module + * (C) 2003 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh + * Based on work by Dan Hollis <goemon at anime dot net> and others. + * http://www.anime.net/~goemon/linux-ecc/ + * + * NMI handling support added by + * Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com> + * + * $Id: edac_mc.h,v 1.4.2.10 2005/10/05 00:43:44 dsp_llnl Exp $ + * + */ + + +#ifndef _EDAC_MC_H_ +#define _EDAC_MC_H_ + + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/pci.h> +#include <linux/time.h> +#include <linux/nmi.h> +#include <linux/rcupdate.h> +#include <linux/completion.h> +#include <linux/kobject.h> + + +#define EDAC_MC_LABEL_LEN 31 +#define MC_PROC_NAME_MAX_LEN 7 + +#if PAGE_SHIFT < 20 +#define PAGES_TO_MiB( pages ) ( ( pages ) >> ( 20 - PAGE_SHIFT ) ) +#else /* PAGE_SHIFT > 20 */ +#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) ) +#endif + +#ifdef CONFIG_EDAC_DEBUG +extern int edac_debug_level; +#define edac_debug_printk(level, fmt, args...) \ +do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0) +#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ ) +#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ ) +#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) +#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ ) +#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ ) +#else /* !CONFIG_EDAC_DEBUG */ +#define debugf0( ... ) +#define debugf1( ... ) +#define debugf2( ... ) +#define debugf3( ... ) +#define debugf4( ... ) +#endif /* !CONFIG_EDAC_DEBUG */ + + +#define bs_xstr(s) bs_str(s) +#define bs_str(s) #s +#define BS_MOD_STR bs_xstr(KBUILD_BASENAME) + +#define BIT(x) (1 << (x)) + +#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev + +/* memory devices */ +enum dev_type { + DEV_UNKNOWN = 0, + DEV_X1, + DEV_X2, + DEV_X4, + DEV_X8, + DEV_X16, + DEV_X32, /* Do these parts exist? */ + DEV_X64 /* Do these parts exist? */ +}; + +#define DEV_FLAG_UNKNOWN BIT(DEV_UNKNOWN) +#define DEV_FLAG_X1 BIT(DEV_X1) +#define DEV_FLAG_X2 BIT(DEV_X2) +#define DEV_FLAG_X4 BIT(DEV_X4) +#define DEV_FLAG_X8 BIT(DEV_X8) +#define DEV_FLAG_X16 BIT(DEV_X16) +#define DEV_FLAG_X32 BIT(DEV_X32) +#define DEV_FLAG_X64 BIT(DEV_X64) + +/* memory types */ +enum mem_type { + MEM_EMPTY = 0, /* Empty csrow */ + MEM_RESERVED, /* Reserved csrow type */ + MEM_UNKNOWN, /* Unknown csrow type */ + MEM_FPM, /* Fast page mode */ + MEM_EDO, /* Extended data out */ + MEM_BEDO, /* Burst Extended data out */ + MEM_SDR, /* Single data rate SDRAM */ + MEM_RDR, /* Registered single data rate SDRAM */ + MEM_DDR, /* Double data rate SDRAM */ + MEM_RDDR, /* Registered Double data rate SDRAM */ + MEM_RMBS /* Rambus DRAM */ +}; + +#define MEM_FLAG_EMPTY BIT(MEM_EMPTY) +#define MEM_FLAG_RESERVED BIT(MEM_RESERVED) +#define MEM_FLAG_UNKNOWN BIT(MEM_UNKNOWN) +#define MEM_FLAG_FPM BIT(MEM_FPM) +#define MEM_FLAG_EDO BIT(MEM_EDO) +#define MEM_FLAG_BEDO BIT(MEM_BEDO) +#define MEM_FLAG_SDR BIT(MEM_SDR) +#define MEM_FLAG_RDR BIT(MEM_RDR) +#define MEM_FLAG_DDR BIT(MEM_DDR) +#define MEM_FLAG_RDDR BIT(MEM_RDDR) +#define MEM_FLAG_RMBS BIT(MEM_RMBS) + + +/* chipset Error Detection and Correction capabilities and mode */ +enum edac_type { + EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ + EDAC_NONE, /* Doesnt support ECC */ + EDAC_RESERVED, /* Reserved ECC type */ + EDAC_PARITY, /* Detects parity errors */ + EDAC_EC, /* Error Checking - no correction */ + EDAC_SECDED, /* Single bit error correction, Double detection */ + EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */ + EDAC_S4ECD4ED, /* Chipkill x4 devices */ + EDAC_S8ECD8ED, /* Chipkill x8 devices */ + EDAC_S16ECD16ED, /* Chipkill x16 devices */ +}; + +#define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN) +#define EDAC_FLAG_NONE BIT(EDAC_NONE) +#define EDAC_FLAG_PARITY BIT(EDAC_PARITY) +#define EDAC_FLAG_EC BIT(EDAC_EC) +#define EDAC_FLAG_SECDED BIT(EDAC_SECDED) +#define EDAC_FLAG_S2ECD2ED BIT(EDAC_S2ECD2ED) +#define EDAC_FLAG_S4ECD4ED BIT(EDAC_S4ECD4ED) +#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED) +#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED) + + +/* scrubbing capabilities */ +enum scrub_type { + SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */ + SCRUB_NONE, /* No scrubber */ + SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */ + SCRUB_SW_SRC, /* Software scrub only errors */ + SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */ + SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */ + SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */ + SCRUB_HW_SRC, /* Hardware scrub only errors */ + SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */ + SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */ +}; + +#define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG) +#define SCRUB_FLAG_SW_SRC BIT(SCRUB_SW_SRC_CORR) +#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC_CORR) +#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE) +#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG) +#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC_CORR) +#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR) +#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE) + +enum mci_sysfs_status { + MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */ + MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */ +}; + +/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */ + +/* + * There are several things to be aware of that aren't at all obvious: + * + * + * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc.. + * + * These are some of the many terms that are thrown about that don't always + * mean what people think they mean (Inconceivable!). In the interest of + * creating a common ground for discussion, terms and their definitions + * will be established. + * + * Memory devices: The individual chip on a memory stick. These devices + * commonly output 4 and 8 bits each. Grouping several + * of these in parallel provides 64 bits which is common + * for a memory stick. + * + * Memory Stick: A printed circuit board that agregates multiple + * memory devices in parallel. This is the atomic + * memory component that is purchaseable by Joe consumer + * and loaded into a memory socket. + * + * Socket: A physical connector on the motherboard that accepts + * a single memory stick. + * + * Channel: Set of memory devices on a memory stick that must be + * grouped in parallel with one or more additional + * channels from other memory sticks. This parallel + * grouping of the output from multiple channels are + * necessary for the smallest granularity of memory access. + * Some memory controllers are capable of single channel - + * which means that memory sticks can be loaded + * individually. Other memory controllers are only + * capable of dual channel - which means that memory + * sticks must be loaded as pairs (see "socket set"). + * + * Chip-select row: All of the memory devices that are selected together. + * for a single, minimum grain of memory access. + * This selects all of the parallel memory devices across + * all of the parallel channels. Common chip-select rows + * for single channel are 64 bits, for dual channel 128 + * bits. + * + * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memmory. + * Motherboards commonly drive two chip-select pins to + * a memory stick. A single-ranked stick, will occupy + * only one of those rows. The other will be unused. + * + * Double-Ranked stick: A double-ranked stick has two chip-select rows which + * access different sets of memory devices. The two + * rows cannot be accessed concurrently. + * + * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick. + * A double-sided stick has two chip-select rows which + * access different sets of memory devices. The two + * rows cannot be accessed concurrently. "Double-sided" + * is irrespective of the memory devices being mounted + * on both sides of the memory stick. + * + * Socket set: All of the memory sticks that are required for for + * a single memory access or all of the memory sticks + * spanned by a chip-select row. A single socket set + * has two chip-select rows and if double-sided sticks + * are used these will occupy those chip-select rows. + * + * Bank: This term is avoided because it is unclear when + * needing to distinguish between chip-select rows and + * socket sets. + * + * Controller pages: + * + * Physical pages: + * + * Virtual pages: + * + * + * STRUCTURE ORGANIZATION AND CHOICES + * + * + * + * PS - I enjoyed writing all that about as much as you enjoyed reading it. + */ + + +struct channel_info { + int chan_idx; /* channel index */ + u32 ce_count; /* Correctable Errors for this CHANNEL */ + char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ + struct csrow_info *csrow; /* the parent */ +}; + + +struct csrow_info { + unsigned long first_page; /* first page number in dimm */ + unsigned long last_page; /* last page number in dimm */ + unsigned long page_mask; /* used for interleaving - + 0UL for non intlv */ + u32 nr_pages; /* number of pages in csrow */ + u32 grain; /* granularity of reported error in bytes */ + int csrow_idx; /* the chip-select row */ + enum dev_type dtype; /* memory device type */ + u32 ue_count; /* Uncorrectable Errors for this csrow */ + u32 ce_count; /* Correctable Errors for this csrow */ + enum mem_type mtype; /* memory csrow type */ + enum edac_type edac_mode; /* EDAC mode for this csrow */ + struct mem_ctl_info *mci; /* the parent */ + + struct kobject kobj; /* sysfs kobject for this csrow */ + + /* FIXME the number of CHANNELs might need to become dynamic */ + u32 nr_channels; + struct channel_info *channels; +}; + + +struct mem_ctl_info { + struct list_head link; /* for global list of mem_ctl_info structs */ + unsigned long mtype_cap; /* memory types supported by mc */ + unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */ + unsigned long edac_cap; /* configuration capabilities - this is + closely related to edac_ctl_cap. The + difference is that the controller + may be capable of s4ecd4ed which would + be listed in edac_ctl_cap, but if + channels aren't capable of s4ecd4ed then the + edac_cap would not have that capability. */ + unsigned long scrub_cap; /* chipset scrub capabilities */ + enum scrub_type scrub_mode; /* current scrub mode */ + + enum mci_sysfs_status sysfs_active; /* status of sysfs */ + + /* pointer to edac checking routine */ + void (*edac_check) (struct mem_ctl_info * mci); + /* + * Remaps memory pages: controller pages to physical pages. + * For most MC's, this will be NULL. + */ + /* FIXME - why not send the phys page to begin with? */ + unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, + unsigned long page); + int mc_idx; + int nr_csrows; + struct csrow_info *csrows; + /* + * FIXME - what about controllers on other busses? - IDs must be + * unique. pdev pointer should be sufficiently unique, but + * BUS:SLOT.FUNC numbers may not be unique. + */ + struct pci_dev *pdev; + const char *mod_name; + const char *mod_ver; + const char *ctl_name; + char proc_name[MC_PROC_NAME_MAX_LEN + 1]; + void *pvt_info; + u32 ue_noinfo_count; /* Uncorrectable Errors w/o info */ + u32 ce_noinfo_count; /* Correctable Errors w/o info */ + u32 ue_count; /* Total Uncorrectable Errors for this MC */ + u32 ce_count; /* Total Correctable Errors for this MC */ + unsigned long start_time; /* mci load start time (in jiffies) */ + + /* this stuff is for safe removal of mc devices from global list while + * NMI handlers may be traversing list + */ + struct rcu_head rcu; + struct completion complete; + + /* edac sysfs device control */ + struct kobject edac_mci_kobj; +}; + + + +/* write all or some bits in a byte-register*/ +static inline void pci_write_bits8(struct pci_dev *pdev, int offset, + u8 value, u8 mask) +{ + if (mask != 0xff) { + u8 buf; + pci_read_config_byte(pdev, offset, &buf); + value &= mask; + buf &= ~mask; + value |= buf; + } + pci_write_config_byte(pdev, offset, value); +} + + +/* write all or some bits in a word-register*/ +static inline void pci_write_bits16(struct pci_dev *pdev, int offset, + u16 value, u16 mask) +{ + if (mask != 0xffff) { + u16 buf; + pci_read_config_word(pdev, offset, &buf); + value &= mask; + buf &= ~mask; + value |= buf; + } + pci_write_config_word(pdev, offset, value); +} + + +/* write all or some bits in a dword-register*/ +static inline void pci_write_bits32(struct pci_dev *pdev, int offset, + u32 value, u32 mask) +{ + if (mask != 0xffff) { + u32 buf; + pci_read_config_dword(pdev, offset, &buf); + value &= mask; + buf &= ~mask; + value |= buf; + } + pci_write_config_dword(pdev, offset, value); +} + + +#ifdef CONFIG_EDAC_DEBUG +void edac_mc_dump_channel(struct channel_info *chan); +void edac_mc_dump_mci(struct mem_ctl_info *mci); +void edac_mc_dump_csrow(struct csrow_info *csrow); +#endif /* CONFIG_EDAC_DEBUG */ + +extern int edac_mc_add_mc(struct mem_ctl_info *mci); +extern int edac_mc_del_mc(struct mem_ctl_info *mci); + +extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, + unsigned long page); + +extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev + *pdev); + +extern void edac_mc_scrub_block(unsigned long page, + unsigned long offset, u32 size); + +/* + * The no info errors are used when error overflows are reported. + * There are a limited number of error logging registers that can + * be exausted. When all registers are exhausted and an additional + * error occurs then an error overflow register records that an + * error occured and the type of error, but doesn't have any + * further information. The ce/ue versions make for cleaner + * reporting logic and function interface - reduces conditional + * statement clutter and extra function arguments. + */ +extern void edac_mc_handle_ce(struct mem_ctl_info *mci, + unsigned long page_frame_number, + unsigned long offset_in_page, + unsigned long syndrome, + int row, int channel, const char *msg); + +extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, + const char *msg); + +extern void edac_mc_handle_ue(struct mem_ctl_info *mci, + unsigned long page_frame_number, + unsigned long offset_in_page, + int row, const char *msg); + +extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, + const char *msg); + +/* + * This kmalloc's and initializes all the structures. + * Can't be used if all structures don't have the same lifetime. + */ +extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, + unsigned nr_csrows, unsigned nr_chans); + +/* Free an mc previously allocated by edac_mc_alloc() */ +extern void edac_mc_free(struct mem_ctl_info *mci); + + +#endif /* _EDAC_MC_H_ */ diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c new file mode 100644 index 000000000000..52596e75f9c2 --- /dev/null +++ b/drivers/edac/i82860_edac.c @@ -0,0 +1,299 @@ +/* + * Intel 82860 Memory Controller kernel module + * (C) 2005 Red Hat (http://www.redhat.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Ben Woodard <woodard@redhat.com> + * shamelessly copied from and based upon the edac_i82875 driver + * by Thayne Harbaugh of Linux Networx. (http://lnxi.com) + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/slab.h> +#include "edac_mc.h" + + +#ifndef PCI_DEVICE_ID_INTEL_82860_0 +#define PCI_DEVICE_ID_INTEL_82860_0 0x2531 +#endif /* PCI_DEVICE_ID_INTEL_82860_0 */ + +#define I82860_MCHCFG 0x50 +#define I82860_GBA 0x60 +#define I82860_GBA_MASK 0x7FF +#define I82860_GBA_SHIFT 24 +#define I82860_ERRSTS 0xC8 +#define I82860_EAP 0xE4 +#define I82860_DERRCTL_STS 0xE2 + +enum i82860_chips { + I82860 = 0, +}; + +struct i82860_dev_info { + const char *ctl_name; +}; + +struct i82860_error_info { + u16 errsts; + u32 eap; + u16 derrsyn; + u16 errsts2; +}; + +static const struct i82860_dev_info i82860_devs[] = { + [I82860] = { + .ctl_name = "i82860"}, +}; + +static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code + has already registered driver */ + +static int i82860_registered = 1; + +static void i82860_get_error_info (struct mem_ctl_info *mci, + struct i82860_error_info *info) +{ + /* + * This is a mess because there is no atomic way to read all the + * registers at once and the registers can transition from CE being + * overwritten by UE. + */ + pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts); + pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); + pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn); + pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2); + + pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003); + + /* + * If the error is the same for both reads then the first set of reads + * is valid. If there is a change then there is a CE no info and the + * second set of reads is valid and should be UE info. + */ + if (!(info->errsts2 & 0x0003)) + return; + if ((info->errsts ^ info->errsts2) & 0x0003) { + pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); + pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, + &info->derrsyn); + } +} + +static int i82860_process_error_info (struct mem_ctl_info *mci, + struct i82860_error_info *info, int handle_errors) +{ + int row; + + if (!(info->errsts2 & 0x0003)) + return 0; + + if (!handle_errors) + return 1; + + if ((info->errsts ^ info->errsts2) & 0x0003) { + edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); + info->errsts = info->errsts2; + } + + info->eap >>= PAGE_SHIFT; + row = edac_mc_find_csrow_by_page(mci, info->eap); + + if (info->errsts & 0x0002) + edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE"); + else + edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, + 0, "i82860 UE"); + + return 1; +} + +static void i82860_check(struct mem_ctl_info *mci) +{ + struct i82860_error_info info; + + debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + i82860_get_error_info(mci, &info); + i82860_process_error_info(mci, &info, 1); +} + +static int i82860_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + struct mem_ctl_info *mci = NULL; + unsigned long last_cumul_size; + + u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + + /* RDRAM has channels but these don't map onto the abstractions that + edac uses. + The device groups from the GRA registers seem to map reasonably + well onto the notion of a chip select row. + There are 16 GRA registers and since the name is associated with + the channel and the GRA registers map to physical devices so we are + going to make 1 channel for group. + */ + mci = edac_mc_alloc(0, 16, 1); + if (!mci) + return -ENOMEM; + + debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + + mci->pdev = pdev; + mci->mtype_cap = MEM_FLAG_DDR; + + + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; + /* I"m not sure about this but I think that all RDRAM is SECDED */ + mci->edac_cap = EDAC_FLAG_SECDED; + /* adjust FLAGS */ + + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.1.2.6 $"; + mci->ctl_name = i82860_devs[dev_idx].ctl_name; + mci->edac_check = i82860_check; + mci->ctl_page_to_phys = NULL; + + pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim); + mchcfg_ddim = mchcfg_ddim & 0x180; + + /* + * The group row boundary (GRA) reg values are boundary address + * for each DRAM row with a granularity of 16MB. GRA regs are + * cumulative; therefore GRA15 will contain the total memory contained + * in all eight rows. + */ + for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { + u16 value; + u32 cumul_size; + struct csrow_info *csrow = &mci->csrows[index]; + + pci_read_config_word(mci->pdev, I82860_GBA + index * 2, + &value); + + cumul_size = (value & I82860_GBA_MASK) << + (I82860_GBA_SHIFT - PAGE_SHIFT); + debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", + __func__, index, cumul_size); + if (cumul_size == last_cumul_size) + continue; /* not populated */ + + csrow->first_page = last_cumul_size; + csrow->last_page = cumul_size - 1; + csrow->nr_pages = cumul_size - last_cumul_size; + last_cumul_size = cumul_size; + csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ + csrow->mtype = MEM_RMBS; + csrow->dtype = DEV_UNKNOWN; + csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; + } + + /* clear counters */ + pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003); + + if (edac_mc_add_mc(mci)) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", + __func__); + edac_mc_free(mci); + } else { + /* get this far and it's successful */ + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + rc = 0; + } + return rc; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit i82860_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rc; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + printk(KERN_INFO "i82860 init one\n"); + if(pci_enable_device(pdev) < 0) + return -EIO; + rc = i82860_probe1(pdev, ent->driver_data); + if(rc == 0) + mci_pdev = pci_dev_get(pdev); + return rc; +} + +static void __devexit i82860_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + + debugf0(__FILE__ ": %s()\n", __func__); + + mci = edac_mc_find_mci_by_pdev(pdev); + if ((mci != NULL) && (edac_mc_del_mc(mci) == 0)) + edac_mc_free(mci); +} + +static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82860}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); + +static struct pci_driver i82860_driver = { + .name = BS_MOD_STR, + .probe = i82860_init_one, + .remove = __devexit_p(i82860_remove_one), + .id_table = i82860_pci_tbl, +}; + +static int __init i82860_init(void) +{ + int pci_rc; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) + return pci_rc; + + if (!mci_pdev) { + i82860_registered = 0; + mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82860_0, NULL); + if (mci_pdev == NULL) { + debugf0("860 pci_get_device fail\n"); + return -ENODEV; + } + pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); + if (pci_rc < 0) { + debugf0("860 init fail\n"); + pci_dev_put(mci_pdev); + return -ENODEV; + } + } + return 0; +} + +static void __exit i82860_exit(void) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + pci_unregister_driver(&i82860_driver); + if (!i82860_registered) { + i82860_remove_one(mci_pdev); + pci_dev_put(mci_pdev); + } +} + +module_init(i82860_init); +module_exit(i82860_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR + ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>"); +MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers"); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c new file mode 100644 index 000000000000..1991f94af753 --- /dev/null +++ b/drivers/edac/i82875p_edac.c @@ -0,0 +1,532 @@ +/* + * Intel D82875P Memory Controller kernel module + * (C) 2003 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh + * Contributors: + * Wang Zhenyu at intel.com + * + * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $ + * + * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/pci.h> +#include <linux/pci_ids.h> + +#include <linux/slab.h> + +#include "edac_mc.h" + + +#ifndef PCI_DEVICE_ID_INTEL_82875_0 +#define PCI_DEVICE_ID_INTEL_82875_0 0x2578 +#endif /* PCI_DEVICE_ID_INTEL_82875_0 */ + +#ifndef PCI_DEVICE_ID_INTEL_82875_6 +#define PCI_DEVICE_ID_INTEL_82875_6 0x257e +#endif /* PCI_DEVICE_ID_INTEL_82875_6 */ + + +/* four csrows in dual channel, eight in single channel */ +#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans)) + + +/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */ +#define I82875P_EAP 0x58 /* Error Address Pointer (32b) + * + * 31:12 block address + * 11:0 reserved + */ + +#define I82875P_DERRSYN 0x5c /* DRAM Error Syndrome (8b) + * + * 7:0 DRAM ECC Syndrome + */ + +#define I82875P_DES 0x5d /* DRAM Error Status (8b) + * + * 7:1 reserved + * 0 Error channel 0/1 + */ + +#define I82875P_ERRSTS 0xc8 /* Error Status Register (16b) + * + * 15:10 reserved + * 9 non-DRAM lock error (ndlock) + * 8 Sftwr Generated SMI + * 7 ECC UE + * 6 reserved + * 5 MCH detects unimplemented cycle + * 4 AGP access outside GA + * 3 Invalid AGP access + * 2 Invalid GA translation table + * 1 Unsupported AGP command + * 0 ECC CE + */ + +#define I82875P_ERRCMD 0xca /* Error Command (16b) + * + * 15:10 reserved + * 9 SERR on non-DRAM lock + * 8 SERR on ECC UE + * 7 SERR on ECC CE + * 6 target abort on high exception + * 5 detect unimplemented cyc + * 4 AGP access outside of GA + * 3 SERR on invalid AGP access + * 2 invalid translation table + * 1 SERR on unsupported AGP command + * 0 reserved + */ + + +/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */ +#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b) + * + * 15:10 reserved + * 9 fast back-to-back - ro 0 + * 8 SERR enable - ro 0 + * 7 addr/data stepping - ro 0 + * 6 parity err enable - ro 0 + * 5 VGA palette snoop - ro 0 + * 4 mem wr & invalidate - ro 0 + * 3 special cycle - ro 0 + * 2 bus master - ro 0 + * 1 mem access dev6 - 0(dis),1(en) + * 0 IO access dev3 - 0(dis),1(en) + */ + +#define I82875P_BAR6 0x10 /* Mem Delays Base ADDR Reg (32b) + * + * 31:12 mem base addr [31:12] + * 11:4 address mask - ro 0 + * 3 prefetchable - ro 0(non),1(pre) + * 2:1 mem type - ro 0 + * 0 mem space - ro 0 + */ + +/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */ + +#define I82875P_DRB_SHIFT 26 /* 64MiB grain */ +#define I82875P_DRB 0x00 /* DRAM Row Boundary (8b x 8) + * + * 7 reserved + * 6:0 64MiB row boundary addr + */ + +#define I82875P_DRA 0x10 /* DRAM Row Attribute (4b x 8) + * + * 7 reserved + * 6:4 row attr row 1 + * 3 reserved + * 2:0 row attr row 0 + * + * 000 = 4KiB + * 001 = 8KiB + * 010 = 16KiB + * 011 = 32KiB + */ + +#define I82875P_DRC 0x68 /* DRAM Controller Mode (32b) + * + * 31:30 reserved + * 29 init complete + * 28:23 reserved + * 22:21 nr chan 00=1,01=2 + * 20 reserved + * 19:18 Data Integ Mode 00=none,01=ecc + * 17:11 reserved + * 10:8 refresh mode + * 7 reserved + * 6:4 mode select + * 3:2 reserved + * 1:0 DRAM type 01=DDR + */ + + +enum i82875p_chips { + I82875P = 0, +}; + + +struct i82875p_pvt { + struct pci_dev *ovrfl_pdev; + void __iomem *ovrfl_window; +}; + + +struct i82875p_dev_info { + const char *ctl_name; +}; + + +struct i82875p_error_info { + u16 errsts; + u32 eap; + u8 des; + u8 derrsyn; + u16 errsts2; +}; + + +static const struct i82875p_dev_info i82875p_devs[] = { + [I82875P] = { + .ctl_name = "i82875p"}, +}; + +static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code + has already registered driver */ +static int i82875p_registered = 1; + +static void i82875p_get_error_info (struct mem_ctl_info *mci, + struct i82875p_error_info *info) +{ + /* + * This is a mess because there is no atomic way to read all the + * registers at once and the registers can transition from CE being + * overwritten by UE. + */ + pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts); + pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); + pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); + pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn); + pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2); + + pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081); + + /* + * If the error is the same then we can for both reads then + * the first set of reads is valid. If there is a change then + * there is a CE no info and the second set of reads is valid + * and should be UE info. + */ + if (!(info->errsts2 & 0x0081)) + return; + if ((info->errsts ^ info->errsts2) & 0x0081) { + pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); + pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); + pci_read_config_byte(mci->pdev, I82875P_DERRSYN, + &info->derrsyn); + } +} + +static int i82875p_process_error_info (struct mem_ctl_info *mci, + struct i82875p_error_info *info, int handle_errors) +{ + int row, multi_chan; + + multi_chan = mci->csrows[0].nr_channels - 1; + + if (!(info->errsts2 & 0x0081)) + return 0; + + if (!handle_errors) + return 1; + + if ((info->errsts ^ info->errsts2) & 0x0081) { + edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); + info->errsts = info->errsts2; + } + + info->eap >>= PAGE_SHIFT; + row = edac_mc_find_csrow_by_page(mci, info->eap); + + if (info->errsts & 0x0080) + edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE"); + else + edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, + multi_chan ? (info->des & 0x1) : 0, + "i82875p CE"); + + return 1; +} + + +static void i82875p_check(struct mem_ctl_info *mci) +{ + struct i82875p_error_info info; + + debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + i82875p_get_error_info(mci, &info); + i82875p_process_error_info(mci, &info, 1); +} + + +#ifdef CONFIG_PROC_FS +extern int pci_proc_attach_device(struct pci_dev *); +#endif + +static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + struct mem_ctl_info *mci = NULL; + struct i82875p_pvt *pvt = NULL; + unsigned long last_cumul_size; + struct pci_dev *ovrfl_pdev; + void __iomem *ovrfl_window = NULL; + + u32 drc; + u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ + u32 nr_chans; + u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); + + if (!ovrfl_pdev) { + /* + * Intel tells BIOS developers to hide device 6 which + * configures the overflow device access containing + * the DRBs - this is where we expose device 6. + * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm + */ + pci_write_bits8(pdev, 0xf4, 0x2, 0x2); + ovrfl_pdev = + pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); + if (!ovrfl_pdev) + goto fail; + } +#ifdef CONFIG_PROC_FS + if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { + printk(KERN_ERR "MC: " __FILE__ + ": %s(): Failed to attach overflow device\n", + __func__); + goto fail; + } +#endif /* CONFIG_PROC_FS */ + if (pci_enable_device(ovrfl_pdev)) { + printk(KERN_ERR "MC: " __FILE__ + ": %s(): Failed to enable overflow device\n", + __func__); + goto fail; + } + + if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) { +#ifdef CORRECT_BIOS + goto fail; +#endif + } + /* cache is irrelevant for PCI bus reads/writes */ + ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), + pci_resource_len(ovrfl_pdev, 0)); + + if (!ovrfl_window) { + printk(KERN_ERR "MC: " __FILE__ + ": %s(): Failed to ioremap bar6\n", __func__); + goto fail; + } + + /* need to find out the number of channels */ + drc = readl(ovrfl_window + I82875P_DRC); + drc_chan = ((drc >> 21) & 0x1); + nr_chans = drc_chan + 1; + drc_ddim = (drc >> 18) & 0x1; + + mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), + nr_chans); + + if (!mci) { + rc = -ENOMEM; + goto fail; + } + + debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + + mci->pdev = pdev; + mci->mtype_cap = MEM_FLAG_DDR; + + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_UNKNOWN; + /* adjust FLAGS */ + + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.5.2.11 $"; + mci->ctl_name = i82875p_devs[dev_idx].ctl_name; + mci->edac_check = i82875p_check; + mci->ctl_page_to_phys = NULL; + + debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + + pvt = (struct i82875p_pvt *) mci->pvt_info; + pvt->ovrfl_pdev = ovrfl_pdev; + pvt->ovrfl_window = ovrfl_window; + + /* + * The dram row boundary (DRB) reg values are boundary address + * for each DRAM row with a granularity of 32 or 64MB (single/dual + * channel operation). DRB regs are cumulative; therefore DRB7 will + * contain the total memory contained in all eight rows. + */ + for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { + u8 value; + u32 cumul_size; + struct csrow_info *csrow = &mci->csrows[index]; + + value = readb(ovrfl_window + I82875P_DRB + index); + cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); + debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", + __func__, index, cumul_size); + if (cumul_size == last_cumul_size) + continue; /* not populated */ + + csrow->first_page = last_cumul_size; + csrow->last_page = cumul_size - 1; + csrow->nr_pages = cumul_size - last_cumul_size; + last_cumul_size = cumul_size; + csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ + csrow->mtype = MEM_DDR; + csrow->dtype = DEV_UNKNOWN; + csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; + } + + /* clear counters */ + pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081); + + if (edac_mc_add_mc(mci)) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", __func__); + goto fail; + } + + /* get this far and it's successful */ + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + return 0; + + fail: + if (mci) + edac_mc_free(mci); + + if (ovrfl_window) + iounmap(ovrfl_window); + + if (ovrfl_pdev) { + pci_release_regions(ovrfl_pdev); + pci_disable_device(ovrfl_pdev); + } + + /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ + return rc; +} + + +/* returns count (>= 0), or negative on error */ +static int __devinit i82875p_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rc; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + printk(KERN_INFO "i82875p init one\n"); + if(pci_enable_device(pdev) < 0) + return -EIO; + rc = i82875p_probe1(pdev, ent->driver_data); + if (mci_pdev == NULL) + mci_pdev = pci_dev_get(pdev); + return rc; +} + + +static void __devexit i82875p_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + struct i82875p_pvt *pvt = NULL; + + debugf0(__FILE__ ": %s()\n", __func__); + + if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) + return; + + pvt = (struct i82875p_pvt *) mci->pvt_info; + if (pvt->ovrfl_window) + iounmap(pvt->ovrfl_window); + + if (pvt->ovrfl_pdev) { +#ifdef CORRECT_BIOS + pci_release_regions(pvt->ovrfl_pdev); +#endif /*CORRECT_BIOS */ + pci_disable_device(pvt->ovrfl_pdev); + pci_dev_put(pvt->ovrfl_pdev); + } + + if (edac_mc_del_mc(mci)) + return; + + edac_mc_free(mci); +} + + +static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82875P}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); + + +static struct pci_driver i82875p_driver = { + .name = BS_MOD_STR, + .probe = i82875p_init_one, + .remove = __devexit_p(i82875p_remove_one), + .id_table = i82875p_pci_tbl, +}; + + +static int __init i82875p_init(void) +{ + int pci_rc; + + debugf3("MC: " __FILE__ ": %s()\n", __func__); + pci_rc = pci_register_driver(&i82875p_driver); + if (pci_rc < 0) + return pci_rc; + if (mci_pdev == NULL) { + i82875p_registered = 0; + mci_pdev = + pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82875_0, NULL); + if (!mci_pdev) { + debugf0("875p pci_get_device fail\n"); + return -ENODEV; + } + pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); + if (pci_rc < 0) { + debugf0("875p init fail\n"); + pci_dev_put(mci_pdev); + return -ENODEV; + } + } + return 0; +} + + +static void __exit i82875p_exit(void) +{ + debugf3("MC: " __FILE__ ": %s()\n", __func__); + + pci_unregister_driver(&i82875p_driver); + if (!i82875p_registered) { + i82875p_remove_one(mci_pdev); + pci_dev_put(mci_pdev); + } +} + + +module_init(i82875p_init); +module_exit(i82875p_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); +MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers"); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c new file mode 100644 index 000000000000..e90892831b90 --- /dev/null +++ b/drivers/edac/r82600_edac.c @@ -0,0 +1,407 @@ +/* + * Radisys 82600 Embedded chipset Memory Controller kernel module + * (C) 2005 EADS Astrium + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne + * Harbaugh, Dan Hollis <goemon at anime dot net> and others. + * + * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $ + * + * Written with reference to 82600 High Integration Dual PCI System + * Controller Data Book: + * http://www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf + * references to this document given in [] + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/pci.h> +#include <linux/pci_ids.h> + +#include <linux/slab.h> + +#include "edac_mc.h" + +/* Radisys say "The 82600 integrates a main memory SDRAM controller that + * supports up to four banks of memory. The four banks can support a mix of + * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs, + * each of which can be any size from 16MB to 512MB. Both registered (control + * signals buffered) and unbuffered DIMM types are supported. Mixing of + * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs + * is not allowed. The 82600 SDRAM interface operates at the same frequency as + * the CPU bus, 66MHz, 100MHz or 133MHz." + */ + +#define R82600_NR_CSROWS 4 +#define R82600_NR_CHANS 1 +#define R82600_NR_DIMMS 4 + +#define R82600_BRIDGE_ID 0x8200 + +/* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */ +#define R82600_DRAMC 0x57 /* Various SDRAM related control bits + * all bits are R/W + * + * 7 SDRAM ISA Hole Enable + * 6 Flash Page Mode Enable + * 5 ECC Enable: 1=ECC 0=noECC + * 4 DRAM DIMM Type: 1= + * 3 BIOS Alias Disable + * 2 SDRAM BIOS Flash Write Enable + * 1:0 SDRAM Refresh Rate: 00=Disabled + * 01=7.8usec (256Mbit SDRAMs) + * 10=15.6us 11=125usec + */ + +#define R82600_SDRAMC 0x76 /* "SDRAM Control Register" + * More SDRAM related control bits + * all bits are R/W + * + * 15:8 Reserved. + * + * 7:5 Special SDRAM Mode Select + * + * 4 Force ECC + * + * 1=Drive ECC bits to 0 during + * write cycles (i.e. ECC test mode) + * + * 0=Normal ECC functioning + * + * 3 Enhanced Paging Enable + * + * 2 CAS# Latency 0=3clks 1=2clks + * + * 1 RAS# to CAS# Delay 0=3 1=2 + * + * 0 RAS# Precharge 0=3 1=2 + */ + +#define R82600_EAP 0x80 /* ECC Error Address Pointer Register + * + * 31 Disable Hardware Scrubbing (RW) + * 0=Scrub on corrected read + * 1=Don't scrub on corrected read + * + * 30:12 Error Address Pointer (RO) + * Upper 19 bits of error address + * + * 11:4 Syndrome Bits (RO) + * + * 3 BSERR# on multibit error (RW) + * 1=enable 0=disable + * + * 2 NMI on Single Bit Eror (RW) + * 1=NMI triggered by SBE n.b. other + * prerequeists + * 0=NMI not triggered + * + * 1 MBE (R/WC) + * read 1=MBE at EAP (see above) + * read 0=no MBE, or SBE occurred first + * write 1=Clear MBE status (must also + * clear SBE) + * write 0=NOP + * + * 1 SBE (R/WC) + * read 1=SBE at EAP (see above) + * read 0=no SBE, or MBE occurred first + * write 1=Clear SBE status (must also + * clear MBE) + * write 0=NOP + */ + +#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundry Address + * Registers + * + * 7:0 Address lines 30:24 - upper limit of + * each row [p57] + */ + +struct r82600_error_info { + u32 eapr; +}; + + +static unsigned int disable_hardware_scrub = 0; + + +static void r82600_get_error_info (struct mem_ctl_info *mci, + struct r82600_error_info *info) +{ + pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr); + + if (info->eapr & BIT(0)) + /* Clear error to allow next error to be reported [p.62] */ + pci_write_bits32(mci->pdev, R82600_EAP, + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); + + if (info->eapr & BIT(1)) + /* Clear error to allow next error to be reported [p.62] */ + pci_write_bits32(mci->pdev, R82600_EAP, + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); +} + + +static int r82600_process_error_info (struct mem_ctl_info *mci, + struct r82600_error_info *info, int handle_errors) +{ + int error_found; + u32 eapaddr, page; + u32 syndrome; + + error_found = 0; + + /* bits 30:12 store the upper 19 bits of the 32 bit error address */ + eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13; + /* Syndrome in bits 11:4 [p.62] */ + syndrome = (info->eapr >> 4) & 0xFF; + + /* the R82600 reports at less than page * + * granularity (upper 19 bits only) */ + page = eapaddr >> PAGE_SHIFT; + + if (info->eapr & BIT(0)) { /* CE? */ + error_found = 1; + + if (handle_errors) + edac_mc_handle_ce( + mci, page, 0, /* not avail */ + syndrome, + edac_mc_find_csrow_by_page(mci, page), + 0, /* channel */ + mci->ctl_name); + } + + if (info->eapr & BIT(1)) { /* UE? */ + error_found = 1; + + if (handle_errors) + /* 82600 doesn't give enough info */ + edac_mc_handle_ue(mci, page, 0, + edac_mc_find_csrow_by_page(mci, page), + mci->ctl_name); + } + + return error_found; +} + +static void r82600_check(struct mem_ctl_info *mci) +{ + struct r82600_error_info info; + + debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + r82600_get_error_info(mci, &info); + r82600_process_error_info(mci, &info, 1); +} + +static int r82600_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc = -ENODEV; + int index; + struct mem_ctl_info *mci = NULL; + u8 dramcr; + u32 ecc_on; + u32 reg_sdram; + u32 eapr; + u32 scrub_disabled; + u32 sdram_refresh_rate; + u32 row_high_limit_last = 0; + u32 eap_init_bits; + + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + + pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); + pci_read_config_dword(pdev, R82600_EAP, &eapr); + + ecc_on = dramcr & BIT(5); + reg_sdram = dramcr & BIT(4); + scrub_disabled = eapr & BIT(31); + sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); + + debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n", + __func__, sdram_refresh_rate); + + debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__, + dramcr); + + mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); + + if (mci == NULL) { + rc = -ENOMEM; + goto fail; + } + + debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + + mci->pdev = pdev; + mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; + + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; + /* FIXME try to work out if the chip leads have been * + * used for COM2 instead on this board? [MA6?] MAYBE: */ + + /* On the R82600, the pins for memory bits 72:65 - i.e. the * + * EC bits are shared with the pins for COM2 (!), so if COM2 * + * is enabled, we assume COM2 is wired up, and thus no EDAC * + * is possible. */ + mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; + if (ecc_on) { + if (scrub_disabled) + debugf3("MC: " __FILE__ ": %s(): mci = %p - " + "Scrubbing disabled! EAP: %#0x\n", __func__, + mci, eapr); + } else + mci->edac_cap = EDAC_FLAG_NONE; + + mci->mod_name = BS_MOD_STR; + mci->mod_ver = "$Revision: 1.1.2.6 $"; + mci->ctl_name = "R82600"; + mci->edac_check = r82600_check; + mci->ctl_page_to_phys = NULL; + + for (index = 0; index < mci->nr_csrows; index++) { + struct csrow_info *csrow = &mci->csrows[index]; + u8 drbar; /* sDram Row Boundry Address Register */ + u32 row_high_limit; + u32 row_base; + + /* find the DRAM Chip Select Base address and mask */ + pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar); + + debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n", + mci->mc_idx, __func__, index, drbar); + + row_high_limit = ((u32) drbar << 24); +/* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ + + debugf1("MC%d: " __FILE__ ": %s() Row=%d, " + "Boundry Address=%#0x, Last = %#0x \n", + mci->mc_idx, __func__, index, row_high_limit, + row_high_limit_last); + + /* Empty row [p.57] */ + if (row_high_limit == row_high_limit_last) + continue; + + row_base = row_high_limit_last; + + csrow->first_page = row_base >> PAGE_SHIFT; + csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; + csrow->nr_pages = csrow->last_page - csrow->first_page + 1; + /* Error address is top 19 bits - so granularity is * + * 14 bits */ + csrow->grain = 1 << 14; + csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; + /* FIXME - check that this is unknowable with this chipset */ + csrow->dtype = DEV_UNKNOWN; + + /* Mode is global on 82600 */ + csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE; + row_high_limit_last = row_high_limit; + } + + /* clear counters */ + /* FIXME should we? */ + + if (edac_mc_add_mc(mci)) { + debugf3("MC: " __FILE__ + ": %s(): failed edac_mc_add_mc()\n", __func__); + goto fail; + } + + /* get this far and it's successful */ + + /* Clear error flags to allow next error to be reported [p.62] */ + /* Test systems seem to always have the UE flag raised on boot */ + + eap_init_bits = BIT(0) & BIT(1); + if (disable_hardware_scrub) { + eap_init_bits |= BIT(31); + debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub " + "(scrub on error)\n", __func__); + } + + pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits, + eap_init_bits); + + debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + return 0; + +fail: + if (mci) + edac_mc_free(mci); + + return rc; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit r82600_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + debugf0("MC: " __FILE__ ": %s()\n", __func__); + + /* don't need to call pci_device_enable() */ + return r82600_probe1(pdev, ent->driver_data); +} + + +static void __devexit r82600_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + + debugf0(__FILE__ ": %s()\n", __func__); + + if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) && + !edac_mc_del_mc(mci)) + edac_mc_free(mci); +} + + +static const struct pci_device_id r82600_pci_tbl[] __devinitdata = { + {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); + + +static struct pci_driver r82600_driver = { + .name = BS_MOD_STR, + .probe = r82600_init_one, + .remove = __devexit_p(r82600_remove_one), + .id_table = r82600_pci_tbl, +}; + + +static int __init r82600_init(void) +{ + return pci_register_driver(&r82600_driver); +} + + +static void __exit r82600_exit(void) +{ + pci_unregister_driver(&r82600_driver); +} + + +module_init(r82600_init); +module_exit(r82600_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. " + "on behalf of EADS Astrium"); +MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers"); + +module_param(disable_hardware_scrub, bool, 0644); +MODULE_PARM_DESC(disable_hardware_scrub, + "If set, disable the chipset's automatic scrub for CEs"); diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c58295914365..7230d4e08196 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -113,6 +113,16 @@ config SENSORS_DS1621 This driver can also be built as a module. If so, the module will be called ds1621. +config SENSORS_F71805F + tristate "Fintek F71805F/FG" + depends on HWMON && EXPERIMENTAL + help + If you say yes here you get support for hardware monitoring + features of the Fintek F71805F/FG chips. + + This driver can also be built as a module. If so, the module + will be called f71805f. + config SENSORS_FSCHER tristate "FSC Hermes" depends on HWMON && I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 06d4a1d14105..fbdb8d911a72 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o +obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c new file mode 100644 index 000000000000..e029e0a94ecc --- /dev/null +++ b/drivers/hwmon/f71805f.c @@ -0,0 +1,908 @@ +/* + * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated + * hardware monitoring features + * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> + * + * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates + * complete hardware monitoring features: voltage, fan and temperature + * sensors, and manual and automatic fan speed control. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <asm/io.h> + +static struct platform_device *pdev; + +#define DRVNAME "f71805f" + +/* + * Super-I/O constants and functions + */ + +#define F71805F_LD_HWM 0x04 + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 +#define SIO_F71805F_ID 0x0406 + +static inline int +superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int +superio_inw(int base, int reg) +{ + int val; + outb(reg++, base); + val = inb(base + 1) << 8; + outb(reg, base); + val |= inb(base + 1); + return val; +} + +static inline void +superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void +superio_enter(int base) +{ + outb(0x87, base); + outb(0x87, base); +} + +static inline void +superio_exit(int base) +{ + outb(0xaa, base); +} + +/* + * ISA constants + */ + +#define REGION_LENGTH 2 +#define ADDR_REG_OFFSET 0 +#define DATA_REG_OFFSET 1 + +static struct resource f71805f_resource __initdata = { + .flags = IORESOURCE_IO, +}; + +/* + * Registers + */ + +/* in nr from 0 to 8 (8-bit values) */ +#define F71805F_REG_IN(nr) (0x10 + (nr)) +#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr)) +#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr)) +/* fan nr from 0 to 2 (12-bit values, two registers) */ +#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr)) +#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr)) +#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr)) +/* temp nr from 0 to 2 (8-bit values) */ +#define F71805F_REG_TEMP(nr) (0x1B + (nr)) +#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) +#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) +#define F71805F_REG_TEMP_MODE 0x01 + +#define F71805F_REG_START 0x00 +/* status nr from 0 to 2 */ +#define F71805F_REG_STATUS(nr) (0x36 + (nr)) + +/* + * Data structures and manipulation thereof + */ + +struct f71805f_data { + unsigned short addr; + const char *name; + struct semaphore lock; + struct class_device *class_dev; + + struct semaphore update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long last_limits; /* In jiffies */ + + /* Register values */ + u8 in[9]; + u8 in_high[9]; + u8 in_low[9]; + u16 fan[3]; + u16 fan_low[3]; + u8 fan_enabled; /* Read once at init time */ + u8 temp[3]; + u8 temp_high[3]; + u8 temp_hyst[3]; + u8 temp_mode; + u8 alarms[3]; +}; + +static inline long in_from_reg(u8 reg) +{ + return (reg * 8); +} + +/* The 2 least significant bits are not used */ +static inline u8 in_to_reg(long val) +{ + if (val <= 0) + return 0; + if (val >= 2016) + return 0xfc; + return (((val + 16) / 32) << 2); +} + +/* in0 is downscaled by a factor 2 internally */ +static inline long in0_from_reg(u8 reg) +{ + return (reg * 16); +} + +static inline u8 in0_to_reg(long val) +{ + if (val <= 0) + return 0; + if (val >= 4032) + return 0xfc; + return (((val + 32) / 64) << 2); +} + +/* The 4 most significant bits are not used */ +static inline long fan_from_reg(u16 reg) +{ + reg &= 0xfff; + if (!reg || reg == 0xfff) + return 0; + return (1500000 / reg); +} + +static inline u16 fan_to_reg(long rpm) +{ + /* If the low limit is set below what the chip can measure, + store the largest possible 12-bit value in the registers, + so that no alarm will ever trigger. */ + if (rpm < 367) + return 0xfff; + return (1500000 / rpm); +} + +static inline long temp_from_reg(u8 reg) +{ + return (reg * 1000); +} + +static inline u8 temp_to_reg(long val) +{ + if (val < 0) + val = 0; + else if (val > 1000 * 0xff) + val = 0xff; + return ((val + 500) / 1000); +} + +/* + * Device I/O access + */ + +static u8 f71805f_read8(struct f71805f_data *data, u8 reg) +{ + u8 val; + + down(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET); + up(&data->lock); + + return val; +} + +static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) +{ + down(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val, data->addr + DATA_REG_OFFSET); + up(&data->lock); +} + +/* It is important to read the MSB first, because doing so latches the + value of the LSB, so we are sure both bytes belong to the same value. */ +static u16 f71805f_read16(struct f71805f_data *data, u8 reg) +{ + u16 val; + + down(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET) << 8; + outb(++reg, data->addr + ADDR_REG_OFFSET); + val |= inb(data->addr + DATA_REG_OFFSET); + up(&data->lock); + + return val; +} + +static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) +{ + down(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val >> 8, data->addr + DATA_REG_OFFSET); + outb(++reg, data->addr + ADDR_REG_OFFSET); + outb(val & 0xff, data->addr + DATA_REG_OFFSET); + up(&data->lock); +} + +static struct f71805f_data *f71805f_update_device(struct device *dev) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + int nr; + + down(&data->update_lock); + + /* Limit registers cache is refreshed after 60 seconds */ + if (time_after(jiffies, data->last_updated + 60 * HZ) + || !data->valid) { + for (nr = 0; nr < 9; nr++) { + data->in_high[nr] = f71805f_read8(data, + F71805F_REG_IN_HIGH(nr)); + data->in_low[nr] = f71805f_read8(data, + F71805F_REG_IN_LOW(nr)); + } + for (nr = 0; nr < 3; nr++) { + if (data->fan_enabled & (1 << nr)) + data->fan_low[nr] = f71805f_read16(data, + F71805F_REG_FAN_LOW(nr)); + } + for (nr = 0; nr < 3; nr++) { + data->temp_high[nr] = f71805f_read8(data, + F71805F_REG_TEMP_HIGH(nr)); + data->temp_hyst[nr] = f71805f_read8(data, + F71805F_REG_TEMP_HYST(nr)); + } + data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); + + data->last_limits = jiffies; + } + + /* Measurement registers cache is refreshed after 1 second */ + if (time_after(jiffies, data->last_updated + HZ) + || !data->valid) { + for (nr = 0; nr < 9; nr++) { + data->in[nr] = f71805f_read8(data, + F71805F_REG_IN(nr)); + } + for (nr = 0; nr < 3; nr++) { + if (data->fan_enabled & (1 << nr)) + data->fan[nr] = f71805f_read16(data, + F71805F_REG_FAN(nr)); + } + for (nr = 0; nr < 3; nr++) { + data->temp[nr] = f71805f_read8(data, + F71805F_REG_TEMP(nr)); + } + for (nr = 0; nr < 3; nr++) { + data->alarms[nr] = f71805f_read8(data, + F71805F_REG_STATUS(nr)); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +/* + * Sysfs interface + */ + +static ssize_t show_in0(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%ld\n", in0_from_reg(data->in[0])); +} + +static ssize_t show_in0_max(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0])); +} + +static ssize_t show_in0_min(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0])); +} + +static ssize_t set_in0_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->in_high[0] = in0_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); + up(&data->update_lock); + + return count; +} + +static ssize_t set_in0_min(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->in_low[0] = in0_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); + up(&data->update_lock); + + return count; +} + +static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); +static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); +static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); + +static ssize_t show_in(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", in_from_reg(data->in[nr])); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr])); +} + +static ssize_t show_in_min(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr])); +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->in_high[nr] = in_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); + up(&data->update_lock); + + return count; +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->in_low[nr] = in_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); + up(&data->update_lock); + + return count; +} + +#define sysfs_in(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset) + +sysfs_in(1); +sysfs_in(2); +sysfs_in(3); +sysfs_in(4); +sysfs_in(5); +sysfs_in(6); +sysfs_in(7); +sysfs_in(8); + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr])); +} + +static ssize_t show_fan_min(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr])); +} + +static ssize_t set_fan_min(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->fan_low[nr] = fan_to_reg(val); + f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); + up(&data->update_lock); + + return count; +} + +#define sysfs_fan(offset) \ +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1) + +sysfs_fan(1); +sysfs_fan(2); +sysfs_fan(3); + +static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr])); +} + +static ssize_t show_temp_hyst(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr])); +} + +static ssize_t show_temp_type(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + + /* 3 is diode, 4 is thermistor */ + return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4); +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_high[nr] = temp_to_reg(val); + f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); + up(&data->update_lock); + + return count; +} + +static ssize_t set_temp_hyst(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_hyst[nr] = temp_to_reg(val); + f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); + up(&data->update_lock); + + return count; +} + +#define sysfs_temp(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ + show_temp_hyst, set_temp_hyst, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ + show_temp_type, NULL, offset - 1) + +sysfs_temp(1); +sysfs_temp(2); +sysfs_temp(3); + +static ssize_t show_alarms_in(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%d\n", data->alarms[0] | + ((data->alarms[1] & 0x01) << 8)); +} + +static ssize_t show_alarms_fan(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%d\n", data->alarms[2] & 0x07); +} + +static ssize_t show_alarms_temp(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = f71805f_update_device(dev); + + return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); +} + +static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); +static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); +static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); + +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", data->name); +} + +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +/* + * Device registration and initialization + */ + +static void __devinit f71805f_init_device(struct f71805f_data *data) +{ + u8 reg; + int i; + + reg = f71805f_read8(data, F71805F_REG_START); + if ((reg & 0x41) != 0x01) { + printk(KERN_DEBUG DRVNAME ": Starting monitoring " + "operations\n"); + f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40); + } + + /* Fan monitoring can be disabled. If it is, we won't be polling + the register values, and won't create the related sysfs files. */ + for (i = 0; i < 3; i++) { + reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i)); + if (!(reg & 0x80)) + data->fan_enabled |= (1 << i); + } +} + +static int __devinit f71805f_probe(struct platform_device *pdev) +{ + struct f71805f_data *data; + struct resource *res; + int err; + + if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { + err = -ENOMEM; + printk(KERN_ERR DRVNAME ": Out of memory\n"); + goto exit; + } + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + data->addr = res->start; + init_MUTEX(&data->lock); + data->name = "f71805f"; + init_MUTEX(&data->update_lock); + + platform_set_drvdata(pdev, data); + + data->class_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + dev_err(&pdev->dev, "Class registration failed (%d)\n", err); + goto exit_free; + } + + /* Initialize the F71805F chip */ + f71805f_init_device(data); + + /* Register sysfs interface files */ + device_create_file(&pdev->dev, &dev_attr_in0_input); + device_create_file(&pdev->dev, &dev_attr_in0_max); + device_create_file(&pdev->dev, &dev_attr_in0_min); + device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); + if (data->fan_enabled & (1 << 0)) { + device_create_file(&pdev->dev, + &sensor_dev_attr_fan1_input.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_fan1_min.dev_attr); + } + if (data->fan_enabled & (1 << 1)) { + device_create_file(&pdev->dev, + &sensor_dev_attr_fan2_input.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_fan2_min.dev_attr); + } + if (data->fan_enabled & (1 << 2)) { + device_create_file(&pdev->dev, + &sensor_dev_attr_fan3_input.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_fan3_min.dev_attr); + } + device_create_file(&pdev->dev, + &sensor_dev_attr_temp1_input.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_temp3_input.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_temp1_max_hyst.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_temp2_max_hyst.dev_attr); + device_create_file(&pdev->dev, + &sensor_dev_attr_temp3_max_hyst.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); + device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); + device_create_file(&pdev->dev, &dev_attr_alarms_in); + device_create_file(&pdev->dev, &dev_attr_alarms_fan); + device_create_file(&pdev->dev, &dev_attr_alarms_temp); + device_create_file(&pdev->dev, &dev_attr_name); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static int __devexit f71805f_remove(struct platform_device *pdev) +{ + struct f71805f_data *data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + hwmon_device_unregister(data->class_dev); + kfree(data); + + return 0; +} + +static struct platform_driver f71805f_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, + .probe = f71805f_probe, + .remove = __devexit_p(f71805f_remove), +}; + +static int __init f71805f_device_add(unsigned short address) +{ + int err; + + pdev = platform_device_alloc(DRVNAME, address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + goto exit; + } + + f71805f_resource.start = address; + f71805f_resource.end = address + REGION_LENGTH - 1; + f71805f_resource.name = pdev->name; + err = platform_device_add_resources(pdev, &f71805f_resource, 1); + if (err) { + printk(KERN_ERR DRVNAME ": Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + +static int __init f71805f_find(int sioaddr, unsigned short *address) +{ + int err = -ENODEV; + u16 devid; + + superio_enter(sioaddr); + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) + goto exit; + + devid = superio_inw(sioaddr, SIO_REG_DEVID); + if (devid != SIO_F71805F_ID) { + printk(KERN_INFO DRVNAME ": Unsupported Fintek device, " + "skipping\n"); + goto exit; + } + + superio_select(sioaddr, F71805F_LD_HWM); + if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { + printk(KERN_WARNING DRVNAME ": Device not activated, " + "skipping\n"); + goto exit; + } + + *address = superio_inw(sioaddr, SIO_REG_ADDR); + if (*address == 0) { + printk(KERN_WARNING DRVNAME ": Base address not set, " + "skipping\n"); + goto exit; + } + + err = 0; + printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n", + *address, superio_inb(sioaddr, SIO_REG_DEVREV)); + +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71805f_init(void) +{ + int err; + unsigned short address; + + if (f71805f_find(0x2e, &address) + && f71805f_find(0x4e, &address)) + return -ENODEV; + + err = platform_driver_register(&f71805f_driver); + if (err) + goto exit; + + /* Sets global pdev as a side effect */ + err = f71805f_device_add(address); + if (err) + goto exit_driver; + + return 0; + +exit_driver: + platform_driver_unregister(&f71805f_driver); +exit: + return err; +} + +static void __exit f71805f_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&f71805f_driver); +} + +MODULE_AUTHOR("Jean Delvare <khali@linux-fr>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("F71805F hardware monitoring driver"); + +module_init(f71805f_init); +module_exit(f71805f_exit); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0da7c9c508c3..e87d52c59940 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -45,8 +45,7 @@ /* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; static unsigned short isa_address; /* Insmod parameters */ @@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = i2c_attach_client(new_client))) goto ERROR2; + if (!is_isa) + dev_info(&new_client->dev, "The I2C interface to IT87xxF " + "hardware monitoring chips is deprecated. Please " + "report if you still rely on it.\n"); + /* Check PWM configuration */ enable_pwm_interface = it87_check_pwm(new_client); diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index a2f420d01fb7..df9e02aaa70a 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = { /* In the temperature registers, the low 3 bits are not part of the temperature values; they are the status bits. */ -static inline u16 LM77_TEMP_TO_REG(int temp) +static inline s16 LM77_TEMP_TO_REG(int temp) { int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); - return (u16)((ntemp / 500) * 8); + return (ntemp / 500) * 8; } -static inline int LM77_TEMP_FROM_REG(u16 reg) +static inline int LM77_TEMP_FROM_REG(s16 reg) { - return ((int)reg / 8) * 500; + return (reg / 8) * 500; } /* sysfs stuff */ diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index b176bf0c4c7b..a2f6bb676235 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -303,10 +303,6 @@ struct w83792d_data { static int w83792d_attach_adapter(struct i2c_adapter *adapter); static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); static int w83792d_detach_client(struct i2c_client *client); - -static int w83792d_read_value(struct i2c_client *client, u8 register); -static int w83792d_write_value(struct i2c_client *client, u8 register, - u8 value); static struct w83792d_data *w83792d_update_device(struct device *dev); #ifdef DEBUG @@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data) return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03)); } +/* The SMBus locks itself. The Winbond W83792D chip has a bank register, + but the driver only accesses registers in bank 0, so we don't have + to switch banks and lock access between switches. */ +static inline int w83792d_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static inline int +w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + /* following are the sysfs callback functions */ static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf) @@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client) return 0; } -/* The SMBus locks itself. The Winbond W83792D chip has a bank register, - but the driver only accesses registers in bank 0, so we don't have - to switch banks and lock access between switches. */ -static int w83792d_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - static void w83792d_init_client(struct i2c_client *client) { diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c index 938848ae162d..3df3f09995c2 100644 --- a/drivers/i2c/algos/i2c-algo-sibyte.c +++ b/drivers/i2c/algos/i2c-algo-sibyte.c @@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus); #ifdef MODULE MODULE_AUTHOR("Kip Walker, Broadcom Corp."); MODULE_DESCRIPTION("SiByte I2C-Bus algorithm"); -MODULE_PARM(bit_scan, "i"); +module_param(bit_scan, int, 0); MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 08d5b8fed2dc..ff92735c7c85 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -124,6 +124,7 @@ config I2C_I801 ICH6 ICH7 ESB2 + ICH8 This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1c752ddc10e2..8e0f3158215f 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -32,6 +32,7 @@ ICH6 266A ICH7 27DA ESB2 269B + ICH8 283E This driver supports several versions of Intel's I/O Controller Hubs (ICH). For SMBus support, they are similar to the PIIX4 and are part of Intel's '810' and other chipsets. @@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 3e5eba9fcacb..c63025a4c861 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = { static int __init i2c_parport_init(void) { - int type_count; - - type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); - if (type < 0 || type >= type_count) { + if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); type = 0; } - + if (base == 0) { printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE); base = DEFAULT_BASE; @@ -152,7 +149,7 @@ static int __init i2c_parport_init(void) release_region(base, 3); return -ENODEV; } - + return 0; } diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 2854d858fc9b..7e2e8cd1c14a 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = { static int __init i2c_parport_init(void) { - int type_count; - - type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); - if (type < 0 || type >= type_count) { + if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); type = 0; } - + return parport_register_driver(&i2c_parport_driver); } diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 86e2234faf80..7579f4b256a8 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r decode_ISR(isr); } - if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32)) + if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog)) i2c->isrlog[i2c->irqlogidx++] = isr; show_state(i2c); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0ce58b506046..1a2c9ab5d9e3 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val } } +s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, + u8 length, u8 *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + memcpy(data.block + 1, values, length); + return i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); +} + /* Simulate a SMBus command using the i2c protocol No checking of parameters is done! */ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, @@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_write_word_data); EXPORT_SYMBOL(i2c_smbus_write_block_data); EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); +EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_DESCRIPTION("I2C-Bus main module"); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 1c81174595b3..d633081fa4c5 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -52,9 +52,9 @@ config IDE if IDE -config IDE_MAX_HWIFS +config IDE_MAX_HWIFS int "Max IDE interfaces" - depends on ALPHA || SUPERH + depends on ALPHA || SUPERH || IA64 default 4 help This is the maximum number of IDE hardware interfaces that will @@ -162,8 +162,8 @@ config BLK_DEV_IDECS tristate "PCMCIA IDE support" depends on PCMCIA help - Support for outboard IDE disks, tape drives, and CD-ROM drives - connected through a PCMCIA card. + Support for Compact Flash cards, outboard IDE disks, tape drives, + and CD-ROM drives connected through a PCMCIA card. config BLK_DEV_IDECD tristate "Include IDE/ATAPI CDROM support" @@ -267,7 +267,7 @@ config IDE_TASK_IOCTL help This is a direct raw access to the media. It is a complex but elegant solution to test and validate the domain of the hardware and - perform below the driver data recover if needed. This is the most + perform below the driver data recovery if needed. This is the most basic form of media-forensics. If you are unsure, say N here. @@ -525,7 +525,7 @@ config BLK_DEV_CS5520 tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)" depends on EXPERIMENTAL help - Include support for PIO tuning an virtual DMA on the Cyrix MediaGX + Include support for PIO tuning and virtual DMA on the Cyrix MediaGX 5510/5520 chipset. This will automatically be detected and configured if found. @@ -662,7 +662,7 @@ config PDC202XX_BURST It was originally designed for the PDC20246/Ultra33, whose BIOS will only setup UDMA on the first two PDC20246 cards. It has also been - used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes + used successfully on a PDC20265/Ultra100, allowing use of UDMA modes when the PDC20265 BIOS has been disabled (for faster boot up). Please read the comments at the top of @@ -673,13 +673,6 @@ config PDC202XX_BURST config BLK_DEV_PDC202XX_NEW tristate "PROMISE PDC202{68|69|70|71|75|76|77} support" -# FIXME - probably wants to be one for old and for new -config PDC202XX_FORCE - bool "Enable controller even if disabled by BIOS" - depends on BLK_DEV_PDC202XX_NEW - help - Enable the PDC202xx controller even if it has been disabled in the BIOS setup. - config BLK_DEV_SVWKS tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support" help @@ -722,7 +715,7 @@ config BLK_DEV_SIS5513 config BLK_DEV_SLC90E66 tristate "SLC90E66 chipset support" help - This driver ensures (U)DMA support for Victroy66 SouthBridges for + This driver ensures (U)DMA support for Victory66 SouthBridges for SMsC with Intel NorthBridges. This is an Ultra66 based chipset. The nice thing about it is that you can mix Ultra/DMA/PIO devices and it will handle timing cycles. Since this is an improved @@ -1060,7 +1053,7 @@ config IDEDMA_IVB in that mode with an 80c ribbon. If you are experiencing compatibility or performance problems, you - MAY try to answering Y here. However, it does not necessarily solve + MAY try to answer Y here. However, it does not necessarily solve any of your problems, it could even cause more of them. It is normally safe to answer Y; however, the default is N. diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ca25f9e3d0f4..09086b8b6486 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -190,7 +190,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, if (lba48) { task_ioreg_t tasklets[10]; - pr_debug("%s: LBA=0x%012llx\n", drive->name, block); + pr_debug("%s: LBA=0x%012llx\n", drive->name, + (unsigned long long)block); tasklets[0] = 0; tasklets[1] = 0; @@ -317,7 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", drive->name, rq_data_dir(rq) == READ ? "read" : "writ", - block, rq->nr_sectors, (unsigned long)rq->buffer); + (unsigned long long)block, rq->nr_sectors, + (unsigned long)rq->buffer); if (hwif->rw_disk) hwif->rw_disk(drive, rq); @@ -776,7 +778,7 @@ static void update_ordered(ide_drive_t *drive) ide_id_has_flush_cache_ext(id)); printk(KERN_INFO "%s: cache flushes %ssupported\n", - drive->name, barrier ? "" : "not"); + drive->name, barrier ? "" : "not "); if (barrier) { ordered = QUEUE_ORDERED_DRAIN_FLUSH; @@ -889,11 +891,7 @@ static void idedisk_setup (ide_drive_t *drive) if (drive->id_read == 0) return; - /* - * CompactFlash cards and their brethern look just like hard drives - * to us, but they are removable and don't have a doorlock mechanism. - */ - if (drive->removable && !(drive->is_flash)) { + if (drive->removable) { /* * Removable disks (eg. SYQUEST); ignore 'WD' drives */ diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8d50df4526a4..c01615dec202 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -55,8 +55,8 @@ #include <asm/io.h> #include <asm/bitops.h> -int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, - int nr_sectors) +static int __ide_end_request(ide_drive_t *drive, struct request *rq, + int uptodate, int nr_sectors) { int ret = 1; @@ -91,7 +91,6 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, return ret; } -EXPORT_SYMBOL(__ide_end_request); /** * ide_end_request - complete an IDE I/O diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index af7af958ab3e..b72dde70840a 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1243,6 +1243,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) */ if (stat == 0xff) return -ENODEV; + touch_softlockup_watchdog(); } return -EBUSY; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e7425546b4b1..427d1c204174 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -125,45 +125,6 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) } /** - * drive_is_flashcard - check for compact flash - * @drive: drive to check - * - * CompactFlash cards and their brethern pretend to be removable - * hard disks, except: - * (1) they never have a slave unit, and - * (2) they don't have doorlock mechanisms. - * This test catches them, and is invoked elsewhere when setting - * appropriate config bits. - * - * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) - * devices, so in linux 2.3.x we should change this to just treat all - * PCMCIA drives this way, and get rid of the model-name tests below - * (too big of an interface change for 2.4.x). - * At that time, we might also consider parameterizing the timeouts and - * retries, since these are MUCH faster than mechanical drives. -M.Lord - */ - -static inline int drive_is_flashcard (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - - if (drive->removable) { - if (id->config == 0x848a) return 1; /* CompactFlash */ - if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ - || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ - || !strncmp(id->model, "SunDisk SDCFB", 13) /* old SanDisk */ - || !strncmp(id->model, "SanDisk SDCFB", 13) /* SanDisk */ - || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ - || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ - || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ - { - return 1; /* yes, it is a flash memory card */ - } - } - return 0; /* no, it is not a flash memory card */ -} - -/** * do_identify - identify a drive * @drive: drive to identify * @cmd: command used @@ -278,13 +239,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) /* * Not an ATAPI device: looks like a "regular" hard disk */ - if (id->config & (1<<7)) + + /* + * 0x848a = CompactFlash device + * These are *not* removable in Linux definition of the term + */ + + if ((id->config != 0x848a) && (id->config & (1<<7))) drive->removable = 1; - if (drive_is_flashcard(drive)) - drive->is_flash = 1; drive->media = ide_disk; - printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" ); + printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); QUIRK_LIST(drive); return; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index afeb02bbb722..b2cc43702f65 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -242,7 +242,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->using_dma = 0; - drive->is_flash = 0; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); init_completion(&drive->gendev_rel_comp); diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index a21b1e11eef4..c743e68c33aa 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -262,6 +262,21 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch else pci_set_drvdata(dev, (void *) aec6xxx_34_base); + /* These are necessary to get AEC6280 Macintosh cards to work */ + if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || + (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) { + u8 reg49h = 0, reg4ah = 0; + /* Clear reset and test bits. */ + pci_read_config_byte(dev, 0x49, ®49h); + pci_write_config_byte(dev, 0x49, reg49h & ~0x30); + /* Enable chip interrupt output. */ + pci_read_config_byte(dev, 0x4a, ®4ah); + pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01); + /* Enable burst mode. */ + pci_read_config_byte(dev, 0x4a, ®4ah); + pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); + } + return dev->irq; } diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 7b589d948bf9..940bdd4c5784 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1288,6 +1288,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) goto init_hpt37X_done; } } + if (!pci_get_drvdata(dev)) { + printk("No Clock Stabilization!!!\n"); + return; + } pll_recal: if (adjust & 1) pll -= (adjust >> 1); diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 108fda83fea4..38f41b377ff6 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -733,7 +733,7 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev) pci_write_config_dword(dev,0x4C, 0x02040204); pci_write_config_byte(dev, 0x42, 0x36); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name) diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index fe06ebb0e5bf..acd63173199b 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -420,9 +420,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 3 */ .name = "PDC20271", @@ -447,9 +444,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .init_hwif = init_hwif_pdc202new, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, },{ /* 6 */ .name = "PDC20277", diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index ad9d95817f95..6f8f8645b02c 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -786,9 +786,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 16, },{ /* 1 */ @@ -799,9 +796,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, .flags = IDEPCI_FLAG_FORCE_PDC, @@ -813,9 +807,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, },{ /* 3 */ @@ -826,9 +817,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, .flags = IDEPCI_FLAG_FORCE_PDC, @@ -840,9 +828,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .init_dma = init_dma_pdc202xx, .channels = 2, .autodma = AUTODMA, -#ifndef CONFIG_PDC202XX_FORCE - .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, -#endif .bootable = OFF_BOARD, .extra = 48, } diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index b3e77df63cef..e9b83e1a3028 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -135,6 +135,7 @@ static u8 piix_ratemask (ide_drive_t *drive) case PCI_DEVICE_ID_INTEL_ICH6_19: case PCI_DEVICE_ID_INTEL_ICH7_21: case PCI_DEVICE_ID_INTEL_ESB2_18: + case PCI_DEVICE_ID_INTEL_ICH8_6: mode = 3; break; /* UDMA 66 capable */ @@ -449,6 +450,7 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char case PCI_DEVICE_ID_INTEL_ICH6_19: case PCI_DEVICE_ID_INTEL_ICH7_21: case PCI_DEVICE_ID_INTEL_ESB2_18: + case PCI_DEVICE_ID_INTEL_ICH8_6: { unsigned int extra = 0; pci_read_config_dword(dev, 0x54, &extra); @@ -575,6 +577,7 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { /* 21 */ DECLARE_PIIX_DEV("ICH7"), /* 22 */ DECLARE_PIIX_DEV("ICH4"), /* 23 */ DECLARE_PIIX_DEV("ESB2"), + /* 24 */ DECLARE_PIIX_DEV("ICH8M"), }; /** @@ -651,6 +654,7 @@ static struct pci_device_id piix_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24}, { 0, }, }; MODULE_DEVICE_TABLE(pci, piix_pci_tbl); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 4ee597d08797..2b286e865163 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -510,7 +510,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) drive->name); goto use_pio_instead; } else { - u32 xcount, bcount = + u32 bcount = 0x10000 - (cur_addr & 0xffff); if (bcount > cur_len) @@ -525,8 +525,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) *table = 0x0; table++; - xcount = bcount & 0xffff; - *table = cpu_to_be32(xcount); + *table = cpu_to_be32(bcount); table++; cur_addr += bcount; @@ -680,7 +679,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) return -EIO; /* Create /proc/ide entries */ - create_proc_ide_interfaces(); + create_proc_ide_interfaces(); return 0; } diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index acda7d63d6fe..501cc054cb3b 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -956,6 +956,8 @@ static void ib_sa_remove_one(struct ib_device *device) ib_unregister_event_handler(&sa_dev->event_handler); + flush_scheduled_work(); + for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { ib_unregister_mad_agent(sa_dev->port[i].agent); kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index e95c4293a496..f6a05965a4e8 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -1319,15 +1319,6 @@ static struct class ucm_class = { .release = ib_ucm_release_class_dev }; -static ssize_t show_dev(struct class_device *class_dev, char *buf) -{ - struct ib_ucm_device *dev; - - dev = container_of(class_dev, struct ib_ucm_device, class_dev); - return print_dev_t(buf, dev->dev.dev); -} -static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); - static ssize_t show_ibdev(struct class_device *class_dev, char *buf) { struct ib_ucm_device *dev; @@ -1364,15 +1355,13 @@ static void ib_ucm_add_one(struct ib_device *device) ucm_dev->class_dev.class = &ucm_class; ucm_dev->class_dev.dev = device->dma_device; + ucm_dev->class_dev.devt = ucm_dev->dev.dev; snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d", ucm_dev->devnum); if (class_device_register(&ucm_dev->class_dev)) goto err_cdev; if (class_device_create_file(&ucm_dev->class_dev, - &class_device_attr_dev)) - goto err_class; - if (class_device_create_file(&ucm_dev->class_dev, &class_device_attr_ibdev)) goto err_class; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 96ea79b63df7..903f85a4bc0c 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -902,6 +902,7 @@ static void __exit ib_uverbs_cleanup(void) unregister_filesystem(&uverbs_event_fs); class_destroy(uverbs_class); unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); + flush_scheduled_work(); idr_destroy(&ib_uverbs_pd_idr); idr_destroy(&ib_uverbs_mr_idr); idr_destroy(&ib_uverbs_mw_idr); diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index a14eed08a0fc..a19e0ed03d7c 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -184,7 +184,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff); ib_get_cached_gid(&dev->ib_dev, be32_to_cpu(ah->av->port_pd) >> 24, - ah->av->gid_index, + ah->av->gid_index % dev->limits.gid_table_len, &header->grh.source_gid); memcpy(header->grh.destination_gid.raw, ah->av->dgid, 16); diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index be1791be627b..f9b9b93dc501 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -199,8 +199,7 @@ static int mthca_cmd_post(struct mthca_dev *dev, { int err = 0; - if (down_interruptible(&dev->cmd.hcr_sem)) - return -EINTR; + mutex_lock(&dev->cmd.hcr_mutex); if (event) { unsigned long end = jiffies + GO_BIT_TIMEOUT; @@ -238,7 +237,7 @@ static int mthca_cmd_post(struct mthca_dev *dev, op), dev->hcr + 6 * 4); out: - up(&dev->cmd.hcr_sem); + mutex_unlock(&dev->cmd.hcr_mutex); return err; } @@ -255,8 +254,7 @@ static int mthca_cmd_poll(struct mthca_dev *dev, int err = 0; unsigned long end; - if (down_interruptible(&dev->cmd.poll_sem)) - return -EINTR; + down(&dev->cmd.poll_sem); err = mthca_cmd_post(dev, in_param, out_param ? *out_param : 0, @@ -333,8 +331,7 @@ static int mthca_cmd_wait(struct mthca_dev *dev, int err = 0; struct mthca_cmd_context *context; - if (down_interruptible(&dev->cmd.event_sem)) - return -EINTR; + down(&dev->cmd.event_sem); spin_lock(&dev->cmd.context_lock); BUG_ON(dev->cmd.free_head < 0); @@ -438,7 +435,7 @@ static int mthca_cmd_imm(struct mthca_dev *dev, int mthca_cmd_init(struct mthca_dev *dev) { - sema_init(&dev->cmd.hcr_sem, 1); + mutex_init(&dev->cmd.hcr_mutex); sema_init(&dev->cmd.poll_sem, 1); dev->cmd.use_events = 0; diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index a104ab041ea3..2a165fd06e57 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -44,6 +44,8 @@ #include <linux/pci.h> #include <linux/dma-mapping.h> #include <linux/timer.h> +#include <linux/mutex.h> + #include <asm/semaphore.h> #include "mthca_provider.h" @@ -111,7 +113,7 @@ enum { struct mthca_cmd { struct pci_pool *pool; int use_events; - struct semaphore hcr_sem; + struct mutex hcr_mutex; struct semaphore poll_sem; struct semaphore event_sem; int max_cmds; @@ -256,7 +258,7 @@ struct mthca_av_table { }; struct mthca_mcg_table { - struct semaphore sem; + struct mutex mutex; struct mthca_alloc alloc; struct mthca_icm_table *table; }; @@ -301,7 +303,7 @@ struct mthca_dev { u64 ddr_end; MTHCA_DECLARE_DOORBELL_LOCK(doorbell_lock) - struct semaphore cap_mask_mutex; + struct mutex cap_mask_mutex; void __iomem *hcr; void __iomem *kar; diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 8b00d9a0f6f4..9c849d27b06e 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -155,6 +155,13 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim return -ENODEV; } + if (dev_lim->uar_size > pci_resource_len(mdev->pdev, 2)) { + mthca_err(mdev, "HCA reported UAR size of 0x%x bigger than " + "PCI resource 2 size of 0x%lx, aborting.\n", + dev_lim->uar_size, pci_resource_len(mdev->pdev, 2)); + return -ENODEV; + } + mdev->limits.num_ports = dev_lim->num_ports; mdev->limits.vl_cap = dev_lim->max_vl; mdev->limits.mtu_cap = dev_lim->max_mtu; @@ -976,8 +983,7 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, err = -ENODEV; goto err_disable_pdev; } - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) || - pci_resource_len(pdev, 2) != 1 << 23) { + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { dev_err(&pdev->dev, "Missing UAR, aborting.\n"); err = -ENODEV; goto err_disable_pdev; diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 77bc6c746f43..321f11e707f2 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -154,10 +154,7 @@ 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; - } + mutex_lock(&dev->mcg_table.mutex); err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); if (err) @@ -241,8 +238,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) BUG_ON(index < dev->limits.num_mgms); mthca_free(&dev->mcg_table.alloc, index); } - up(&dev->mcg_table.sem); - err_sem: + mutex_unlock(&dev->mcg_table.mutex); + mthca_free_mailbox(dev, mailbox); return err; } @@ -263,10 +260,7 @@ 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; - } + mutex_lock(&dev->mcg_table.mutex); err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); if (err) @@ -371,8 +365,8 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) } out: - up(&dev->mcg_table.sem); - err_sem: + mutex_unlock(&dev->mcg_table.mutex); + mthca_free_mailbox(dev, mailbox); return err; } @@ -389,7 +383,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev) if (err) return err; - init_MUTEX(&dev->mcg_table.sem); + mutex_init(&dev->mcg_table.mutex); return 0; } diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 9fb985a016e9..d709cb162a72 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -50,7 +50,7 @@ enum { }; struct mthca_user_db_table { - struct semaphore mutex; + struct mutex mutex; struct { u64 uvirt; struct scatterlist mem; @@ -158,7 +158,7 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob int ret = 0; u8 status; - down(&table->mutex); + mutex_lock(&table->mutex); if (table->icm[i]) { ++table->icm[i]->refcount; @@ -184,7 +184,7 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob ++table->icm[i]->refcount; out: - up(&table->mutex); + mutex_unlock(&table->mutex); return ret; } @@ -198,7 +198,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE; - down(&table->mutex); + mutex_lock(&table->mutex); if (--table->icm[i]->refcount == 0) { mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE, @@ -207,7 +207,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o table->icm[i] = NULL; } - up(&table->mutex); + mutex_unlock(&table->mutex); } void *mthca_table_find(struct mthca_icm_table *table, int obj) @@ -220,7 +220,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj) if (!table->lowmem) return NULL; - down(&table->mutex); + mutex_lock(&table->mutex); idx = (obj & (table->num_obj - 1)) * table->obj_size; icm = table->icm[idx / MTHCA_TABLE_CHUNK_SIZE]; @@ -240,7 +240,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj) } out: - up(&table->mutex); + mutex_unlock(&table->mutex); return page ? lowmem_page_address(page) + offset : NULL; } @@ -301,7 +301,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, table->num_obj = nobj; table->obj_size = obj_size; table->lowmem = use_lowmem; - init_MUTEX(&table->mutex); + mutex_init(&table->mutex); for (i = 0; i < num_icm; ++i) table->icm[i] = NULL; @@ -380,7 +380,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, if (index < 0 || index > dev->uar_table.uarc_size / 8) return -EINVAL; - down(&db_tab->mutex); + mutex_lock(&db_tab->mutex); i = index / MTHCA_DB_REC_PER_PAGE; @@ -424,7 +424,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, db_tab->page[i].refcount = 1; out: - up(&db_tab->mutex); + mutex_unlock(&db_tab->mutex); return ret; } @@ -439,11 +439,11 @@ void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar, * pages until we clean up the whole db table. */ - down(&db_tab->mutex); + mutex_lock(&db_tab->mutex); --db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount; - up(&db_tab->mutex); + mutex_unlock(&db_tab->mutex); } struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev) @@ -460,7 +460,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev) if (!db_tab) return ERR_PTR(-ENOMEM); - init_MUTEX(&db_tab->mutex); + mutex_init(&db_tab->mutex); for (i = 0; i < npages; ++i) { db_tab->page[i].refcount = 0; db_tab->page[i].uvirt = 0; @@ -499,7 +499,7 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, int ret = 0; u8 status; - down(&dev->db_tab->mutex); + mutex_lock(&dev->db_tab->mutex); switch (type) { case MTHCA_DB_TYPE_CQ_ARM: @@ -585,7 +585,7 @@ found: *db = (__be32 *) &page->db_rec[j]; out: - up(&dev->db_tab->mutex); + mutex_unlock(&dev->db_tab->mutex); return ret; } @@ -601,7 +601,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index) page = dev->db_tab->page + i; - down(&dev->db_tab->mutex); + mutex_lock(&dev->db_tab->mutex); page->db_rec[j] = 0; if (i >= dev->db_tab->min_group2) @@ -624,7 +624,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index) ++dev->db_tab->min_group2; } - up(&dev->db_tab->mutex); + mutex_unlock(&dev->db_tab->mutex); } int mthca_init_db_tab(struct mthca_dev *dev) @@ -638,7 +638,7 @@ int mthca_init_db_tab(struct mthca_dev *dev) if (!dev->db_tab) return -ENOMEM; - init_MUTEX(&dev->db_tab->mutex); + mutex_init(&dev->db_tab->mutex); dev->db_tab->npages = dev->uar_table.uarc_size / 4096; dev->db_tab->max_group1 = 0; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h index 4fdca26eea85..36f1141a08aa 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.h +++ b/drivers/infiniband/hw/mthca/mthca_memfree.h @@ -39,8 +39,7 @@ #include <linux/list.h> #include <linux/pci.h> - -#include <asm/semaphore.h> +#include <linux/mutex.h> #define MTHCA_ICM_CHUNK_LEN \ ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ @@ -64,7 +63,7 @@ struct mthca_icm_table { int num_obj; int obj_size; int lowmem; - struct semaphore mutex; + struct mutex mutex; struct mthca_icm *icm[0]; }; @@ -147,7 +146,7 @@ struct mthca_db_table { int max_group1; int min_group2; struct mthca_db_page *page; - struct semaphore mutex; + struct mutex mutex; }; enum mthca_db_type { diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 484a7e6b7f8c..e88e39aef85a 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -185,7 +185,7 @@ static int mthca_modify_port(struct ib_device *ibdev, int err; u8 status; - if (down_interruptible(&to_mdev(ibdev)->cap_mask_mutex)) + if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex)) return -ERESTARTSYS; err = mthca_query_port(ibdev, port, &attr); @@ -207,7 +207,7 @@ static int mthca_modify_port(struct ib_device *ibdev, } out: - up(&to_mdev(ibdev)->cap_mask_mutex); + mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex); return err; } @@ -1185,7 +1185,7 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.post_recv = mthca_tavor_post_receive; } - init_MUTEX(&dev->cap_mask_mutex); + mutex_init(&dev->cap_mask_mutex); ret = ib_register_device(&dev->ib_dev); if (ret) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index fd3f5c862a5d..c3b5f79d1168 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -505,7 +505,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) list_add_tail(&neigh->list, &path->neigh_list); - if (path->pathrec.dlid) { + if (path->ah) { kref_get(&path->ah->ref); neigh->ah = path->ah; @@ -591,7 +591,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, return; } - if (path->pathrec.dlid) { + if (path->ah) { ipoib_dbg(priv, "Send unicast ARP to %04x\n", be16_to_cpu(path->pathrec.dlid)); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 98039da0caf0..ccaa0c387076 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -97,6 +97,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_neigh *neigh, *tmp; unsigned long flags; + int tx_dropped = 0; ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group " IPOIB_GID_FMT "\n", @@ -123,8 +124,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) if (mcast->ah) ipoib_put_ah(mcast->ah); - while (!skb_queue_empty(&mcast->pkt_queue)) + while (!skb_queue_empty(&mcast->pkt_queue)) { + ++tx_dropped; dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); + } + + spin_lock_irqsave(&priv->tx_lock, flags); + priv->stats.tx_dropped += tx_dropped; + spin_unlock_irqrestore(&priv->tx_lock, flags); kfree(mcast); } @@ -276,8 +283,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, } /* actually send any queued packets */ + spin_lock_irq(&priv->tx_lock); while (!skb_queue_empty(&mcast->pkt_queue)) { struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); + spin_unlock_irq(&priv->tx_lock); skb->dev = dev; @@ -288,7 +297,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, if (dev_queue_xmit(skb)) ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n"); + spin_lock_irq(&priv->tx_lock); } + spin_unlock_irq(&priv->tx_lock); return 0; } @@ -300,6 +311,7 @@ ipoib_mcast_sendonly_join_complete(int status, { struct ipoib_mcast *mcast = mcast_ptr; struct net_device *dev = mcast->dev; + struct ipoib_dev_priv *priv = netdev_priv(dev); if (!status) ipoib_mcast_join_finish(mcast, mcmember); @@ -310,8 +322,12 @@ ipoib_mcast_sendonly_join_complete(int status, IPOIB_GID_ARG(mcast->mcmember.mgid), status); /* Flush out any queued packets */ - while (!skb_queue_empty(&mcast->pkt_queue)) + spin_lock_irq(&priv->tx_lock); + while (!skb_queue_empty(&mcast->pkt_queue)) { + ++priv->stats.tx_dropped; dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); + } + spin_unlock_irq(&priv->tx_lock); /* Clear the busy flag so we try again */ clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); @@ -687,6 +703,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, if (!mcast) { ipoib_warn(priv, "unable to allocate memory for " "multicast structure\n"); + ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); goto out; } @@ -700,8 +717,10 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, if (!mcast->ah) { if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) skb_queue_tail(&mcast->pkt_queue, skb); - else + else { + ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); + } if (mcast->query) ipoib_dbg_mcast(priv, "no address vector, " diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 31207e664148..2d2d4ac3525a 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -357,9 +357,9 @@ static void srp_remove_work(void *target_ptr) target->state = SRP_TARGET_REMOVED; spin_unlock_irq(target->scsi_host->host_lock); - down(&target->srp_host->target_mutex); + mutex_lock(&target->srp_host->target_mutex); list_del(&target->list); - up(&target->srp_host->target_mutex); + mutex_unlock(&target->srp_host->target_mutex); scsi_remove_host(target->scsi_host); ib_destroy_cm_id(target->cm_id); @@ -1254,9 +1254,9 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) if (scsi_add_host(target->scsi_host, host->dev->dma_device)) return -ENODEV; - down(&host->target_mutex); + mutex_lock(&host->target_mutex); list_add_tail(&target->list, &host->target_list); - up(&host->target_mutex); + mutex_unlock(&host->target_mutex); target->state = SRP_TARGET_LIVE; @@ -1525,7 +1525,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port) return NULL; INIT_LIST_HEAD(&host->target_list); - init_MUTEX(&host->target_mutex); + mutex_init(&host->target_mutex); init_completion(&host->released); host->dev = device; host->port = port; @@ -1626,7 +1626,7 @@ static void srp_remove_one(struct ib_device *device) * Mark all target ports as removed, so we stop queueing * commands and don't try to reconnect. */ - down(&host->target_mutex); + mutex_lock(&host->target_mutex); list_for_each_entry_safe(target, tmp_target, &host->target_list, list) { spin_lock_irqsave(target->scsi_host->host_lock, flags); @@ -1634,7 +1634,7 @@ static void srp_remove_one(struct ib_device *device) target->state = SRP_TARGET_REMOVED; spin_unlock_irqrestore(target->scsi_host->host_lock, flags); } - up(&host->target_mutex); + mutex_unlock(&host->target_mutex); /* * Wait for any reconnection tasks that may have diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index b564f18caf78..4e7727df32f1 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -37,8 +37,7 @@ #include <linux/types.h> #include <linux/list.h> - -#include <asm/semaphore.h> +#include <linux/mutex.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> @@ -85,7 +84,7 @@ struct srp_host { struct ib_mr *mr; struct class_device class_dev; struct list_head target_list; - struct semaphore target_mutex; + struct mutex target_mutex; struct completion released; struct list_head list; }; diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 4571ea3a4b92..4612d13ea756 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -57,7 +57,7 @@ static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", " struct a3d { struct gameport *gameport; struct gameport *adc; - struct input_dev dev; + struct input_dev *dev; int axes[4]; int buttons; int mode; @@ -115,7 +115,7 @@ static int a3d_csum(char *data, int count) static void a3d_read(struct a3d *a3d, unsigned char *data) { - struct input_dev *dev = &a3d->dev; + struct input_dev *dev = a3d->dev; switch (a3d->mode) { @@ -265,14 +265,20 @@ static void a3d_close(struct input_dev *dev) static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) { struct a3d *a3d; + struct input_dev *input_dev; struct gameport *adc; unsigned char data[A3D_MAX_LENGTH]; int i; int err; - if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL))) - return -ENOMEM; + a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!a3d || !input_dev) { + err = -ENOMEM; + goto fail1; + } + a3d->dev = input_dev; a3d->gameport = gameport; gameport_set_drvdata(gameport, a3d); @@ -302,42 +308,48 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) sprintf(a3d->phys, "%s/input0", gameport->phys); + input_dev->name = a3d_names[a3d->mode]; + input_dev->phys = a3d->phys; + input_dev->id.bustype = BUS_GAMEPORT; + input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; + input_dev->id.product = a3d->mode; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &gameport->dev; + input_dev->private = a3d; + input_dev->open = a3d_open; + input_dev->close = a3d_close; + if (a3d->mode == A3D_MODE_PXL) { int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; a3d->length = 33; - init_input_dev(&a3d->dev); - - a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); - a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); - a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) - | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); - - a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) - | BIT(BTN_SIDE) | BIT(BTN_EXTRA); - - a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE); + input_dev->evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); + input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y); + input_dev->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) + | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); + input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) + | BIT(BTN_SIDE) | BIT(BTN_EXTRA); + input_dev->keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) + | BIT(BTN_PINKIE); a3d_read(a3d, data); for (i = 0; i < 4; i++) { if (i < 2) - input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8); + input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8); else - input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0); - input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0); + input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); + input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); } } else { a3d->length = 29; - init_input_dev(&a3d->dev); - - a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); - a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); - a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); + input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); + input_dev->relbit[0] |= BIT(REL_X) | BIT(REL_Y); + input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); a3d_read(a3d, data); @@ -358,24 +370,17 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) } } - a3d->dev.private = a3d; - a3d->dev.open = a3d_open; - a3d->dev.close = a3d_close; - - a3d->dev.name = a3d_names[a3d->mode]; - a3d->dev.phys = a3d->phys; - a3d->dev.id.bustype = BUS_GAMEPORT; - a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; - a3d->dev.id.product = a3d->mode; - a3d->dev.id.version = 0x0100; - - input_register_device(&a3d->dev); - printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys); + err = input_register_device(a3d->dev); + if (err) + goto fail3; return 0; -fail2: gameport_close(gameport); -fail1: gameport_set_drvdata(gameport, NULL); + fail3: if (a3d->adc) + gameport_unregister_port(a3d->adc); + fail2: gameport_close(gameport); + fail1: gameport_set_drvdata(gameport, NULL); + input_free_device(input_dev); kfree(a3d); return err; } @@ -384,11 +389,9 @@ static void a3d_disconnect(struct gameport *gameport) { struct a3d *a3d = gameport_get_drvdata(gameport); - input_unregister_device(&a3d->dev); - if (a3d->adc) { + input_unregister_device(a3d->dev); + if (a3d->adc) gameport_unregister_port(a3d->adc); - a3d->adc = NULL; - } gameport_close(gameport); gameport_set_drvdata(gameport, NULL); kfree(a3d); @@ -397,6 +400,7 @@ static void a3d_disconnect(struct gameport *gameport) static struct gameport_driver a3d_drv = { .driver = { .name = "adc", + .owner = THIS_MODULE, }, .description = DRIVER_DESC, .connect = a3d_connect, diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 499344c72756..dcffc34f30c3 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -275,68 +275,70 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char /* * db9_saturn_report() analyzes packet and reports. */ -static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads) +static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *devs[], int n, int max_pads) { + struct input_dev *dev; int tmp, i, j; tmp = (id == 0x41) ? 60 : 10; - for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) { + for (j = 0; j < tmp && n < max_pads; j += 10, n++) { + dev = devs[n]; switch (data[j]) { case 0x16: /* multi controller (analog 4 axis) */ - input_report_abs(dev + n, db9_abs[5], data[j + 6]); + input_report_abs(dev, db9_abs[5], data[j + 6]); case 0x15: /* mission stick (analog 3 axis) */ - input_report_abs(dev + n, db9_abs[3], data[j + 4]); - input_report_abs(dev + n, db9_abs[4], data[j + 5]); + input_report_abs(dev, db9_abs[3], data[j + 4]); + input_report_abs(dev, db9_abs[4], data[j + 5]); case 0x13: /* racing controller (analog 1 axis) */ - input_report_abs(dev + n, db9_abs[2], data[j + 3]); + input_report_abs(dev, db9_abs[2], data[j + 3]); case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */ case 0x02: /* digital pad (digital 2 axis + buttons) */ - input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); - input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); + input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); + input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); for (i = 0; i < 9; i++) - input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); + input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); break; case 0x19: /* mission stick x2 (analog 6 axis + buttons) */ - input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); - input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); + input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64)); + input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16)); for (i = 0; i < 9; i++) - input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); - input_report_abs(dev + n, db9_abs[2], data[j + 3]); - input_report_abs(dev + n, db9_abs[3], data[j + 4]); - input_report_abs(dev + n, db9_abs[4], data[j + 5]); + input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]); + input_report_abs(dev, db9_abs[2], data[j + 3]); + input_report_abs(dev, db9_abs[3], data[j + 4]); + input_report_abs(dev, db9_abs[4], data[j + 5]); /* - input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1)); - input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1)); + input_report_abs(dev, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1)); + input_report_abs(dev, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1)); */ - input_report_abs(dev + n, db9_abs[6], data[j + 7]); - input_report_abs(dev + n, db9_abs[7], data[j + 8]); - input_report_abs(dev + n, db9_abs[5], data[j + 9]); + input_report_abs(dev, db9_abs[6], data[j + 7]); + input_report_abs(dev, db9_abs[7], data[j + 8]); + input_report_abs(dev, db9_abs[5], data[j + 9]); break; case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */ - input_report_key(dev + n, BTN_A, data[j + 3] & 0x80); - input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f); + input_report_key(dev, BTN_A, data[j + 3] & 0x80); + input_report_abs(dev, db9_abs[2], data[j + 3] & 0x7f); break; case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */ - input_report_key(dev + n, BTN_START, data[j + 1] & 0x08); - input_report_key(dev + n, BTN_A, data[j + 1] & 0x04); - input_report_key(dev + n, BTN_C, data[j + 1] & 0x02); - input_report_key(dev + n, BTN_B, data[j + 1] & 0x01); - input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80); - input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */ + input_report_key(dev, BTN_START, data[j + 1] & 0x08); + input_report_key(dev, BTN_A, data[j + 1] & 0x04); + input_report_key(dev, BTN_C, data[j + 1] & 0x02); + input_report_key(dev, BTN_B, data[j + 1] & 0x01); + input_report_abs(dev, db9_abs[2], data[j + 2] ^ 0x80); + input_report_abs(dev, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */ break; case 0xff: default: /* no pad */ - input_report_abs(dev + n, db9_abs[0], 0); - input_report_abs(dev + n, db9_abs[1], 0); + input_report_abs(dev, db9_abs[0], 0); + input_report_abs(dev, db9_abs[1], 0); for (i = 0; i < 9; i++) - input_report_key(dev + n, db9_cd32_btn[i], 0); + input_report_key(dev, db9_cd32_btn[i], 0); break; } } return n; } -static int db9_saturn(int mode, struct parport *port, struct input_dev *dev) +static int db9_saturn(int mode, struct parport *port, struct input_dev *devs[]) { unsigned char id, data[60]; int type, n, max_pads; @@ -361,7 +363,7 @@ static int db9_saturn(int mode, struct parport *port, struct input_dev *dev) max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES); for (tmp = 0, i = 0; i < n; i++) { id = db9_saturn_read_packet(port, data, type + i, 1); - tmp = db9_saturn_report(id, data, dev, tmp, max_pads); + tmp = db9_saturn_report(id, data, devs, tmp, max_pads); } return 0; } @@ -489,7 +491,7 @@ static void db9_timer(unsigned long private) case DB9_SATURN_DPP: case DB9_SATURN_DPP_2: - db9_saturn(db9->mode, port, dev); + db9_saturn(db9->mode, port, db9->dev); break; case DB9_CD32_PAD: @@ -614,7 +616,7 @@ static struct db9 __init *db9_probe(int parport, int mode) if (!input_dev) { printk(KERN_ERR "db9.c: Not enough memory for input device\n"); err = -ENOMEM; - goto err_free_devs; + goto err_unreg_devs; } sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i); @@ -640,13 +642,17 @@ static struct db9 __init *db9_probe(int parport, int mode) input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0); } - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) + goto err_free_dev; } parport_put_port(pp); return db9; - err_free_devs: + err_free_dev: + input_free_device(db9->dev[i]); + err_unreg_devs: while (--i >= 0) input_unregister_device(db9->dev[i]); kfree(db9); @@ -658,7 +664,7 @@ static struct db9 __init *db9_probe(int parport, int mode) return ERR_PTR(err); } -static void __exit db9_remove(struct db9 *db9) +static void db9_remove(struct db9 *db9) { int i; @@ -696,7 +702,8 @@ static int __init db9_init(void) if (err) { while (--i >= 0) - db9_remove(db9_base[i]); + if (db9_base[i]) + db9_remove(db9_base[i]); return err; } diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 7df2d82f2c83..900587acdb47 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -159,6 +159,48 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) } +static void gc_n64_process_packet(struct gc *gc) +{ + unsigned char data[GC_N64_LENGTH]; + signed char axes[2]; + struct input_dev *dev; + int i, j, s; + + gc_n64_read_packet(gc, data); + + for (i = 0; i < GC_MAX_DEVICES; i++) { + + dev = gc->dev[i]; + if (!dev) + continue; + + s = gc_status_bit[i]; + + if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { + + axes[0] = axes[1] = 0; + + for (j = 0; j < 8; j++) { + if (data[23 - j] & s) + axes[0] |= 1 << j; + if (data[31 - j] & s) + axes[1] |= 1 << j; + } + + input_report_abs(dev, ABS_X, axes[0]); + input_report_abs(dev, ABS_Y, -axes[1]); + + input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); + input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); + + for (j = 0; j < 10; j++) + input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); + + input_sync(dev); + } + } +} + /* * NES/SNES support. */ @@ -198,6 +240,39 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) } } +static void gc_nes_process_packet(struct gc *gc) +{ + unsigned char data[GC_SNES_LENGTH]; + struct input_dev *dev; + int i, j, s; + + gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); + + for (i = 0; i < GC_MAX_DEVICES; i++) { + + dev = gc->dev[i]; + if (!dev) + continue; + + s = gc_status_bit[i]; + + if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { + input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); + input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); + } + + if (s & gc->pads[GC_NES]) + for (j = 0; j < 4; j++) + input_report_key(dev, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); + + if (s & gc->pads[GC_SNES]) + for (j = 0; j < 8; j++) + input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); + + input_sync(dev); + } +} + /* * Multisystem joystick support */ @@ -219,6 +294,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) } } +static void gc_multi_process_packet(struct gc *gc) +{ + unsigned char data[GC_MULTI2_LENGTH]; + struct input_dev *dev; + int i, s; + + gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data); + + for (i = 0; i < GC_MAX_DEVICES; i++) { + + dev = gc->dev[i]; + if (!dev) + continue; + + s = gc_status_bit[i]; + + if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { + input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3])); + input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1])); + input_report_key(dev, BTN_TRIGGER, s & data[4]); + } + + if (s & gc->pads[GC_MULTI2]) + input_report_key(dev, BTN_THUMB, s & data[5]); + + input_sync(dev); + } +} + /* * PSX support * @@ -263,10 +367,11 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; * the psx pad. */ -static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) +static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES]) { int i, j, cmd, read; - for (i = 0; i < 5; i++) + + for (i = 0; i < GC_MAX_DEVICES; i++) data[i] = 0; for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { @@ -274,7 +379,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); udelay(gc_psx_delay); read = parport_read_status(gc->pd->port) ^ 0x80; - for (j = 0; j < 5; j++) + for (j = 0; j < GC_MAX_DEVICES; j++) data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); udelay(gc_psx_delay); @@ -286,11 +391,12 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[5]) * device identifier code. */ -static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5]) +static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], + unsigned char id[GC_MAX_DEVICES]) { int i, j, max_len = 0; unsigned long flags; - unsigned char data2[5]; + unsigned char data2[GC_MAX_DEVICES]; parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */ udelay(gc_psx_delay); @@ -303,7 +409,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES gc_psx_command(gc, 0x42, id); /* Get device ids */ gc_psx_command(gc, 0, data2); /* Dump status */ - for (i =0; i < 5; i++) /* Find the longest pad */ + for (i =0; i < GC_MAX_DEVICES; i++) /* Find the longest pad */ if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len) && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES)) @@ -311,7 +417,7 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES for (i = 0; i < max_len; i++) { /* Read in all the data */ gc_psx_command(gc, 0, data2); - for (j = 0; j < 5; j++) + for (j = 0; j < GC_MAX_DEVICES; j++) data[j][i] = data2[j]; } @@ -319,185 +425,124 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); - for(i = 0; i < 5; i++) /* Set id's to the real value */ + for(i = 0; i < GC_MAX_DEVICES; i++) /* Set id's to the real value */ id[i] = GC_PSX_ID(id[i]); } -/* - * gc_timer() reads and analyzes console pads data. - */ +static void gc_psx_process_packet(struct gc *gc) +{ + unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; + unsigned char id[GC_MAX_DEVICES]; + struct input_dev *dev; + int i, j; -#define GC_MAX_LENGTH GC_N64_LENGTH + gc_psx_read_packet(gc, data, id); -static void gc_timer(unsigned long private) -{ - struct gc *gc = (void *) private; - unsigned char data[GC_MAX_LENGTH]; - unsigned char data_psx[5][GC_PSX_BYTES]; - int i, j, s; + for (i = 0; i < GC_MAX_DEVICES; i++) { -/* - * N64 pads - must be read first, any read confuses them for 200 us - */ + dev = gc->dev[i]; + if (!dev) + continue; - if (gc->pads[GC_N64]) { + switch (id[i]) { - gc_n64_read_packet(gc, data); + case GC_PSX_RUMBLE: - for (i = 0; i < 5; i++) { + input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04); + input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02); - s = gc_status_bit[i]; + case GC_PSX_NEGCON: + case GC_PSX_ANALOG: - if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { + if (gc->pads[GC_DDR] & gc_status_bit[i]) { + for(j = 0; j < 4; j++) + input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); + } else { + for (j = 0; j < 4; j++) + input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]); - signed char axes[2]; - axes[0] = axes[1] = 0; + input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); + input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); + } - for (j = 0; j < 8; j++) { - if (data[23 - j] & s) axes[0] |= 1 << j; - if (data[31 - j] & s) axes[1] |= 1 << j; + for (j = 0; j < 8; j++) + input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); + + input_report_key(dev, BTN_START, ~data[i][0] & 0x08); + input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); + + input_sync(dev); + + break; + + case GC_PSX_NORMAL: + if (gc->pads[GC_DDR] & gc_status_bit[i]) { + for(j = 0; j < 4; j++) + input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); + } else { + input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); + input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); + + /* for some reason if the extra axes are left unset they drift */ + /* for (j = 0; j < 4; j++) + input_report_abs(dev, gc_psx_abs[j + 2], 128); + * This needs to be debugged properly, + * maybe fuzz processing needs to be done in input_sync() + * --vojtech + */ } - input_report_abs(gc->dev[i], ABS_X, axes[0]); - input_report_abs(gc->dev[i], ABS_Y, -axes[1]); + for (j = 0; j < 8; j++) + input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); + + input_report_key(dev, BTN_START, ~data[i][0] & 0x08); + input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); - input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7])); - input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); + input_sync(dev); - for (j = 0; j < 10; j++) - input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]); + break; - input_sync(gc->dev[i]); - } + case 0: /* not a pad, ignore */ + break; } } +} /* - * NES and SNES pads + * gc_timer() initiates reads of console pads data. */ - if (gc->pads[GC_NES] || gc->pads[GC_SNES]) { - - gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); - - for (i = 0; i < 5; i++) { - - s = gc_status_bit[i]; +static void gc_timer(unsigned long private) +{ + struct gc *gc = (void *) private; - if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { - input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7])); - input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5])); - } +/* + * N64 pads - must be read first, any read confuses them for 200 us + */ - if (s & gc->pads[GC_NES]) - for (j = 0; j < 4; j++) - input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]); + if (gc->pads[GC_N64]) + gc_n64_process_packet(gc); - if (s & gc->pads[GC_SNES]) - for (j = 0; j < 8; j++) - input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]); +/* + * NES and SNES pads + */ - input_sync(gc->dev[i]); - } - } + if (gc->pads[GC_NES] || gc->pads[GC_SNES]) + gc_nes_process_packet(gc); /* * Multi and Multi2 joysticks */ - if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) { - - gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data); - - for (i = 0; i < 5; i++) { - - s = gc_status_bit[i]; - - if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { - input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3])); - input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1])); - input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]); - } - - if (s & gc->pads[GC_MULTI2]) - input_report_key(gc->dev[i], BTN_THUMB, s & data[5]); - - input_sync(gc->dev[i]); - } - } + if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) + gc_multi_process_packet(gc); /* * PSX controllers */ - if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) { - - gc_psx_read_packet(gc, data_psx, data); - - for (i = 0; i < 5; i++) { - switch (data[i]) { - - case GC_PSX_RUMBLE: - - input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04); - input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02); - - case GC_PSX_NEGCON: - case GC_PSX_ANALOG: - - if (gc->pads[GC_DDR] & gc_status_bit[i]) { - for(j = 0; j < 4; j++) - input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); - } else { - for (j = 0; j < 4; j++) - input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]); - - input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); - input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); - } - - for (j = 0; j < 8; j++) - input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); - - input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08); - input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01); - - input_sync(gc->dev[i]); - - break; - - case GC_PSX_NORMAL: - if (gc->pads[GC_DDR] & gc_status_bit[i]) { - for(j = 0; j < 4; j++) - input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); - } else { - input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); - input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); - - /* for some reason if the extra axes are left unset they drift */ - /* for (j = 0; j < 4; j++) - input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128); - * This needs to be debugged properly, - * maybe fuzz processing needs to be done in input_sync() - * --vojtech - */ - } - - for (j = 0; j < 8; j++) - input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); - - input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08); - input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01); - - input_sync(gc->dev[i]); - - break; - - case 0: /* not a pad, ignore */ - break; - } - } - } + if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) + gc_psx_process_packet(gc); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); } @@ -654,16 +699,18 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) gc->timer.data = (long) gc; gc->timer.function = gc_timer; - for (i = 0; i < n_pads; i++) { + for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { if (!pads[i]) continue; sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); err = gc_setup_pad(gc, i, pads[i]); if (err) - goto err_free_devs; + goto err_unreg_devs; - input_register_device(gc->dev[i]); + err = input_register_device(gc->dev[i]); + if (err) + goto err_free_dev; } if (!gc->pads[0]) { @@ -675,9 +722,12 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) parport_put_port(pp); return gc; - err_free_devs: + err_free_dev: + input_free_device(gc->dev[i]); + err_unreg_devs: while (--i >= 0) - input_unregister_device(gc->dev[i]); + if (gc->dev[i]) + input_unregister_device(gc->dev[i]); err_free_gc: kfree(gc); err_unreg_pardev: @@ -688,7 +738,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) return ERR_PTR(err); } -static void __exit gc_remove(struct gc *gc) +static void gc_remove(struct gc *gc) { int i; @@ -726,7 +776,8 @@ static int __init gc_init(void) if (err) { while (--i >= 0) - gc_remove(gc_base[i]); + if (gc_base[i]) + gc_remove(gc_base[i]); return err; } diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index a936e7aedb10..20cb98ac2d79 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -192,6 +192,9 @@ static void grip_poll(struct gameport *gameport) for (i = 0; i < 2; i++) { dev = grip->dev[i]; + if (!dev) + continue; + grip->reads++; switch (grip->mode[i]) { @@ -381,12 +384,15 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) if (t > 0) set_bit(t, input_dev->keybit); - input_register_device(grip->dev[i]); + err = input_register_device(grip->dev[i]); + if (err) + goto fail4; } return 0; - fail3: for (i = 0; i < 2; i++) + fail4: input_free_device(grip->dev[i]); + fail3: while (--i >= 0) if (grip->dev[i]) input_unregister_device(grip->dev[i]); fail2: gameport_close(gameport); @@ -411,6 +417,7 @@ static void grip_disconnect(struct gameport *gameport) static struct gameport_driver grip_drv = { .driver = { .name = "grip", + .owner = THIS_MODULE, }, .description = DRIVER_DESC, .connect = grip_connect, diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 64b9c31c47fc..b6bc04998047 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -345,7 +345,7 @@ int iforce_init_device(struct iforce *iforce) int i; input_dev = input_allocate_device(); - if (input_dev) + if (!input_dev) return -ENOMEM; init_waitqueue_head(&iforce->wait); diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 4a2629243e19..76cb1f88f4e8 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -167,9 +167,9 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, iforce->expect_packet = 0; iforce->ecmd = cmd; memcpy(iforce->edata, data, IFORCE_MAX_LENGTH); - wake_up(&iforce->wait); } #endif + wake_up(&iforce->wait); if (!iforce->type) { being_used--; @@ -264,7 +264,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) wait_event_interruptible_timeout(iforce->wait, iforce->ctrl->status != -EINPROGRESS, HZ); - if (iforce->ctrl->status != -EINPROGRESS) { + if (iforce->ctrl->status) { usb_unlink_urb(iforce->ctrl); return -1; } diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index bc2fce60f9f8..fe79d158456d 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -95,7 +95,6 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - wake_up(&iforce->wait); iforce_process_packet(iforce, (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs); diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 78dd163cd702..2b2ec1057dee 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -736,7 +736,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]); sprintf(sw->phys[i], "%s/input%d", gameport->phys, i); - input_dev = input_allocate_device(); + sw->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { err = -ENOMEM; goto fail3; @@ -771,12 +771,15 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k); - input_register_device(sw->dev[i]); + err = input_register_device(sw->dev[i]); + if (err) + goto fail4; } return 0; - fail3: while (--i >= 0) + fail4: input_free_device(sw->dev[i]); + fail3: while (--i >= 0) input_unregister_device(sw->dev[i]); fail2: gameport_close(gameport); fail1: gameport_set_drvdata(gameport, NULL); @@ -801,6 +804,7 @@ static void sw_disconnect(struct gameport *gameport) static struct gameport_driver sw_drv = { .driver = { .name = "sidewinder", + .owner = THIS_MODULE, }, .description = DRIVER_DESC, .connect = sw_connect, diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 60e2aac7d06e..bb23ed2a04a6 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -284,13 +284,13 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data) struct tmdc_port *port; struct input_dev *input_dev; int i, j, b = 0; + int err; tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL); input_dev = input_allocate_device(); if (!port || !input_dev) { - kfree(port); - input_free_device(input_dev); - return -ENOMEM; + err = -ENOMEM; + goto fail; } port->mode = data[TMDC_BYTE_ID]; @@ -347,9 +347,15 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data) b += port->btnc[i]; } - input_register_device(port->dev); + err = input_register_device(port->dev); + if (err) + goto fail; return 0; + + fail: input_free_device(input_dev); + kfree(port); + return err; } /* @@ -424,6 +430,7 @@ static void tmdc_disconnect(struct gameport *gameport) static struct gameport_driver tmdc_drv = { .driver = { .name = "tmdc", + .owner = THIS_MODULE, }, .description = DRIVER_DESC, .connect = tmdc_connect, diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 7e9764937d06..b154938e88a4 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -204,14 +204,14 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) if (n_buttons[i] > 6) { printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]); err = -EINVAL; - goto err_free_devs; + goto err_unreg_devs; } tgfx->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "turbografx.c: Not enough memory for input device\n"); err = -ENOMEM; - goto err_free_devs; + goto err_unreg_devs; } tgfx->sticks |= (1 << i); @@ -238,7 +238,9 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) for (j = 0; j < n_buttons[i]; j++) set_bit(tgfx_buttons[j], input_dev->keybit); - input_register_device(tgfx->dev[i]); + err = input_register_device(tgfx->dev[i]); + if (err) + goto err_free_dev; } if (!tgfx->sticks) { @@ -249,9 +251,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) return tgfx; - err_free_devs: + err_free_dev: + input_free_device(tgfx->dev[i]); + err_unreg_devs: while (--i >= 0) - input_unregister_device(tgfx->dev[i]); + if (tgfx->dev[i]) + input_unregister_device(tgfx->dev[i]); err_free_tgfx: kfree(tgfx); err_unreg_pardev: @@ -262,7 +267,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) return ERR_PTR(err); } -static void __exit tgfx_remove(struct tgfx *tgfx) +static void tgfx_remove(struct tgfx *tgfx) { int i; @@ -300,7 +305,8 @@ static int __init tgfx_init(void) if (err) { while (--i >= 0) - tgfx_remove(tgfx_base[i]); + if (tgfx_base[i]) + tgfx_remove(tgfx_base[i]); return err; } diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index cd3a1e742a30..7f8b0093c5bc 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -265,13 +265,13 @@ static struct serio_driver twidjoy_drv = { * The functions for inserting/removing us as a module. */ -int __init twidjoy_init(void) +static int __init twidjoy_init(void) { serio_register_driver(&twidjoy_drv); return 0; } -void __exit twidjoy_exit(void) +static void __exit twidjoy_exit(void) { serio_unregister_driver(&twidjoy_drv); } diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e08dbe08f46d..4bad588d0e5d 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -50,6 +50,18 @@ config INPUT_WISTRON_BTNS To compile this driver as a module, choose M here: the module will be called wistron_btns. +config INPUT_IXP4XX_BEEPER + tristate "IXP4XX Beeper support" + depends on ARCH_IXP4XX + help + If you say yes here, you can connect a beeper to the + ixp4xx gpio pins. This is used by the LinkSys NSLU2. + + If unsure, say Y. + + To compile this driver as a module, choose M here: the + module will be called ixp4xx-beeper. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index ce44cce01285..184c4129470d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o +obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c new file mode 100644 index 000000000000..d448bb5e4869 --- /dev/null +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -0,0 +1,183 @@ +/* + * Generic IXP4xx beeper driver + * + * Copyright (C) 2005 Tower Technologies + * + * based on nslu2-io.c + * Copyright (C) 2004 Karen Spearel + * + * Author: Alessandro Zummo <a.zummo@towertech.it> + * Maintainers: http://www.nslu2-linux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/input.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <asm/hardware.h> + +MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); +MODULE_DESCRIPTION("ixp4xx beeper driver"); +MODULE_LICENSE("GPL"); + +static DEFINE_SPINLOCK(beep_lock); + +static void ixp4xx_spkr_control(unsigned int pin, unsigned int count) +{ + unsigned long flags; + + spin_lock_irqsave(&beep_lock, flags); + + if (count) { + gpio_line_config(pin, IXP4XX_GPIO_OUT); + gpio_line_set(pin, IXP4XX_GPIO_LOW); + + *IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; + } else { + gpio_line_config(pin, IXP4XX_GPIO_IN); + gpio_line_set(pin, IXP4XX_GPIO_HIGH); + + *IXP4XX_OSRT2 = 0; + } + + spin_unlock_irqrestore(&beep_lock, flags); +} + +static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + unsigned int pin = (unsigned int) dev->private; + unsigned int count = 0; + + if (type != EV_SND) + return -1; + + switch (code) { + case SND_BELL: + if (value) + value = 1000; + case SND_TONE: + break; + default: + return -1; + } + + if (value > 20 && value < 32767) +#ifndef FREQ + count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1; +#else + count = (FREQ / (value * 4)) - 1; +#endif + + ixp4xx_spkr_control(pin, count); + + return 0; +} + +static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* clear interrupt */ + *IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND; + + /* flip the beeper output */ + *IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id); + + return IRQ_HANDLED; +} + +static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) +{ + struct input_dev *input_dev; + int err; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + input_dev->private = (void *) dev->id; + input_dev->name = "ixp4xx beeper", + input_dev->phys = "ixp4xx/gpio"; + input_dev->id.bustype = BUS_HOST; + input_dev->id.vendor = 0x001f; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_SND); + input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + input_dev->event = ixp4xx_spkr_event; + + err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt, + SA_INTERRUPT | SA_TIMER, "ixp4xx-beeper", (void *) dev->id); + if (err) + goto err_free_device; + + err = input_register_device(input_dev); + if (err) + goto err_free_irq; + + platform_set_drvdata(dev, input_dev); + + return 0; + + err_free_irq: + free_irq(IRQ_IXP4XX_TIMER2, dev); + err_free_device: + input_free_device(input_dev); + + return err; +} + +static int __devexit ixp4xx_spkr_remove(struct platform_device *dev) +{ + struct input_dev *input_dev = platform_get_drvdata(dev); + unsigned int pin = (unsigned int) input_dev->private; + + input_unregister_device(input_dev); + platform_set_drvdata(dev, NULL); + + /* turn the speaker off */ + disable_irq(IRQ_IXP4XX_TIMER2); + ixp4xx_spkr_control(pin, 0); + + free_irq(IRQ_IXP4XX_TIMER2, dev); + + return 0; +} + +static void ixp4xx_spkr_shutdown(struct platform_device *dev) +{ + struct input_dev *input_dev = platform_get_drvdata(dev); + unsigned int pin = (unsigned int) input_dev->private; + + /* turn off the speaker */ + disable_irq(IRQ_IXP4XX_TIMER2); + ixp4xx_spkr_control(pin, 0); +} + +static struct platform_driver ixp4xx_spkr_platform_driver = { + .driver = { + .name = "ixp4xx-beeper", + .owner = THIS_MODULE, + }, + .probe = ixp4xx_spkr_probe, + .remove = __devexit_p(ixp4xx_spkr_remove), + .shutdown = ixp4xx_spkr_shutdown, +}; + +static int __init ixp4xx_spkr_init(void) +{ + return platform_driver_register(&ixp4xx_spkr_platform_driver); +} + +static void __exit ixp4xx_spkr_exit(void) +{ + platform_driver_unregister(&ixp4xx_spkr_platform_driver); +} + +module_init(ixp4xx_spkr_init); +module_exit(ixp4xx_spkr_exit); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 7665fd9ce559..19b1b0121726 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -403,6 +403,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) set_bit(REL_WHEEL, psmouse->dev->relbit); psmouse->vendor = "Genius"; + psmouse->name = "Mouse"; psmouse->pktsize = 4; } diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 81fd7a97a93d..9abed18d2ecf 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -356,7 +356,7 @@ static void mousedev_free(struct mousedev *mousedev) kfree(mousedev); } -static int mixdev_release(void) +static void mixdev_release(void) { struct input_handle *handle; @@ -370,8 +370,6 @@ static int mixdev_release(void) mousedev_free(mousedev); } } - - return 0; } static int mousedev_release(struct inode * inode, struct file * file) @@ -384,9 +382,8 @@ static int mousedev_release(struct inode * inode, struct file * file) if (!--list->mousedev->open) { if (list->mousedev->minor == MOUSEDEV_MIX) - return mixdev_release(); - - if (!mousedev_mix.open) { + mixdev_release(); + else if (!mousedev_mix.open) { if (list->mousedev->exist) input_close_device(&list->mousedev->handle); else diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index dd8c6a9ffc76..b45a45ca7cc9 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -29,9 +29,6 @@ #ifdef CONFIG_ARCH_OMAP #include <asm/arch/gpio.h> #endif - -#else -#define set_irq_type(irq,type) do{}while(0) #endif @@ -509,14 +506,14 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->msg.complete = ads7846_rx; ts->msg.context = ts; - if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, - spi->dev.bus_id, ts)) { + if (request_irq(spi->irq, ads7846_irq, + SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, + spi->dev.bus_id, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); input_unregister_device(&ts->input); kfree(ts); return -EBUSY; } - set_irq_type(spi->irq, IRQT_FALLING); dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 4844d250a5eb..3226830eea08 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c @@ -154,7 +154,7 @@ static void mk712_close(struct input_dev *dev) spin_unlock_irqrestore(&mk712_lock, flags); } -int __init mk712_init(void) +static int __init mk712_init(void) { int err; diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 0ef560144be3..6dfc94122dd9 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -351,7 +351,7 @@ config HISAX_ENTERNOW_PCI config HISAX_AMD7930 bool "Am7930 (EXPERIMENTAL)" - depends on EXPERIMENTAL && SPARC + depends on EXPERIMENTAL && SPARC && BROKEN help This enables HiSax support for the AMD7930 chips on some SPARCs. This code is not finished yet. diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 1b85ce166af8..11fe537e2f6f 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -216,7 +216,7 @@ struct Layer1 { #define GROUP_TEI 127 #define TEI_SAPI 63 #define CTRL_SAPI 0 -#define PACKET_NOACK 250 +#define PACKET_NOACK 7 /* Layer2 Flags */ diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 3314a5a19854..94c9afb7017c 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -71,14 +71,14 @@ int sc_ioctl(int card, scs_ioctl *data) /* * Get the SRec from user space */ - if (copy_from_user(srec, data->dataptr, sizeof(srec))) { + if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) { kfree(rcvmsg); kfree(srec); return -EFAULT; } status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, - 0, sizeof(srec), srec, rcvmsg, SAR_TIMEOUT); + 0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT); kfree(rcvmsg); kfree(srec); diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 7d4a0ac28c06..12ad462737ba 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -187,6 +187,14 @@ config WINDFARM_PM91 This driver provides thermal control for the PowerMac9,1 which is the recent (SMU based) single CPU desktop G5 +config WINDFARM_PM112 + tristate "Support for thermal management on PowerMac11,2" + depends on WINDFARM && I2C && PMAC_SMU + select I2C_POWERMAC + help + This driver provides thermal control for the PowerMac11,2 + which are the recent dual and quad G5 machines using the + 970MP dual-core processor. config ANSLCD tristate "Support for ANS LCD display" diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index f4657aa81fb0..6081acdea404 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \ windfarm_smu_sensors.o \ windfarm_lm75_sensor.o windfarm_pid.o \ windfarm_cpufreq_clamp.o windfarm_pm91.o +obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \ + windfarm_smu_controls.o \ + windfarm_smu_sensors.o \ + windfarm_max6690_sensor.o \ + windfarm_lm75_sensor.o windfarm_pid.o diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index ed6d3174d660..69596f6438e9 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -140,10 +140,9 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, { struct macio_dev * macio_dev; struct of_device * of; - char *scratch, *compat; + char *scratch, *compat, *compat2; int i = 0; - int length = 0; - int cplen, seen = 0; + int length, cplen, cplen2, seen = 0; if (!dev) return -ENODEV; @@ -153,23 +152,22 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, return -ENODEV; of = &macio_dev->ofdev; - scratch = buffer; /* stuff we want to pass to /sbin/hotplug */ - envp[i++] = scratch; - length += scnprintf (scratch, buffer_size - length, "OF_NAME=%s", - of->node->name); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; + envp[i++] = scratch = buffer; + length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; scratch += length; envp[i++] = scratch; - length += scnprintf (scratch, buffer_size - length, "OF_TYPE=%s", - of->node->type); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; + length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; scratch += length; /* Since the compatible field can contain pretty much anything @@ -177,29 +175,55 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, * up using a number of environment variables instead. */ compat = (char *) get_property(of->node, "compatible", &cplen); + compat2 = compat; + cplen2= cplen; while (compat && cplen > 0) { - int l; envp[i++] = scratch; - length += scnprintf (scratch, buffer_size - length, + length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_%d=%s", seen, compat); - if ((buffer_size - length <= 0) || (i >= num_envp)) + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) return -ENOMEM; - length++; scratch += length; - l = strlen (compat) + 1; - compat += l; - cplen -= l; + length = strlen (compat) + 1; + compat += length; + cplen -= length; seen++; } envp[i++] = scratch; - length += scnprintf (scratch, buffer_size - length, - "OF_COMPATIBLE_N=%d", seen); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; + length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s", + of->node->name, of->node->type); + /* overwrite '\0' */ + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; scratch += length; + if (!compat2) { + compat2 = ""; + cplen2 = 1; + } + while (cplen2 > 0) { + length = snprintf (scratch, buffer_size, "C%s", compat2); + buffer_size -= length; + if (buffer_size <= 0) + return -ENOMEM; + scratch += length; + length = strlen (compat2) + 1; + compat2 += length; + cplen2 -= length; + } + envp[i] = NULL; return 0; diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h index 3f0cb0312ea3..7a2482cc26a7 100644 --- a/drivers/macintosh/windfarm.h +++ b/drivers/macintosh/windfarm.h @@ -14,6 +14,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/notifier.h> +#include <linux/device.h> /* Display a 16.16 fixed point value */ #define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) @@ -39,6 +40,7 @@ struct wf_control { char *name; int type; struct kref ref; + struct device_attribute attr; }; #define WF_CONTROL_TYPE_GENERIC 0 @@ -87,6 +89,7 @@ struct wf_sensor { struct wf_sensor_ops *ops; char *name; struct kref ref; + struct device_attribute attr; }; /* Same lifetime rules as controls */ diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c2a471ea6c0..bb8d5efe19bf 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -33,6 +33,7 @@ #include <linux/reboot.h> #include <linux/device.h> #include <linux/platform_device.h> +#include <linux/mutex.h> #include "windfarm.h" @@ -48,13 +49,17 @@ static LIST_HEAD(wf_controls); static LIST_HEAD(wf_sensors); -static DECLARE_MUTEX(wf_lock); +static DEFINE_MUTEX(wf_lock); static struct notifier_block *wf_client_list; static int wf_client_count; static unsigned int wf_overtemp; static unsigned int wf_overtemp_counter; struct task_struct *wf_thread; +static struct platform_device wf_platform_device = { + .name = "windfarm", +}; + /* * Utilities & tick thread */ @@ -156,26 +161,67 @@ static void wf_control_release(struct kref *kref) kfree(ct); } +static ssize_t wf_show_control(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wf_control *ctrl = container_of(attr, struct wf_control, attr); + s32 val = 0; + int err; + + err = ctrl->ops->get_value(ctrl, &val); + if (err < 0) + return err; + return sprintf(buf, "%d\n", val); +} + +/* This is really only for debugging... */ +static ssize_t wf_store_control(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wf_control *ctrl = container_of(attr, struct wf_control, attr); + int val; + int err; + char *endp; + + val = simple_strtoul(buf, &endp, 0); + while (endp < buf + count && (*endp == ' ' || *endp == '\n')) + ++endp; + if (endp - buf < count) + return -EINVAL; + err = ctrl->ops->set_value(ctrl, val); + if (err < 0) + return err; + return count; +} + int wf_register_control(struct wf_control *new_ct) { struct wf_control *ct; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(ct, &wf_controls, link) { if (!strcmp(ct->name, new_ct->name)) { printk(KERN_WARNING "windfarm: trying to register" " duplicate control %s\n", ct->name); - up(&wf_lock); + mutex_unlock(&wf_lock); return -EEXIST; } } kref_init(&new_ct->ref); list_add(&new_ct->link, &wf_controls); + new_ct->attr.attr.name = new_ct->name; + new_ct->attr.attr.owner = THIS_MODULE; + new_ct->attr.attr.mode = 0644; + new_ct->attr.show = wf_show_control; + new_ct->attr.store = wf_store_control; + device_create_file(&wf_platform_device.dev, &new_ct->attr); + DBG("wf: Registered control %s\n", new_ct->name); wf_notify(WF_EVENT_NEW_CONTROL, new_ct); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -183,9 +229,9 @@ EXPORT_SYMBOL_GPL(wf_register_control); void wf_unregister_control(struct wf_control *ct) { - down(&wf_lock); + mutex_lock(&wf_lock); list_del(&ct->link); - up(&wf_lock); + mutex_unlock(&wf_lock); DBG("wf: Unregistered control %s\n", ct->name); @@ -197,16 +243,16 @@ struct wf_control * wf_find_control(const char *name) { struct wf_control *ct; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(ct, &wf_controls, link) { if (!strcmp(ct->name, name)) { if (wf_get_control(ct)) ct = NULL; - up(&wf_lock); + mutex_unlock(&wf_lock); return ct; } } - up(&wf_lock); + mutex_unlock(&wf_lock); return NULL; } EXPORT_SYMBOL_GPL(wf_find_control); @@ -246,26 +292,46 @@ static void wf_sensor_release(struct kref *kref) kfree(sr); } +static ssize_t wf_show_sensor(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr); + s32 val = 0; + int err; + + err = sens->ops->get_value(sens, &val); + if (err < 0) + return err; + return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val)); +} + int wf_register_sensor(struct wf_sensor *new_sr) { struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(sr, &wf_sensors, link) { if (!strcmp(sr->name, new_sr->name)) { printk(KERN_WARNING "windfarm: trying to register" " duplicate sensor %s\n", sr->name); - up(&wf_lock); + mutex_unlock(&wf_lock); return -EEXIST; } } kref_init(&new_sr->ref); list_add(&new_sr->link, &wf_sensors); + new_sr->attr.attr.name = new_sr->name; + new_sr->attr.attr.owner = THIS_MODULE; + new_sr->attr.attr.mode = 0444; + new_sr->attr.show = wf_show_sensor; + new_sr->attr.store = NULL; + device_create_file(&wf_platform_device.dev, &new_sr->attr); + DBG("wf: Registered sensor %s\n", new_sr->name); wf_notify(WF_EVENT_NEW_SENSOR, new_sr); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -273,9 +339,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor); void wf_unregister_sensor(struct wf_sensor *sr) { - down(&wf_lock); + mutex_lock(&wf_lock); list_del(&sr->link); - up(&wf_lock); + mutex_unlock(&wf_lock); DBG("wf: Unregistered sensor %s\n", sr->name); @@ -287,16 +353,16 @@ struct wf_sensor * wf_find_sensor(const char *name) { struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); list_for_each_entry(sr, &wf_sensors, link) { if (!strcmp(sr->name, name)) { if (wf_get_sensor(sr)) sr = NULL; - up(&wf_lock); + mutex_unlock(&wf_lock); return sr; } } - up(&wf_lock); + mutex_unlock(&wf_lock); return NULL; } EXPORT_SYMBOL_GPL(wf_find_sensor); @@ -329,7 +395,7 @@ int wf_register_client(struct notifier_block *nb) struct wf_control *ct; struct wf_sensor *sr; - down(&wf_lock); + mutex_lock(&wf_lock); rc = notifier_chain_register(&wf_client_list, nb); if (rc != 0) goto bail; @@ -341,19 +407,19 @@ int wf_register_client(struct notifier_block *nb) if (wf_client_count == 1) wf_start_thread(); bail: - up(&wf_lock); + mutex_unlock(&wf_lock); return rc; } EXPORT_SYMBOL_GPL(wf_register_client); int wf_unregister_client(struct notifier_block *nb) { - down(&wf_lock); + mutex_lock(&wf_lock); notifier_chain_unregister(&wf_client_list, nb); wf_client_count++; if (wf_client_count == 0) wf_stop_thread(); - up(&wf_lock); + mutex_unlock(&wf_lock); return 0; } @@ -361,23 +427,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client); void wf_set_overtemp(void) { - down(&wf_lock); + mutex_lock(&wf_lock); wf_overtemp++; if (wf_overtemp == 1) { printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); wf_overtemp_counter = 0; wf_notify(WF_EVENT_OVERTEMP, NULL); } - up(&wf_lock); + mutex_unlock(&wf_lock); } EXPORT_SYMBOL_GPL(wf_set_overtemp); void wf_clear_overtemp(void) { - down(&wf_lock); + mutex_lock(&wf_lock); WARN_ON(wf_overtemp == 0); if (wf_overtemp == 0) { - up(&wf_lock); + mutex_unlock(&wf_lock); return; } wf_overtemp--; @@ -385,7 +451,7 @@ void wf_clear_overtemp(void) printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); wf_notify(WF_EVENT_NORMALTEMP, NULL); } - up(&wf_lock); + mutex_unlock(&wf_lock); } EXPORT_SYMBOL_GPL(wf_clear_overtemp); @@ -395,10 +461,6 @@ int wf_is_overtemp(void) } EXPORT_SYMBOL_GPL(wf_is_overtemp); -static struct platform_device wf_platform_device = { - .name = "windfarm", -}; - static int __init windfarm_core_init(void) { DBG("wf: core loaded\n"); diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c new file mode 100644 index 000000000000..5b9ad6ca7cba --- /dev/null +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -0,0 +1,169 @@ +/* + * Windfarm PowerMac thermal control. MAX6690 sensor. + * + * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> + * + * Use and redistribute under the terms of the GNU GPL v2. + */ +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <asm/prom.h> +#include <asm/pmac_low_i2c.h> + +#include "windfarm.h" + +#define VERSION "0.1" + +/* This currently only exports the external temperature sensor, + since that's all the control loops need. */ + +/* Some MAX6690 register numbers */ +#define MAX6690_INTERNAL_TEMP 0 +#define MAX6690_EXTERNAL_TEMP 1 + +struct wf_6690_sensor { + struct i2c_client i2c; + struct wf_sensor sens; +}; + +#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) +#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c) + +static int wf_max6690_attach(struct i2c_adapter *adapter); +static int wf_max6690_detach(struct i2c_client *client); + +static struct i2c_driver wf_max6690_driver = { + .driver = { + .name = "wf_max6690", + }, + .attach_adapter = wf_max6690_attach, + .detach_client = wf_max6690_detach, +}; + +static int wf_max6690_get(struct wf_sensor *sr, s32 *value) +{ + struct wf_6690_sensor *max = wf_to_6690(sr); + s32 data; + + if (max->i2c.adapter == NULL) + return -ENODEV; + + /* chip gets initialized by firmware */ + data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP); + if (data < 0) + return data; + *value = data << 16; + return 0; +} + +static void wf_max6690_release(struct wf_sensor *sr) +{ + struct wf_6690_sensor *max = wf_to_6690(sr); + + if (max->i2c.adapter) { + i2c_detach_client(&max->i2c); + max->i2c.adapter = NULL; + } + kfree(max); +} + +static struct wf_sensor_ops wf_max6690_ops = { + .get_value = wf_max6690_get, + .release = wf_max6690_release, + .owner = THIS_MODULE, +}; + +static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr) +{ + struct wf_6690_sensor *max; + char *name = "u4-temp"; + + max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); + if (max == NULL) { + printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " + "no memory\n", name); + return; + } + + max->sens.ops = &wf_max6690_ops; + max->sens.name = name; + max->i2c.addr = addr >> 1; + max->i2c.adapter = adapter; + max->i2c.driver = &wf_max6690_driver; + strncpy(max->i2c.name, name, I2C_NAME_SIZE-1); + + if (i2c_attach_client(&max->i2c)) { + printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); + goto fail; + } + + if (wf_register_sensor(&max->sens)) { + i2c_detach_client(&max->i2c); + goto fail; + } + + return; + + fail: + kfree(max); +} + +static int wf_max6690_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + const char *loc; + u32 *reg; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) { + if (!device_is_compatible(dev, "max6690")) + continue; + loc = get_property(dev, "hwsensor-location", NULL); + reg = (u32 *) get_property(dev, "reg", NULL); + if (!loc || !reg) + continue; + printk("found max6690, loc=%s reg=%x\n", loc, *reg); + if (strcmp(loc, "BACKSIDE")) + continue; + wf_max6690_create(adapter, *reg); + } + + return 0; +} + +static int wf_max6690_detach(struct i2c_client *client) +{ + struct wf_6690_sensor *max = i2c_to_6690(client); + + max->i2c.adapter = NULL; + wf_unregister_sensor(&max->sens); + + return 0; +} + +static int __init wf_max6690_sensor_init(void) +{ + return i2c_add_driver(&wf_max6690_driver); +} + +static void __exit wf_max6690_sensor_exit(void) +{ + i2c_del_driver(&wf_max6690_driver); +} + +module_init(wf_max6690_sensor_init); +module_exit(wf_max6690_sensor_exit); + +MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); +MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c index 2e803b368757..0842432e27ad 100644 --- a/drivers/macintosh/windfarm_pid.c +++ b/drivers/macintosh/windfarm_pid.c @@ -88,8 +88,8 @@ EXPORT_SYMBOL_GPL(wf_cpu_pid_init); s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) { - s64 error, integ, deriv, prop; - s32 target, sval, adj; + s64 integ, deriv, prop; + s32 error, target, sval, adj; int i, hlen = st->param.history_len; /* Calculate error term */ @@ -117,7 +117,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) integ += st->errors[(st->index + hlen - i) % hlen]; integ *= st->param.interval; integ *= st->param.gr; - sval = st->param.tmax - ((integ >> 20) & 0xffffffff); + sval = st->param.tmax - (s32)(integ >> 20); adj = min(st->param.ttarget, sval); DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj); @@ -129,7 +129,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) deriv *= st->param.gd; /* Calculate proportional term */ - prop = (new_temp - adj); + prop = st->last_delta = (new_temp - adj); prop *= st->param.gp; DBG("deriv: %lx, prop: %lx\n", deriv, prop); diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h index a364c2a2499c..bbccc22d42b8 100644 --- a/drivers/macintosh/windfarm_pid.h +++ b/drivers/macintosh/windfarm_pid.h @@ -72,6 +72,7 @@ struct wf_cpu_pid_state { int index; /* index of current power */ int tindex; /* index of current temp */ s32 target; /* current target value */ + s32 last_delta; /* last Tactual - Ttarget */ s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */ s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */ s32 temps[2]; /* temp. history buffer */ diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c new file mode 100644 index 000000000000..c2a4e689c784 --- /dev/null +++ b/drivers/macintosh/windfarm_pm112.c @@ -0,0 +1,698 @@ +/* + * Windfarm PowerMac thermal control. + * Control loops for machines with SMU and PPC970MP processors. + * + * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * + * Use and redistribute under the terms of the GNU GPL v2. + */ +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> +#include <asm/prom.h> +#include <asm/smu.h> + +#include "windfarm.h" +#include "windfarm_pid.h" + +#define VERSION "0.2" + +#define DEBUG +#undef LOTSA_DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +#ifdef LOTSA_DEBUG +#define DBG_LOTS(args...) printk(args) +#else +#define DBG_LOTS(args...) do { } while(0) +#endif + +/* define this to force CPU overtemp to 60 degree, useful for testing + * the overtemp code + */ +#undef HACKED_OVERTEMP + +/* We currently only handle 2 chips, 4 cores... */ +#define NR_CHIPS 2 +#define NR_CORES 4 +#define NR_CPU_FANS 3 * NR_CHIPS + +/* Controls and sensors */ +static struct wf_sensor *sens_cpu_temp[NR_CORES]; +static struct wf_sensor *sens_cpu_power[NR_CORES]; +static struct wf_sensor *hd_temp; +static struct wf_sensor *slots_power; +static struct wf_sensor *u4_temp; + +static struct wf_control *cpu_fans[NR_CPU_FANS]; +static char *cpu_fan_names[NR_CPU_FANS] = { + "cpu-rear-fan-0", + "cpu-rear-fan-1", + "cpu-front-fan-0", + "cpu-front-fan-1", + "cpu-pump-0", + "cpu-pump-1", +}; +static struct wf_control *cpufreq_clamp; + +/* Second pump isn't required (and isn't actually present) */ +#define CPU_FANS_REQD (NR_CPU_FANS - 2) +#define FIRST_PUMP 4 +#define LAST_PUMP 5 + +/* We keep a temperature history for average calculation of 180s */ +#define CPU_TEMP_HIST_SIZE 180 + +/* Scale factor for fan speed, *100 */ +static int cpu_fan_scale[NR_CPU_FANS] = { + 100, + 100, + 97, /* inlet fans run at 97% of exhaust fan */ + 97, + 100, /* updated later */ + 100, /* updated later */ +}; + +static struct wf_control *backside_fan; +static struct wf_control *slots_fan; +static struct wf_control *drive_bay_fan; + +/* PID loop state */ +static struct wf_cpu_pid_state cpu_pid[NR_CORES]; +static u32 cpu_thist[CPU_TEMP_HIST_SIZE]; +static int cpu_thist_pt; +static s64 cpu_thist_total; +static s32 cpu_all_tmax = 100 << 16; +static int cpu_last_target; +static struct wf_pid_state backside_pid; +static int backside_tick; +static struct wf_pid_state slots_pid; +static int slots_started; +static struct wf_pid_state drive_bay_pid; +static int drive_bay_tick; + +static int nr_cores; +static int have_all_controls; +static int have_all_sensors; +static int started; + +static int failure_state; +#define FAILURE_SENSOR 1 +#define FAILURE_FAN 2 +#define FAILURE_PERM 4 +#define FAILURE_LOW_OVERTEMP 8 +#define FAILURE_HIGH_OVERTEMP 16 + +/* Overtemp values */ +#define LOW_OVER_AVERAGE 0 +#define LOW_OVER_IMMEDIATE (10 << 16) +#define LOW_OVER_CLEAR ((-10) << 16) +#define HIGH_OVER_IMMEDIATE (14 << 16) +#define HIGH_OVER_AVERAGE (10 << 16) +#define HIGH_OVER_IMMEDIATE (14 << 16) + + +/* Implementation... */ +static int create_cpu_loop(int cpu) +{ + int chip = cpu / 2; + int core = cpu & 1; + struct smu_sdbp_header *hdr; + struct smu_sdbp_cpupiddata *piddata; + struct wf_cpu_pid_param pid; + struct wf_control *main_fan = cpu_fans[0]; + s32 tmax; + int fmin; + + /* Get PID params from the appropriate SAT */ + hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL); + if (hdr == NULL) { + printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n"); + return -EINVAL; + } + piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; + + /* Get FVT params to get Tmax; if not found, assume default */ + hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL); + if (hdr) { + struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1]; + tmax = fvt->maxtemp << 16; + } else + tmax = 95 << 16; /* default to 95 degrees C */ + + /* We keep a global tmax for overtemp calculations */ + if (tmax < cpu_all_tmax) + cpu_all_tmax = tmax; + + /* + * Darwin has a minimum fan speed of 1000 rpm for the 4-way and + * 515 for the 2-way. That appears to be overkill, so for now, + * impose a minimum of 750 or 515. + */ + fmin = (nr_cores > 2) ? 750 : 515; + + /* Initialize PID loop */ + pid.interval = 1; /* seconds */ + pid.history_len = piddata->history_len; + pid.gd = piddata->gd; + pid.gp = piddata->gp; + pid.gr = piddata->gr / piddata->history_len; + pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8); + pid.ttarget = tmax - (piddata->target_temp_delta << 16); + pid.tmax = tmax; + pid.min = main_fan->ops->get_min(main_fan); + pid.max = main_fan->ops->get_max(main_fan); + if (pid.min < fmin) + pid.min = fmin; + + wf_cpu_pid_init(&cpu_pid[cpu], &pid); + return 0; +} + +static void cpu_max_all_fans(void) +{ + int i; + + /* We max all CPU fans in case of a sensor error. We also do the + * cpufreq clamping now, even if it's supposedly done later by the + * generic code anyway, we do it earlier here to react faster + */ + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + for (i = 0; i < NR_CPU_FANS; ++i) + if (cpu_fans[i]) + wf_control_set_max(cpu_fans[i]); +} + +static int cpu_check_overtemp(s32 temp) +{ + int new_state = 0; + s32 t_avg, t_old; + + /* First check for immediate overtemps */ + if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) { + new_state |= FAILURE_LOW_OVERTEMP; + if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) + printk(KERN_ERR "windfarm: Overtemp due to immediate CPU" + " temperature !\n"); + } + if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) { + new_state |= FAILURE_HIGH_OVERTEMP; + if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) + printk(KERN_ERR "windfarm: Critical overtemp due to" + " immediate CPU temperature !\n"); + } + + /* We calculate a history of max temperatures and use that for the + * overtemp management + */ + t_old = cpu_thist[cpu_thist_pt]; + cpu_thist[cpu_thist_pt] = temp; + cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE; + cpu_thist_total -= t_old; + cpu_thist_total += temp; + t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE; + + DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n", + FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp)); + + /* Now check for average overtemps */ + if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) { + new_state |= FAILURE_LOW_OVERTEMP; + if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) + printk(KERN_ERR "windfarm: Overtemp due to average CPU" + " temperature !\n"); + } + if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) { + new_state |= FAILURE_HIGH_OVERTEMP; + if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) + printk(KERN_ERR "windfarm: Critical overtemp due to" + " average CPU temperature !\n"); + } + + /* Now handle overtemp conditions. We don't currently use the windfarm + * overtemp handling core as it's not fully suited to the needs of those + * new machine. This will be fixed later. + */ + if (new_state) { + /* High overtemp -> immediate shutdown */ + if (new_state & FAILURE_HIGH_OVERTEMP) + machine_power_off(); + if ((failure_state & new_state) != new_state) + cpu_max_all_fans(); + failure_state |= new_state; + } else if ((failure_state & FAILURE_LOW_OVERTEMP) && + (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) { + printk(KERN_ERR "windfarm: Overtemp condition cleared !\n"); + failure_state &= ~FAILURE_LOW_OVERTEMP; + } + + return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP); +} + +static void cpu_fans_tick(void) +{ + int err, cpu; + s32 greatest_delta = 0; + s32 temp, power, t_max = 0; + int i, t, target = 0; + struct wf_sensor *sr; + struct wf_control *ct; + struct wf_cpu_pid_state *sp; + + DBG_LOTS(KERN_DEBUG); + for (cpu = 0; cpu < nr_cores; ++cpu) { + /* Get CPU core temperature */ + sr = sens_cpu_temp[cpu]; + err = sr->ops->get_value(sr, &temp); + if (err) { + DBG("\n"); + printk(KERN_WARNING "windfarm: CPU %d temperature " + "sensor error %d\n", cpu, err); + failure_state |= FAILURE_SENSOR; + cpu_max_all_fans(); + return; + } + + /* Keep track of highest temp */ + t_max = max(t_max, temp); + + /* Get CPU power */ + sr = sens_cpu_power[cpu]; + err = sr->ops->get_value(sr, &power); + if (err) { + DBG("\n"); + printk(KERN_WARNING "windfarm: CPU %d power " + "sensor error %d\n", cpu, err); + failure_state |= FAILURE_SENSOR; + cpu_max_all_fans(); + return; + } + + /* Run PID */ + sp = &cpu_pid[cpu]; + t = wf_cpu_pid_run(sp, power, temp); + + if (cpu == 0 || sp->last_delta > greatest_delta) { + greatest_delta = sp->last_delta; + target = t; + } + DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ", + cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp)); + } + DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max)); + + /* Darwin limits decrease to 20 per iteration */ + if (target < (cpu_last_target - 20)) + target = cpu_last_target - 20; + cpu_last_target = target; + for (cpu = 0; cpu < nr_cores; ++cpu) + cpu_pid[cpu].target = target; + + /* Handle possible overtemps */ + if (cpu_check_overtemp(t_max)) + return; + + /* Set fans */ + for (i = 0; i < NR_CPU_FANS; ++i) { + ct = cpu_fans[i]; + if (ct == NULL) + continue; + err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100); + if (err) { + printk(KERN_WARNING "windfarm: fan %s reports " + "error %d\n", ct->name, err); + failure_state |= FAILURE_FAN; + break; + } + } +} + +/* Backside/U4 fan */ +static struct wf_pid_param backside_param = { + .interval = 5, + .history_len = 2, + .gd = 48 << 20, + .gp = 5 << 20, + .gr = 0, + .itarget = 64 << 16, + .additive = 1, +}; + +static void backside_fan_tick(void) +{ + s32 temp; + int speed; + int err; + + if (!backside_fan || !u4_temp) + return; + if (!backside_tick) { + /* first time; initialize things */ + backside_param.min = backside_fan->ops->get_min(backside_fan); + backside_param.max = backside_fan->ops->get_max(backside_fan); + wf_pid_init(&backside_pid, &backside_param); + backside_tick = 1; + } + if (--backside_tick > 0) + return; + backside_tick = backside_pid.param.interval; + + err = u4_temp->ops->get_value(u4_temp, &temp); + if (err) { + printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n", + err); + failure_state |= FAILURE_SENSOR; + wf_control_set_max(backside_fan); + return; + } + speed = wf_pid_run(&backside_pid, temp); + DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n", + FIX32TOPRINT(temp), speed); + + err = backside_fan->ops->set_value(backside_fan, speed); + if (err) { + printk(KERN_WARNING "windfarm: backside fan error %d\n", err); + failure_state |= FAILURE_FAN; + } +} + +/* Drive bay fan */ +static struct wf_pid_param drive_bay_prm = { + .interval = 5, + .history_len = 2, + .gd = 30 << 20, + .gp = 5 << 20, + .gr = 0, + .itarget = 40 << 16, + .additive = 1, +}; + +static void drive_bay_fan_tick(void) +{ + s32 temp; + int speed; + int err; + + if (!drive_bay_fan || !hd_temp) + return; + if (!drive_bay_tick) { + /* first time; initialize things */ + drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan); + drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan); + wf_pid_init(&drive_bay_pid, &drive_bay_prm); + drive_bay_tick = 1; + } + if (--drive_bay_tick > 0) + return; + drive_bay_tick = drive_bay_pid.param.interval; + + err = hd_temp->ops->get_value(hd_temp, &temp); + if (err) { + printk(KERN_WARNING "windfarm: drive bay temp sensor " + "error %d\n", err); + failure_state |= FAILURE_SENSOR; + wf_control_set_max(drive_bay_fan); + return; + } + speed = wf_pid_run(&drive_bay_pid, temp); + DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n", + FIX32TOPRINT(temp), speed); + + err = drive_bay_fan->ops->set_value(drive_bay_fan, speed); + if (err) { + printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err); + failure_state |= FAILURE_FAN; + } +} + +/* PCI slots area fan */ +/* This makes the fan speed proportional to the power consumed */ +static struct wf_pid_param slots_param = { + .interval = 1, + .history_len = 2, + .gd = 0, + .gp = 0, + .gr = 0x1277952, + .itarget = 0, + .min = 1560, + .max = 3510, +}; + +static void slots_fan_tick(void) +{ + s32 power; + int speed; + int err; + + if (!slots_fan || !slots_power) + return; + if (!slots_started) { + /* first time; initialize things */ + wf_pid_init(&slots_pid, &slots_param); + slots_started = 1; + } + + err = slots_power->ops->get_value(slots_power, &power); + if (err) { + printk(KERN_WARNING "windfarm: slots power sensor error %d\n", + err); + failure_state |= FAILURE_SENSOR; + wf_control_set_max(slots_fan); + return; + } + speed = wf_pid_run(&slots_pid, power); + DBG_LOTS("slots PID power=%d.%.3d speed=%d\n", + FIX32TOPRINT(power), speed); + + err = slots_fan->ops->set_value(slots_fan, speed); + if (err) { + printk(KERN_WARNING "windfarm: slots fan error %d\n", err); + failure_state |= FAILURE_FAN; + } +} + +static void set_fail_state(void) +{ + int i; + + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + for (i = 0; i < NR_CPU_FANS; ++i) + if (cpu_fans[i]) + wf_control_set_max(cpu_fans[i]); + if (backside_fan) + wf_control_set_max(backside_fan); + if (slots_fan) + wf_control_set_max(slots_fan); + if (drive_bay_fan) + wf_control_set_max(drive_bay_fan); +} + +static void pm112_tick(void) +{ + int i, last_failure; + + if (!started) { + started = 1; + for (i = 0; i < nr_cores; ++i) { + if (create_cpu_loop(i) < 0) { + failure_state = FAILURE_PERM; + set_fail_state(); + break; + } + } + DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax)); + +#ifdef HACKED_OVERTEMP + cpu_all_tmax = 60 << 16; +#endif + } + + /* Permanent failure, bail out */ + if (failure_state & FAILURE_PERM) + return; + /* Clear all failure bits except low overtemp which will be eventually + * cleared by the control loop itself + */ + last_failure = failure_state; + failure_state &= FAILURE_LOW_OVERTEMP; + cpu_fans_tick(); + backside_fan_tick(); + slots_fan_tick(); + drive_bay_fan_tick(); + + DBG_LOTS("last_failure: 0x%x, failure_state: %x\n", + last_failure, failure_state); + + /* Check for failures. Any failure causes cpufreq clamping */ + if (failure_state && last_failure == 0 && cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + if (failure_state == 0 && last_failure && cpufreq_clamp) + wf_control_set_min(cpufreq_clamp); + + /* That's it for now, we might want to deal with other failures + * differently in the future though + */ +} + +static void pm112_new_control(struct wf_control *ct) +{ + int i, max_exhaust; + + if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { + if (wf_get_control(ct) == 0) + cpufreq_clamp = ct; + } + + for (i = 0; i < NR_CPU_FANS; ++i) { + if (!strcmp(ct->name, cpu_fan_names[i])) { + if (cpu_fans[i] == NULL && wf_get_control(ct) == 0) + cpu_fans[i] = ct; + break; + } + } + if (i >= NR_CPU_FANS) { + /* not a CPU fan, try the others */ + if (!strcmp(ct->name, "backside-fan")) { + if (backside_fan == NULL && wf_get_control(ct) == 0) + backside_fan = ct; + } else if (!strcmp(ct->name, "slots-fan")) { + if (slots_fan == NULL && wf_get_control(ct) == 0) + slots_fan = ct; + } else if (!strcmp(ct->name, "drive-bay-fan")) { + if (drive_bay_fan == NULL && wf_get_control(ct) == 0) + drive_bay_fan = ct; + } + return; + } + + for (i = 0; i < CPU_FANS_REQD; ++i) + if (cpu_fans[i] == NULL) + return; + + /* work out pump scaling factors */ + max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]); + for (i = FIRST_PUMP; i <= LAST_PUMP; ++i) + if ((ct = cpu_fans[i]) != NULL) + cpu_fan_scale[i] = + ct->ops->get_max(ct) * 100 / max_exhaust; + + have_all_controls = 1; +} + +static void pm112_new_sensor(struct wf_sensor *sr) +{ + unsigned int i; + + if (have_all_sensors) + return; + if (!strncmp(sr->name, "cpu-temp-", 9)) { + i = sr->name[9] - '0'; + if (sr->name[10] == 0 && i < NR_CORES && + sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0) + sens_cpu_temp[i] = sr; + + } else if (!strncmp(sr->name, "cpu-power-", 10)) { + i = sr->name[10] - '0'; + if (sr->name[11] == 0 && i < NR_CORES && + sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0) + sens_cpu_power[i] = sr; + } else if (!strcmp(sr->name, "hd-temp")) { + if (hd_temp == NULL && wf_get_sensor(sr) == 0) + hd_temp = sr; + } else if (!strcmp(sr->name, "slots-power")) { + if (slots_power == NULL && wf_get_sensor(sr) == 0) + slots_power = sr; + } else if (!strcmp(sr->name, "u4-temp")) { + if (u4_temp == NULL && wf_get_sensor(sr) == 0) + u4_temp = sr; + } else + return; + + /* check if we have all the sensors we need */ + for (i = 0; i < nr_cores; ++i) + if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL) + return; + + have_all_sensors = 1; +} + +static int pm112_wf_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + switch (event) { + case WF_EVENT_NEW_SENSOR: + pm112_new_sensor(data); + break; + case WF_EVENT_NEW_CONTROL: + pm112_new_control(data); + break; + case WF_EVENT_TICK: + if (have_all_controls && have_all_sensors) + pm112_tick(); + } + return 0; +} + +static struct notifier_block pm112_events = { + .notifier_call = pm112_wf_notify, +}; + +static int wf_pm112_probe(struct device *dev) +{ + wf_register_client(&pm112_events); + return 0; +} + +static int wf_pm112_remove(struct device *dev) +{ + wf_unregister_client(&pm112_events); + /* should release all sensors and controls */ + return 0; +} + +static struct device_driver wf_pm112_driver = { + .name = "windfarm", + .bus = &platform_bus_type, + .probe = wf_pm112_probe, + .remove = wf_pm112_remove, +}; + +static int __init wf_pm112_init(void) +{ + struct device_node *cpu; + + if (!machine_is_compatible("PowerMac11,2")) + return -ENODEV; + + /* Count the number of CPU cores */ + nr_cores = 0; + for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; ) + ++nr_cores; + + printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n"); + driver_register(&wf_pm112_driver); + return 0; +} + +static void __exit wf_pm112_exit(void) +{ + driver_unregister(&wf_pm112_driver); +} + +module_init(wf_pm112_init); +module_exit(wf_pm112_exit); + +MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); +MODULE_DESCRIPTION("Thermal control for PowerMac11,2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index eb69a601e765..f1df6efcbe68 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c @@ -538,45 +538,6 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st) } } - -/* - * ****** Attributes ****** - * - */ - -#define BUILD_SHOW_FUNC_FIX(name, data) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - ssize_t r; \ - s32 val = 0; \ - data->ops->get_value(data, &val); \ - r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ - return r; \ -} \ -static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); - - -#define BUILD_SHOW_FUNC_INT(name, data) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - s32 val = 0; \ - data->ops->get_value(data, &val); \ - return sprintf(buf, "%d", val); \ -} \ -static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); - -BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); -BUILD_SHOW_FUNC_INT(sys_fan, fan_system); -BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); - -BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); -BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); -BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); - /* * ****** Setup / Init / Misc ... ****** * @@ -654,17 +615,13 @@ static void wf_smu_new_control(struct wf_control *ct) return; if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_cpu_main = ct; - device_create_file(wf_smu_dev, &dev_attr_cpu_fan); - } } if (fan_system == NULL && !strcmp(ct->name, "system-fan")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_system = ct; - device_create_file(wf_smu_dev, &dev_attr_sys_fan); - } } if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { @@ -683,10 +640,8 @@ static void wf_smu_new_control(struct wf_control *ct) } if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_hd = ct; - device_create_file(wf_smu_dev, &dev_attr_hd_fan); - } } if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp) @@ -699,24 +654,18 @@ static void wf_smu_new_sensor(struct wf_sensor *sr) return; if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_cpu_power = sr; - device_create_file(wf_smu_dev, &dev_attr_cpu_power); - } } if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_cpu_temp = sr; - device_create_file(wf_smu_dev, &dev_attr_cpu_temp); - } } if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_hd_temp = sr; - device_create_file(wf_smu_dev, &dev_attr_hd_temp); - } } if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp) @@ -794,32 +743,20 @@ static int wf_smu_remove(struct device *ddev) * with that except by adding locks all over... I'll do that * eventually but heh, who ever rmmod this module anyway ? */ - if (sensor_cpu_power) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_power); + if (sensor_cpu_power) wf_put_sensor(sensor_cpu_power); - } - if (sensor_cpu_temp) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); + if (sensor_cpu_temp) wf_put_sensor(sensor_cpu_temp); - } - if (sensor_hd_temp) { - device_remove_file(wf_smu_dev, &dev_attr_hd_temp); + if (sensor_hd_temp) wf_put_sensor(sensor_hd_temp); - } /* Release all controls */ - if (fan_cpu_main) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); + if (fan_cpu_main) wf_put_control(fan_cpu_main); - } - if (fan_hd) { - device_remove_file(wf_smu_dev, &dev_attr_hd_fan); + if (fan_hd) wf_put_control(fan_hd); - } - if (fan_system) { - device_remove_file(wf_smu_dev, &dev_attr_sys_fan); + if (fan_system) wf_put_control(fan_system); - } if (cpufreq_clamp) wf_put_control(cpufreq_clamp); diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 43243cf7410b..0d6372e96d32 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c @@ -458,45 +458,6 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st) /* - * ****** Attributes ****** - * - */ - -#define BUILD_SHOW_FUNC_FIX(name, data) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - ssize_t r; \ - s32 val = 0; \ - data->ops->get_value(data, &val); \ - r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ - return r; \ -} \ -static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); - - -#define BUILD_SHOW_FUNC_INT(name, data) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - s32 val = 0; \ - data->ops->get_value(data, &val); \ - return sprintf(buf, "%d", val); \ -} \ -static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); - -BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); -BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); -BUILD_SHOW_FUNC_INT(slots_fan, fan_slots); - -BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); -BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); -BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); -BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power); - -/* * ****** Setup / Init / Misc ... ****** * */ @@ -581,10 +542,8 @@ static void wf_smu_new_control(struct wf_control *ct) return; if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_cpu_main = ct; - device_create_file(wf_smu_dev, &dev_attr_cpu_fan); - } } if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) { @@ -603,17 +562,13 @@ static void wf_smu_new_control(struct wf_control *ct) } if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_hd = ct; - device_create_file(wf_smu_dev, &dev_attr_hd_fan); - } } if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) { - if (wf_get_control(ct) == 0) { + if (wf_get_control(ct) == 0) fan_slots = ct; - device_create_file(wf_smu_dev, &dev_attr_slots_fan); - } } if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd && @@ -627,31 +582,23 @@ static void wf_smu_new_sensor(struct wf_sensor *sr) return; if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_cpu_power = sr; - device_create_file(wf_smu_dev, &dev_attr_cpu_power); - } } if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_cpu_temp = sr; - device_create_file(wf_smu_dev, &dev_attr_cpu_temp); - } } if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_hd_temp = sr; - device_create_file(wf_smu_dev, &dev_attr_hd_temp); - } } if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) { - if (wf_get_sensor(sr) == 0) { + if (wf_get_sensor(sr) == 0) sensor_slots_power = sr; - device_create_file(wf_smu_dev, &dev_attr_slots_power); - } } if (sensor_cpu_power && sensor_cpu_temp && @@ -720,40 +667,26 @@ static int wf_smu_remove(struct device *ddev) * with that except by adding locks all over... I'll do that * eventually but heh, who ever rmmod this module anyway ? */ - if (sensor_cpu_power) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_power); + if (sensor_cpu_power) wf_put_sensor(sensor_cpu_power); - } - if (sensor_cpu_temp) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); + if (sensor_cpu_temp) wf_put_sensor(sensor_cpu_temp); - } - if (sensor_hd_temp) { - device_remove_file(wf_smu_dev, &dev_attr_hd_temp); + if (sensor_hd_temp) wf_put_sensor(sensor_hd_temp); - } - if (sensor_slots_power) { - device_remove_file(wf_smu_dev, &dev_attr_slots_power); + if (sensor_slots_power) wf_put_sensor(sensor_slots_power); - } /* Release all controls */ - if (fan_cpu_main) { - device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); + if (fan_cpu_main) wf_put_control(fan_cpu_main); - } if (fan_cpu_second) wf_put_control(fan_cpu_second); if (fan_cpu_third) wf_put_control(fan_cpu_third); - if (fan_hd) { - device_remove_file(wf_smu_dev, &dev_attr_hd_fan); + if (fan_hd) wf_put_control(fan_hd); - } - if (fan_slots) { - device_remove_file(wf_smu_dev, &dev_attr_slots_fan); + if (fan_slots) wf_put_control(fan_slots); - } if (cpufreq_clamp) wf_put_control(cpufreq_clamp); diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 4d811600bdab..a9e88edc0c72 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -24,7 +24,7 @@ #include "windfarm.h" -#define VERSION "0.3" +#define VERSION "0.4" #undef DEBUG @@ -34,6 +34,8 @@ #define DBG(args...) do { } while(0) #endif +static int smu_supports_new_fans_ops = 1; + /* * SMU fans control object */ @@ -59,23 +61,49 @@ static int smu_set_fan(int pwm, u8 id, u16 value) /* Fill SMU command structure */ cmd.cmd = SMU_CMD_FAN_COMMAND; - cmd.data_len = 14; + + /* The SMU has an "old" and a "new" way of setting the fan speed + * Unfortunately, I found no reliable way to know which one works + * on a given machine model. After some investigations it appears + * that MacOS X just tries the new one, and if it fails fallbacks + * to the old ones ... Ugh. + */ + retry: + if (smu_supports_new_fans_ops) { + buffer[0] = 0x30; + buffer[1] = id; + *((u16 *)(&buffer[2])) = value; + cmd.data_len = 4; + } else { + if (id > 7) + return -EINVAL; + /* Fill argument buffer */ + memset(buffer, 0, 16); + buffer[0] = pwm ? 0x10 : 0x00; + buffer[1] = 0x01 << id; + *((u16 *)&buffer[2 + id * 2]) = value; + cmd.data_len = 14; + } + cmd.reply_len = 16; cmd.data_buf = cmd.reply_buf = buffer; cmd.status = 0; cmd.done = smu_done_complete; cmd.misc = ∁ - /* Fill argument buffer */ - memset(buffer, 0, 16); - buffer[0] = pwm ? 0x10 : 0x00; - buffer[1] = 0x01 << id; - *((u16 *)&buffer[2 + id * 2]) = value; - rc = smu_queue_cmd(&cmd); if (rc) return rc; wait_for_completion(&comp); + + /* Handle fallback (see coment above) */ + if (cmd.status != 0 && smu_supports_new_fans_ops) { + printk(KERN_WARNING "windfarm: SMU failed new fan command " + "falling back to old method\n"); + smu_supports_new_fans_ops = 0; + goto retry; + } + return cmd.status; } @@ -158,19 +186,29 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, /* Names used on desktop models */ if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || - !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan")) + !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") || + !strcmp(l, "CPU A EXHAUST")) fct->ctrl.name = "cpu-rear-fan-0"; - else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1")) + else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") || + !strcmp(l, "CPU B EXHAUST")) fct->ctrl.name = "cpu-rear-fan-1"; else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || - !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan")) + !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") || + !strcmp(l, "CPU A INTAKE")) fct->ctrl.name = "cpu-front-fan-0"; - else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1")) + else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") || + !strcmp(l, "CPU B INTAKE")) fct->ctrl.name = "cpu-front-fan-1"; - else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan")) + else if (!strcmp(l, "CPU A PUMP")) + fct->ctrl.name = "cpu-pump-0"; + else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || + !strcmp(l, "EXPANSION SLOTS INTAKE")) fct->ctrl.name = "slots-fan"; - else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay")) + else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") || + !strcmp(l, "DRIVE BAY A INTAKE")) fct->ctrl.name = "drive-bay-fan"; + else if (!strcmp(l, "BACKSIDE")) + fct->ctrl.name = "backside-fan"; /* Names used on iMac models */ if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) @@ -223,7 +261,8 @@ static int __init smu_controls_init(void) /* Look for RPM fans */ for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) - if (!strcmp(fans->name, "rpm-fans")) + if (!strcmp(fans->name, "rpm-fans") || + device_is_compatible(fans, "smu-rpm-fans")) break; for (fan = NULL; fans && (fan = of_get_next_child(fans, fan)) != NULL;) { diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c new file mode 100644 index 000000000000..3a32c59494f2 --- /dev/null +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -0,0 +1,418 @@ +/* + * Windfarm PowerMac thermal control. SMU "satellite" controller sensors. + * + * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> + * + * Released under the terms of the GNU GPL v2. + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/wait.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <asm/semaphore.h> +#include <asm/prom.h> +#include <asm/smu.h> +#include <asm/pmac_low_i2c.h> + +#include "windfarm.h" + +#define VERSION "0.2" + +#define DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +/* If the cache is older than 800ms we'll refetch it */ +#define MAX_AGE msecs_to_jiffies(800) + +struct wf_sat { + int nr; + atomic_t refcnt; + struct semaphore mutex; + unsigned long last_read; /* jiffies when cache last updated */ + u8 cache[16]; + struct i2c_client i2c; + struct device_node *node; +}; + +static struct wf_sat *sats[2]; + +struct wf_sat_sensor { + int index; + int index2; /* used for power sensors */ + int shift; + struct wf_sat *sat; + struct wf_sensor sens; +}; + +#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) +#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) + +static int wf_sat_attach(struct i2c_adapter *adapter); +static int wf_sat_detach(struct i2c_client *client); + +static struct i2c_driver wf_sat_driver = { + .driver = { + .name = "wf_smu_sat", + }, + .attach_adapter = wf_sat_attach, + .detach_client = wf_sat_detach, +}; + +/* + * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested + * length down to the low-level driver, so we use this, which + * works well enough with the SMU i2c driver code... + */ +static int sat_read_block(struct i2c_client *client, u8 command, + u8 *values, int len) +{ + union i2c_smbus_data data; + int err; + + data.block[0] = len; + err = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA, + &data); + if (!err) + memcpy(values, data.block, len); + return err; +} + +struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, + unsigned int *size) +{ + struct wf_sat *sat; + int err; + unsigned int i, len; + u8 *buf; + u8 data[4]; + + /* TODO: Add the resulting partition to the device-tree */ + + if (sat_id > 1 || (sat = sats[sat_id]) == NULL) + return NULL; + + err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); + if (err) { + printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); + return NULL; + } + + len = i2c_smbus_read_word_data(&sat->i2c, 9); + if (len < 0) { + printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); + return NULL; + } + if (len == 0) { + printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); + return NULL; + } + + len = le16_to_cpu(len); + len = (len + 3) & ~3; + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) + return NULL; + + for (i = 0; i < len; i += 4) { + err = sat_read_block(&sat->i2c, 0xa, data, 4); + if (err) { + printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", + err); + goto fail; + } + buf[i] = data[1]; + buf[i+1] = data[0]; + buf[i+2] = data[3]; + buf[i+3] = data[2]; + } +#ifdef DEBUG + DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id); + for (i = 0; i < len; ++i) + DBG(" %x", buf[i]); + DBG("\n"); +#endif + + if (size) + *size = len; + return (struct smu_sdbp_header *) buf; + + fail: + kfree(buf); + return NULL; +} + +/* refresh the cache */ +static int wf_sat_read_cache(struct wf_sat *sat) +{ + int err; + + err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16); + if (err) + return err; + sat->last_read = jiffies; +#ifdef LOTSA_DEBUG + { + int i; + DBG(KERN_DEBUG "wf_sat_get: data is"); + for (i = 0; i < 16; ++i) + DBG(" %.2x", sat->cache[i]); + DBG("\n"); + } +#endif + return 0; +} + +static int wf_sat_get(struct wf_sensor *sr, s32 *value) +{ + struct wf_sat_sensor *sens = wf_to_sat(sr); + struct wf_sat *sat = sens->sat; + int i, err; + s32 val; + + if (sat->i2c.adapter == NULL) + return -ENODEV; + + down(&sat->mutex); + if (time_after(jiffies, (sat->last_read + MAX_AGE))) { + err = wf_sat_read_cache(sat); + if (err) + goto fail; + } + + i = sens->index * 2; + val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift; + if (sens->index2 >= 0) { + i = sens->index2 * 2; + /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */ + val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4; + } + + *value = val; + err = 0; + + fail: + up(&sat->mutex); + return err; +} + +static void wf_sat_release(struct wf_sensor *sr) +{ + struct wf_sat_sensor *sens = wf_to_sat(sr); + struct wf_sat *sat = sens->sat; + + if (atomic_dec_and_test(&sat->refcnt)) { + if (sat->i2c.adapter) { + i2c_detach_client(&sat->i2c); + sat->i2c.adapter = NULL; + } + if (sat->nr >= 0) + sats[sat->nr] = NULL; + kfree(sat); + } + kfree(sens); +} + +static struct wf_sensor_ops wf_sat_ops = { + .get_value = wf_sat_get, + .release = wf_sat_release, + .owner = THIS_MODULE, +}; + +static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) +{ + struct wf_sat *sat; + struct wf_sat_sensor *sens; + u32 *reg; + char *loc, *type; + u8 addr, chip, core; + struct device_node *child; + int shift, cpu, index; + char *name; + int vsens[2], isens[2]; + + reg = (u32 *) get_property(dev, "reg", NULL); + if (reg == NULL) + return; + addr = *reg; + DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); + + sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); + if (sat == NULL) + return; + sat->nr = -1; + sat->node = of_node_get(dev); + atomic_set(&sat->refcnt, 0); + init_MUTEX(&sat->mutex); + sat->i2c.addr = (addr >> 1) & 0x7f; + sat->i2c.adapter = adapter; + sat->i2c.driver = &wf_sat_driver; + strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); + + if (i2c_attach_client(&sat->i2c)) { + printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); + goto fail; + } + + vsens[0] = vsens[1] = -1; + isens[0] = isens[1] = -1; + child = NULL; + while ((child = of_get_next_child(dev, child)) != NULL) { + reg = (u32 *) get_property(child, "reg", NULL); + type = get_property(child, "device_type", NULL); + loc = get_property(child, "location", NULL); + if (reg == NULL || loc == NULL) + continue; + + /* the cooked sensors are between 0x30 and 0x37 */ + if (*reg < 0x30 || *reg > 0x37) + continue; + index = *reg - 0x30; + + /* expect location to be CPU [AB][01] ... */ + if (strncmp(loc, "CPU ", 4) != 0) + continue; + chip = loc[4] - 'A'; + core = loc[5] - '0'; + if (chip > 1 || core > 1) { + printk(KERN_ERR "wf_sat_create: don't understand " + "location %s for %s\n", loc, child->full_name); + continue; + } + cpu = 2 * chip + core; + if (sat->nr < 0) + sat->nr = chip; + else if (sat->nr != chip) { + printk(KERN_ERR "wf_sat_create: can't cope with " + "multiple CPU chips on one SAT (%s)\n", loc); + continue; + } + + if (strcmp(type, "voltage-sensor") == 0) { + name = "cpu-voltage"; + shift = 4; + vsens[core] = index; + } else if (strcmp(type, "current-sensor") == 0) { + name = "cpu-current"; + shift = 8; + isens[core] = index; + } else if (strcmp(type, "temp-sensor") == 0) { + name = "cpu-temp"; + shift = 10; + } else + continue; /* hmmm shouldn't happen */ + + /* the +16 is enough for "cpu-voltage-n" */ + sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); + if (sens == NULL) { + printk(KERN_ERR "wf_sat_create: couldn't create " + "%s sensor %d (no memory)\n", name, cpu); + continue; + } + sens->index = index; + sens->index2 = -1; + sens->shift = shift; + sens->sat = sat; + atomic_inc(&sat->refcnt); + sens->sens.ops = &wf_sat_ops; + sens->sens.name = (char *) (sens + 1); + snprintf(sens->sens.name, 16, "%s-%d", name, cpu); + + if (wf_register_sensor(&sens->sens)) { + atomic_dec(&sat->refcnt); + kfree(sens); + } + } + + /* make the power sensors */ + for (core = 0; core < 2; ++core) { + if (vsens[core] < 0 || isens[core] < 0) + continue; + cpu = 2 * sat->nr + core; + sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); + if (sens == NULL) { + printk(KERN_ERR "wf_sat_create: couldn't create power " + "sensor %d (no memory)\n", cpu); + continue; + } + sens->index = vsens[core]; + sens->index2 = isens[core]; + sens->shift = 0; + sens->sat = sat; + atomic_inc(&sat->refcnt); + sens->sens.ops = &wf_sat_ops; + sens->sens.name = (char *) (sens + 1); + snprintf(sens->sens.name, 16, "cpu-power-%d", cpu); + + if (wf_register_sensor(&sens->sens)) { + atomic_dec(&sat->refcnt); + kfree(sens); + } + } + + if (sat->nr >= 0) + sats[sat->nr] = sat; + + return; + + fail: + kfree(sat); +} + +static int wf_sat_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) + if (device_is_compatible(dev, "smu-sat")) + wf_sat_create(adapter, dev); + return 0; +} + +static int wf_sat_detach(struct i2c_client *client) +{ + struct wf_sat *sat = i2c_to_sat(client); + + /* XXX TODO */ + + sat->i2c.adapter = NULL; + return 0; +} + +static int __init sat_sensors_init(void) +{ + int err; + + err = i2c_add_driver(&wf_sat_driver); + if (err < 0) + return err; + return 0; +} + +static void __exit sat_sensors_exit(void) +{ + i2c_del_driver(&wf_sat_driver); +} + +module_init(sat_sensors_init); +/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */ + +MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); +MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index 1a00d9c75a23..bed25dcf8a1e 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -220,14 +220,29 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) !strcmp(l, "CPU T-Diode")) { ads->sens.ops = &smu_cputemp_ops; ads->sens.name = "cpu-temp"; + if (cpudiode == NULL) { + DBG("wf: cpudiode partition (%02x) not found\n", + SMU_SDB_CPUDIODE_ID); + goto fail; + } } else if (!strcmp(c, "current-sensor") && !strcmp(l, "CPU Current")) { ads->sens.ops = &smu_cpuamp_ops; ads->sens.name = "cpu-current"; + if (cpuvcp == NULL) { + DBG("wf: cpuvcp partition (%02x) not found\n", + SMU_SDB_CPUVCP_ID); + goto fail; + } } else if (!strcmp(c, "voltage-sensor") && !strcmp(l, "CPU Voltage")) { ads->sens.ops = &smu_cpuvolt_ops; ads->sens.name = "cpu-voltage"; + if (cpuvcp == NULL) { + DBG("wf: cpuvcp partition (%02x) not found\n", + SMU_SDB_CPUVCP_ID); + goto fail; + } } else if (!strcmp(c, "power-sensor") && !strcmp(l, "Slots Power")) { ads->sens.ops = &smu_slotspow_ops; @@ -365,29 +380,22 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) return NULL; } -static int smu_fetch_param_partitions(void) +static void smu_fetch_param_partitions(void) { struct smu_sdbp_header *hdr; /* Get CPU voltage/current/power calibration data */ hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); - if (hdr == NULL) { - DBG("wf: cpuvcp partition (%02x) not found\n", - SMU_SDB_CPUVCP_ID); - return -ENODEV; + if (hdr != NULL) { + cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1]; + /* Keep version around */ + cpuvcp_version = hdr->version; } - cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1]; - /* Keep version around */ - cpuvcp_version = hdr->version; /* Get CPU diode calibration data */ hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL); - if (hdr == NULL) { - DBG("wf: cpudiode partition (%02x) not found\n", - SMU_SDB_CPUDIODE_ID); - return -ENODEV; - } - cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1]; + if (hdr != NULL) + cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1]; /* Get slots power calibration data if any */ hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL); @@ -398,23 +406,18 @@ static int smu_fetch_param_partitions(void) hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL); if (hdr != NULL) debugswitches = (u8 *)&hdr[1]; - - return 0; } static int __init smu_sensors_init(void) { struct device_node *smu, *sensors, *s; struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL; - int rc; if (!smu_present()) return -ENODEV; /* Get parameters partitions */ - rc = smu_fetch_param_partitions(); - if (rc) - return rc; + smu_fetch_param_partitions(); smu = of_find_node_by_type(NULL, "smu"); if (smu == NULL) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 1235135b384b..442e2be6052e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1359,16 +1359,11 @@ static int ctl_ioctl(struct inode *inode, struct file *file, * Copy the parameters into kernel space. */ r = copy_params(user, ¶m); - if (r) { - current->flags &= ~PF_MEMALLOC; - return r; - } - /* - * FIXME: eventually we will remove the PF_MEMALLOC flag - * here. However the tools still do nasty things like - * 'load' while a device is suspended. - */ + current->flags &= ~PF_MEMALLOC; + + if (r) + return r; r = validate_params(cmd, param); if (r) @@ -1386,7 +1381,6 @@ static int ctl_ioctl(struct inode *inode, struct file *file, out: free_params(param); - current->flags &= ~PF_MEMALLOC; return r; } diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index efe4adf78530..d73779a42417 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -112,7 +112,7 @@ void dm_destroy_dirty_log(struct dirty_log *log) /* * The on-disk version of the metadata. */ -#define MIRROR_DISK_VERSION 1 +#define MIRROR_DISK_VERSION 2 #define LOG_OFFSET 2 struct log_header { @@ -157,7 +157,6 @@ struct log_c { struct log_header *disk_header; struct io_region bits_location; - uint32_t *disk_bits; }; /* @@ -166,20 +165,20 @@ struct log_c { */ static inline int log_test_bit(uint32_t *bs, unsigned bit) { - return test_bit(bit, (unsigned long *) bs) ? 1 : 0; + return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0; } static inline void log_set_bit(struct log_c *l, uint32_t *bs, unsigned bit) { - set_bit(bit, (unsigned long *) bs); + ext2_set_bit(bit, (unsigned long *) bs); l->touched = 1; } static inline void log_clear_bit(struct log_c *l, uint32_t *bs, unsigned bit) { - clear_bit(bit, (unsigned long *) bs); + ext2_clear_bit(bit, (unsigned long *) bs); l->touched = 1; } @@ -219,6 +218,11 @@ static int read_header(struct log_c *log) log->header.nr_regions = 0; } +#ifdef __LITTLE_ENDIAN + if (log->header.version == 1) + log->header.version = 2; +#endif + if (log->header.version != MIRROR_DISK_VERSION) { DMWARN("incompatible disk log version"); return -EINVAL; @@ -239,45 +243,24 @@ static inline int write_header(struct log_c *log) /*---------------------------------------------------------------- * Bits IO *--------------------------------------------------------------*/ -static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count) -{ - unsigned i; - - for (i = 0; i < count; i++) - core[i] = le32_to_cpu(disk[i]); -} - -static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count) -{ - unsigned i; - - /* copy across the clean/dirty bitset */ - for (i = 0; i < count; i++) - disk[i] = cpu_to_le32(core[i]); -} - static int read_bits(struct log_c *log) { int r; unsigned long ebits; r = dm_io_sync_vm(1, &log->bits_location, READ, - log->disk_bits, &ebits); + log->clean_bits, &ebits); if (r) return r; - bits_to_core(log->clean_bits, log->disk_bits, - log->bitset_uint32_count); return 0; } static int write_bits(struct log_c *log) { unsigned long ebits; - bits_to_disk(log->clean_bits, log->disk_bits, - log->bitset_uint32_count); return dm_io_sync_vm(1, &log->bits_location, WRITE, - log->disk_bits, &ebits); + log->clean_bits, &ebits); } /*---------------------------------------------------------------- @@ -433,11 +416,6 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), 1 << SECTOR_SHIFT); lc->bits_location.count = size >> SECTOR_SHIFT; - lc->disk_bits = vmalloc(size); - if (!lc->disk_bits) { - vfree(lc->disk_header); - goto bad; - } return 0; bad: @@ -451,7 +429,6 @@ static void disk_dtr(struct dirty_log *log) struct log_c *lc = (struct log_c *) log->context; dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); - vfree(lc->disk_bits); core_dtr(log); } @@ -568,7 +545,8 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) return 0; do { - *region = find_next_zero_bit((unsigned long *) lc->sync_bits, + *region = ext2_find_next_zero_bit( + (unsigned long *) lc->sync_bits, lc->region_count, lc->sync_search); lc->sync_search = *region + 1; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 87727d84dbba..f3759dd7828e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -373,16 +373,11 @@ static inline ulong round_up(ulong n, ulong size) static void read_snapshot_metadata(struct dm_snapshot *s) { - if (s->have_metadata) - return; - if (s->store.read_metadata(&s->store)) { down_write(&s->lock); s->valid = 0; up_write(&s->lock); } - - s->have_metadata = 1; } /* @@ -471,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->chunk_shift = ffs(chunk_size) - 1; s->valid = 1; - s->have_metadata = 0; + s->active = 0; s->last_percent = 0; init_rwsem(&s->lock); s->table = ti->table; @@ -506,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad5; } + /* Metadata must only be loaded into one table at once */ + read_snapshot_metadata(s); + /* Add snapshot to the list of snapshots for this origin */ + /* Exceptions aren't triggered till snapshot_resume() is called */ if (register_snapshot(s)) { r = -EINVAL; ti->error = "Cannot register snapshot origin"; @@ -793,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, if (!s->valid) return -EIO; + if (unlikely(bio_barrier(bio))) + return -EOPNOTSUPP; + /* * Write to snapshot - higher level takes care of RW/RO * flags so we should only get this if we are @@ -862,7 +864,9 @@ static void snapshot_resume(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - read_snapshot_metadata(s); + down_write(&s->lock); + s->active = 1; + up_write(&s->lock); } static int snapshot_status(struct dm_target *ti, status_type_t type, @@ -932,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) /* Do all the snapshots on this origin */ list_for_each_entry (snap, snapshots, list) { - /* Only deal with valid snapshots */ - if (!snap->valid) + /* Only deal with valid and active snapshots */ + if (!snap->valid || !snap->active) continue; /* Nothing to do if writing beyond end of snapshot */ @@ -1057,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio, struct dm_dev *dev = (struct dm_dev *) ti->private; bio->bi_bdev = dev->bdev; + if (unlikely(bio_barrier(bio))) + return -EOPNOTSUPP; + /* Only tell snapshots if this is a write */ return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; } @@ -1104,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, static struct target_type origin_target = { .name = "snapshot-origin", - .version = {1, 0, 1}, + .version = {1, 1, 0}, .module = THIS_MODULE, .ctr = origin_ctr, .dtr = origin_dtr, @@ -1115,7 +1122,7 @@ static struct target_type origin_target = { static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 0, 1}, + .version = {1, 1, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 375aa24d4d7d..fdec1e2dc871 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h @@ -99,7 +99,9 @@ struct dm_snapshot { /* You can't use a snapshot if this is 0 (e.g. if full) */ int valid; - int have_metadata; + + /* Origin writes don't trigger exceptions until this is set */ + int active; /* Used for display of table */ char type; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a6f2dc66c3db..9b1e2f5ca630 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -508,7 +508,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, if (q->merge_bvec_fn) rs->max_sectors = min_not_zero(rs->max_sectors, - (unsigned short)(PAGE_SIZE >> 9)); + (unsigned int) (PAGE_SIZE >> 9)); rs->max_phys_segments = min_not_zero(rs->max_phys_segments, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8c16359f8b01..e9adeb9d172f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -31,6 +31,7 @@ struct dm_io { int error; struct bio *bio; atomic_t io_count; + unsigned long start_time; }; /* @@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) mempool_free(tio, md->tio_pool); } +static void start_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + + io->start_time = jiffies; + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = atomic_inc_return(&md->pending); +} + +static int end_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + struct bio *bio = io->bio; + unsigned long duration = jiffies - io->start_time; + int pending; + int rw = bio_data_dir(bio); + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + + disk_stat_add(dm_disk(md), ticks[rw], duration); + + return !pending; +} + /* * Add the bio to the list of deferred io. */ @@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error) io->error = error; if (atomic_dec_and_test(&io->io_count)) { - if (atomic_dec_and_test(&io->md->pending)) + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); @@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.sector_count = bio_sectors(bio); ci.idx = bio->bi_idx; - atomic_inc(&md->pending); + start_io_acct(ci.io); while (ci.sector_count) __clone_and_map(&ci); @@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) static int dm_request(request_queue_t *q, struct bio *bio) { int r; + int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; down_read(&md->io_lock); + disk_stat_inc(dm_disk(md), ios[rw]); + disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); + /* * If we're suspended we have to queue * this io for later. diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index ca99979c868a..8b3515f394a6 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -8,6 +8,7 @@ * completion notification. */ +#include <asm/types.h> #include <asm/atomic.h> #include <linux/blkdev.h> diff --git a/drivers/md/md.c b/drivers/md/md.c index 7145cd150f7b..d05e3125d298 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1024,7 +1024,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) rdev-> sb_size = (rdev->sb_size | bmask)+1; if (refdev == 0) - return 1; + ret = 1; else { __u64 ev1, ev2; struct mdp_superblock_1 *refsb = @@ -1044,7 +1044,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) ev2 = le64_to_cpu(refsb->events); if (ev1 > ev2) - return 1; + ret = 1; + else + ret = 0; } if (minor_version) rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; @@ -1058,7 +1060,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) if (le32_to_cpu(sb->size) > rdev->size*2) return -EINVAL; - return 0; + return ret; } static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) @@ -1081,7 +1083,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->size = le64_to_cpu(sb->size)/2; mddev->events = le64_to_cpu(sb->events); mddev->bitmap_offset = 0; - mddev->default_bitmap_offset = 1024; + mddev->default_bitmap_offset = 1024 >> 9; mddev->recovery_cp = le64_to_cpu(sb->resync_offset); memcpy(mddev->uuid, sb->set_uuid, 16); @@ -1161,6 +1163,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); + sb->raid_disks = cpu_to_le32(mddev->raid_disks); + sb->size = cpu_to_le64(mddev->size<<1); + if (mddev->bitmap && mddev->bitmap_file == NULL) { sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); @@ -2686,14 +2691,6 @@ static int do_md_stop(mddev_t * mddev, int ro) set_disk_ro(disk, 1); } - bitmap_destroy(mddev); - if (mddev->bitmap_file) { - atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); - fput(mddev->bitmap_file); - mddev->bitmap_file = NULL; - } - mddev->bitmap_offset = 0; - /* * Free resources if final stop */ @@ -2703,6 +2700,14 @@ static int do_md_stop(mddev_t * mddev, int ro) struct gendisk *disk; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); + bitmap_destroy(mddev); + if (mddev->bitmap_file) { + atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); + fput(mddev->bitmap_file); + mddev->bitmap_file = NULL; + } + mddev->bitmap_offset = 0; + ITERATE_RDEV(mddev,rdev,tmp) if (rdev->raid_disk >= 0) { char nm[20]; @@ -2939,6 +2944,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg) info.ctime = mddev->ctime; info.level = mddev->level; info.size = mddev->size; + if (info.size != mddev->size) /* overflow */ + info.size = -1; info.nr_disks = nr; info.raid_disks = mddev->raid_disks; info.md_minor = mddev->md_minor; @@ -3465,7 +3472,7 @@ static int update_size(mddev_t *mddev, unsigned long size) bdev = bdget_disk(mddev->gendisk, 0); if (bdev) { mutex_lock(&bdev->bd_inode->i_mutex); - i_size_write(bdev->bd_inode, mddev->array_size << 10); + i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10); mutex_unlock(&bdev->bd_inode->i_mutex); bdput(bdev); } @@ -3485,17 +3492,6 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) if (mddev->sync_thread) return -EBUSY; rv = mddev->pers->reshape(mddev, raid_disks); - if (!rv) { - struct block_device *bdev; - - bdev = bdget_disk(mddev->gendisk, 0); - if (bdev) { - mutex_lock(&bdev->bd_inode->i_mutex); - i_size_write(bdev->bd_inode, mddev->array_size << 10); - mutex_unlock(&bdev->bd_inode->i_mutex); - bdput(bdev); - } - } return rv; } @@ -3531,7 +3527,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) ) return -EINVAL; /* Check there is only one change */ - if (mddev->size != info->size) cnt++; + if (info->size >= 0 && mddev->size != info->size) cnt++; if (mddev->raid_disks != info->raid_disks) cnt++; if (mddev->layout != info->layout) cnt++; if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; @@ -3548,7 +3544,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) else return mddev->pers->reconfig(mddev, info->layout, -1); } - if (mddev->size != info->size) + if (info->size >= 0 && mddev->size != info->size) rv = update_size(mddev, info->size); if (mddev->raid_disks != info->raid_disks) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index d03f99cf4b7d..678f4dbbea1d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -372,7 +372,7 @@ out_free_conf: kfree(conf); mddev->private = NULL; out: - return 1; + return -ENOMEM; } static int raid0_stop (mddev_t *mddev) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9130d051b474..ab90a6d12020 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -565,6 +565,8 @@ rb_out: if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) atomic_inc(&conf->mirrors[disk].rdev->nr_pending); + else + disk = -1; rcu_read_unlock(); return disk; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 25976bfb6f9c..2dba305daf3c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -350,7 +350,8 @@ static void shrink_stripes(raid5_conf_t *conf) while (drop_one_stripe(conf)) ; - kmem_cache_destroy(conf->slab_cache); + if (conf->slab_cache) + kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f618a53b98be..cd477ebf2ee4 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) list_add_tail(&sh->lru, &conf->inactive_list); atomic_dec(&conf->active_stripes); if (!conf->inactive_blocked || - atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4)) + atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) wake_up(&conf->wait_for_stripe); } } @@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector conf->inactive_blocked = 1; wait_event_lock_irq(conf->wait_for_stripe, !list_empty(&conf->inactive_list) && - (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4) + (atomic_read(&conf->active_stripes) + < (conf->max_nr_stripes *3/4) || !conf->inactive_blocked), conf->device_lock, unplug_slaves(conf->mddev); @@ -302,9 +303,31 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector return sh; } -static int grow_stripes(raid6_conf_t *conf, int num) +static int grow_one_stripe(raid6_conf_t *conf) { struct stripe_head *sh; + sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); + if (!sh) + return 0; + memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); + sh->raid_conf = conf; + spin_lock_init(&sh->lock); + + if (grow_buffers(sh, conf->raid_disks)) { + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + return 0; + } + /* we just created an active stripe so... */ + atomic_set(&sh->count, 1); + atomic_inc(&conf->active_stripes); + INIT_LIST_HEAD(&sh->lru); + release_stripe(sh); + return 1; +} + +static int grow_stripes(raid6_conf_t *conf, int num) +{ kmem_cache_t *sc; int devs = conf->raid_disks; @@ -316,45 +339,35 @@ static int grow_stripes(raid6_conf_t *conf, int num) if (!sc) return 1; conf->slab_cache = sc; - while (num--) { - sh = kmem_cache_alloc(sc, GFP_KERNEL); - if (!sh) - return 1; - memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); - sh->raid_conf = conf; - spin_lock_init(&sh->lock); - - if (grow_buffers(sh, conf->raid_disks)) { - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(sc, sh); + while (num--) + if (!grow_one_stripe(conf)) return 1; - } - /* we just created an active stripe so... */ - atomic_set(&sh->count, 1); - atomic_inc(&conf->active_stripes); - INIT_LIST_HEAD(&sh->lru); - release_stripe(sh); - } return 0; } -static void shrink_stripes(raid6_conf_t *conf) +static int drop_one_stripe(raid6_conf_t *conf) { struct stripe_head *sh; + spin_lock_irq(&conf->device_lock); + sh = get_free_stripe(conf); + spin_unlock_irq(&conf->device_lock); + if (!sh) + return 0; + if (atomic_read(&sh->count)) + BUG(); + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + atomic_dec(&conf->active_stripes); + return 1; +} - while (1) { - spin_lock_irq(&conf->device_lock); - sh = get_free_stripe(conf); - spin_unlock_irq(&conf->device_lock); - if (!sh) - break; - if (atomic_read(&sh->count)) - BUG(); - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(conf->slab_cache, sh); - atomic_dec(&conf->active_stripes); - } - kmem_cache_destroy(conf->slab_cache); +static void shrink_stripes(raid6_conf_t *conf) +{ + while (drop_one_stripe(conf)) + ; + + if (conf->slab_cache) + kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } @@ -1912,6 +1925,74 @@ static void raid6d (mddev_t *mddev) PRINTK("--- raid6d inactive\n"); } +static ssize_t +raid6_show_stripe_cache_size(mddev_t *mddev, char *page) +{ + raid6_conf_t *conf = mddev_to_conf(mddev); + if (conf) + return sprintf(page, "%d\n", conf->max_nr_stripes); + else + return 0; +} + +static ssize_t +raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) +{ + raid6_conf_t *conf = mddev_to_conf(mddev); + char *end; + int new; + if (len >= PAGE_SIZE) + return -EINVAL; + if (!conf) + return -ENODEV; + + new = simple_strtoul(page, &end, 10); + if (!*page || (*end && *end != '\n') ) + return -EINVAL; + if (new <= 16 || new > 32768) + return -EINVAL; + while (new < conf->max_nr_stripes) { + if (drop_one_stripe(conf)) + conf->max_nr_stripes--; + else + break; + } + while (new > conf->max_nr_stripes) { + if (grow_one_stripe(conf)) + conf->max_nr_stripes++; + else break; + } + return len; +} + +static struct md_sysfs_entry +raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR, + raid6_show_stripe_cache_size, + raid6_store_stripe_cache_size); + +static ssize_t +stripe_cache_active_show(mddev_t *mddev, char *page) +{ + raid6_conf_t *conf = mddev_to_conf(mddev); + if (conf) + return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); + else + return 0; +} + +static struct md_sysfs_entry +raid6_stripecache_active = __ATTR_RO(stripe_cache_active); + +static struct attribute *raid6_attrs[] = { + &raid6_stripecache_size.attr, + &raid6_stripecache_active.attr, + NULL, +}; +static struct attribute_group raid6_attrs_group = { + .name = NULL, + .attrs = raid6_attrs, +}; + static int run(mddev_t *mddev) { raid6_conf_t *conf; @@ -2095,6 +2176,7 @@ static int stop (mddev_t *mddev) shrink_stripes(conf); kfree(conf->stripe_hashtbl); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ + sysfs_remove_group(&mddev->kobj, &raid6_attrs_group); kfree(conf); mddev->private = NULL; return 0; diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 2583a865a58e..2963605c0ecc 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP select DVB_STV0299 select DVB_MT352 select DVB_MT312 - select DVB_NXT2002 + select DVB_NXT200X select DVB_STV0297 select DVB_BCM3510 select DVB_LGDT330X diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 344a3c898460..7d7e1613c5a7 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma); int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); -int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); -int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets); /* from flexcop-eeprom.c */ /* the PCI part uses this call to get the MAC address, the USB part has its own */ diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index cf4ed1df6086..6f592bc32d22 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c @@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc, } EXPORT_SYMBOL(flexcop_dma_config_timer); -/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */ -int flexcop_dma_control_packet_irq(struct flexcop_device *fc, - flexcop_dma_index_t no, - int onoff) -{ - flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); - - deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); - if (no & FC_DMA_1) - v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; - - if (no & FC_DMA_2) - v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; - - fc->write_ibi_reg(fc,ctrl_208,v); - deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); - - return 0; -} -EXPORT_SYMBOL(flexcop_dma_control_packet_irq); - -int flexcop_dma_config_packet_count(struct flexcop_device *fc, - flexcop_dma_index_t dma_idx, - u8 packets) -{ - flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; - flexcop_ibi_value v = fc->read_ibi_reg(fc,r); - - flexcop_dma_remap(fc,dma_idx,1); - - v.dma_0x4_remap.DMA_maxpackets = packets; - fc->write_ibi_reg(fc,r,v); - return 0; -} -EXPORT_SYMBOL(flexcop_dma_config_packet_count); diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 0b940e152b79..390cc3a99ce6 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -9,7 +9,7 @@ #include "stv0299.h" #include "mt352.h" -#include "nxt2002.h" +#include "nxt200x.h" #include "bcm3510.h" #include "stv0297.h" #include "mt312.h" @@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { .clock_polarity_flip = 1, }; -static struct nxt2002_config samsung_tbmv_config = { +static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, - .request_firmware = flexcop_fe_request_firmware, + .pll_address = 0xc2, + .pll_desc = &dvb_pll_samsung_tbmv, }; static struct bcm3510_config air2pc_atsc_first_gen_config = { @@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); } else /* try the air atsc 2nd generation (nxt2002) */ - if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC2; info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 62282d8dbfa8..167583bf0621 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c @@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc) /* bus parts have to decide if hw pid filtering is used or not. */ } -const char *flexcop_revision_names[] = { +static const char *flexcop_revision_names[] = { "Unkown chip", "FlexCopII", "FlexCopIIb", "FlexCopIII", }; -const char *flexcop_device_names[] = { +static const char *flexcop_device_names[] = { "Unkown device", "Air2PC/AirStar 2 DVB-T", "Air2PC/AirStar 2 ATSC 1st generation", @@ -54,7 +54,7 @@ const char *flexcop_device_names[] = { "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", }; -const char *flexcop_bus_names[] = { +static const char *flexcop_bus_names[] = { "USB", "PCI", }; diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 2f76eb3fea40..9bc40bdcc282 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; - deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", - jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); + deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", + jiffies_to_usecs(jiffies - fc_pci->last_irq), + v.raw, (unsigned long long)cur_addr, cur_pos, + fc_pci->last_dma1_cur_pos); fc_pci->last_irq = jiffies; /* buffer end was reached, restarted from the beginning diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 3153f9513c63..491f9bd6e195 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h @@ -16,8 +16,6 @@ typedef enum { FLEXCOP_III, } flexcop_revision_t; -extern const char *flexcop_revision_names[]; - typedef enum { FC_UNK = 0, FC_AIR_DVB, @@ -34,8 +32,6 @@ typedef enum { FC_PCI, } flexcop_bus_t; -extern const char *flexcop_device_names[]; - /* FlexCop IBI Registers */ #if defined(__LITTLE_ENDIAN) #include "flexcop_ibi_value_le.h" diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index a04bb61f21f4..34c3189a1a33 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * EXPORT_SYMBOL(bt878_device_control); + +struct cards card_list[] __devinitdata = { + + { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, + { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, + { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, + { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, + { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, + { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, + { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, + { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0, -1, NULL } +}; + + /***********************/ /* PCI device handling */ /***********************/ @@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control); static int __devinit bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { - int result; + int result = 0, has_dvb = 0, i; unsigned char lat; struct bt878 *bt; #if defined(__powerpc__) unsigned int cmd; #endif + unsigned int cardid; + unsigned short id; + struct cards *dvb_cards; printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); if (pci_enable_device(dev)) return -EIO; + pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id); + cardid = id << 16; + pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id); + cardid |= id; + + for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) { + if (cardid == dvb_cards->pci_id) { + printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n", + __func__, cardid, dvb_cards->name); + has_dvb = 1; + } + } + + if (!has_dvb) { + printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid); + result = -EINVAL; + + goto fail0; + } + bt = &bt878[bt878_num]; bt->dev = dev; bt->nr = bt878_num; @@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + + printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", bt878_num, bt->id, bt->revision, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index a73baf00ca39..9faf93770d08 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h @@ -88,6 +88,23 @@ #define BT878_RISC_SYNC_MASK (1 << 15) + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 + +struct cards { + __u32 pci_id; + __u16 card_id; + char *name; +}; + extern int bt878_num; struct bt878 { diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 90a69d343b79..d3df12039b06 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -83,12 +83,18 @@ config DVB_USB_UMT_010 Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. config DVB_USB_CXUSB - tristate "Medion MD95700 hybrid USB2.0 (Conexant) support" + tristate "Conexant USB2.0 hybrid reference design support" depends on DVB_USB select DVB_CX22702 + select DVB_LGDT330X + select DVB_MT352 help - Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently - only the DVB-T part is supported. + Say Y here to support the Conexant USB2.0 hybrid reference design. + Currently, only DVB and ATSC modes are supported, analog mode + shall be added in the future. Devices that require this module: + + Medion MD95700 hybrid USB2.0 device. + DViCO FusionHDTV (Bluebird) USB2.0 devices config DVB_USB_DIGITV tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index a7fb06f4cd34..f327fac1688e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } -struct dvb_usb_rc_key dvico_mce_rc_keys[] = { +static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { { 0xfe, 0x02, KEY_TV }, { 0xfe, 0x0e, KEY_MP3 }, { 0xfe, 0x1a, KEY_DVD }, @@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = { static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) { - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; @@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) static int cxusb_mt352_demod_init(struct dvb_frontend* fe) { /* used in both lgz201 and th7579 */ - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; @@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) return 0; } -struct cx22702_config cxusb_cx22702_config = { +static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, .output_mode = CX22702_PARALLEL_OUTPUT, @@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = { .pll_set = dvb_usb_pll_set_i2c, }; -struct lgdt330x_config cxusb_lgdt330x_config = { +static struct lgdt330x_config cxusb_lgdt330x_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .pll_set = dvb_usb_pll_set_i2c, }; -struct mt352_config cxusb_dee1601_config = { +static struct mt352_config cxusb_dee1601_config = { .demod_address = 0x0f, .demod_init = cxusb_dee1601_demod_init, .pll_set = dvb_usb_pll_set, diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index e6c55c9c9417..caa1346e3063 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -175,11 +175,13 @@ static int digitv_probe(struct usb_interface *intf, if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { u8 b[4] = { 0 }; - b[0] = 1; - digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); + if (d != NULL) { /* do that only when the firmware is loaded */ + b[0] = 1; + digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); - b[0] = 0; - digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); + b[0] = 0; + digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); + } } return ret; } @@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-digitv-01.fw", + .firmware = "dvb-usb-digitv-02.fw", .size_of_priv = 0, @@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = { { &digitv_table[0], NULL }, { NULL }, }, + { NULL }, } }; diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index 130ea7f21f5e..12ebaf8bddca 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = { .cold_ids = { &dtt200u_usb_table[0], NULL }, .warm_ids = { &dtt200u_usb_table[1], NULL }, }, - { 0 }, + { NULL }, } }; @@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = { .cold_ids = { &dtt200u_usb_table[2], NULL }, .warm_ids = { &dtt200u_usb_table[3], NULL }, }, - { 0 }, + { NULL }, } }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c index 8535895819fb..9222b0a81f74 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c @@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = { { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, }; +static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, + int *pos); + /* * load a firmware packet to the device */ @@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties return ret; } -int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) +static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, + int *pos) { u8 *b = (u8 *) &fw->data[*pos]; int data_offs = 4; @@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) return *pos; } -EXPORT_SYMBOL(dvb_usb_get_hexline); - diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index dd568396e594..5e5d21ad93c9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -341,7 +341,6 @@ struct hexline { u8 data[255]; u8 chk; }; -extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *); extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); #endif diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index afa00fdb5ec0..4a95eca81c5c 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 return ret; } -int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) { deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); @@ -88,7 +89,8 @@ unlock: return ret; } -int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec) +static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, + int olen, u8 *i, int ilen, int msec) { u8 bout[olen+2]; u8 bin[ilen+1]; diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h index a808d48e7bf2..c2f97f96c21f 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/dvb/dvb-usb/vp702x.h @@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug; extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); -extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec); extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); -extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); #endif diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c index 5242cca5db4a..9999336aeeb6 100644 --- a/drivers/media/dvb/dvb-usb/vp7045-fe.c +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c @@ -23,10 +23,11 @@ struct vp7045_fe_state { struct dvb_frontend fe; + struct dvb_frontend_ops ops; + struct dvb_usb_device *d; }; - static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) { struct vp7045_fe_state *state = fe->demodulator_priv; @@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) goto error; s->d = d; - s->fe.ops = &vp7045_fe_ops; + memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); + s->fe.ops = &s->ops; s->fe.demodulator_priv = s; goto success; diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 028204956bb0..3835235b68df 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = { .cold_ids = { &vp7045_usb_table[2], NULL }, .warm_ids = { &vp7045_usb_table[3], NULL }, }, - { 0 }, + { NULL }, } }; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index db3a8b40031e..76b6a2aef32f 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -28,12 +28,6 @@ config DVB_TDA8083 help A DVB-S tuner module. Say Y when you want to support this frontend. -config DVB_TDA80XX - tristate "Philips TDA8044 or TDA8083 based" - depends on DVB_CORE - help - A DVB-S tuner module. Say Y when you want to support this frontend. - config DVB_MT312 tristate "Zarlink MT312 based" depends on DVB_CORE @@ -139,12 +133,6 @@ config DVB_DIB3000MC comment "DVB-C (cable) frontends" depends on DVB_CORE -config DVB_ATMEL_AT76C651 - tristate "Atmel AT76C651 based" - depends on DVB_CORE - help - A DVB-C tuner module. Say Y when you want to support this frontend. - config DVB_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE @@ -166,18 +154,6 @@ config DVB_STV0297 comment "ATSC (North American/Korean Terresterial DTV) frontends" depends on DVB_CORE -config DVB_NXT2002 - tristate "Nxt2002 based" - depends on DVB_CORE - select FW_LOADER - help - An ATSC 8VSB tuner module. Say Y when you want to support this frontend. - - This driver needs external firmware. Please use the command - "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to - download/extract it, and then copy it to /usr/lib/hotplug/firmware - or /lib/firmware (depending on configuration of firmware hotplug). - config DVB_NXT200X tristate "Nextwave NXT2002/NXT2004 based" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 615ec830e1c9..1af769cd90c0 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_CX22700) += cx22700.o -obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o @@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_CX22702) += cx22702.o -obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o -obj-$(CONFIG_DVB_NXT2002) += nxt2002.o obj-$(CONFIG_DVB_NXT200X) += nxt200x.o obj-$(CONFIG_DVB_OR51211) += or51211.o obj-$(CONFIG_DVB_OR51132) += or51132.o diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c deleted file mode 100644 index 8e0f4b3a1417..000000000000 --- a/drivers/media/dvb/frontends/at76c651.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * at76c651.c - * - * Atmel DVB-C Frontend Driver (at76c651/tua6010xs) - * - * Copyright (C) 2001 fnbrd <fnbrd@gmx.de> - * & 2002-2004 Andreas Oberritter <obi@linuxtv.org> - * & 2003 Wolfram Joost <dbox2@frokaschwei.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * AT76C651 - * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf - * http://www.atmel.com/atmel/acrobat/doc1320.pdf - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include "dvb_frontend.h" -#include "at76c651.h" - - -struct at76c651_state { - - struct i2c_adapter* i2c; - - struct dvb_frontend_ops ops; - - const struct at76c651_config* config; - - struct dvb_frontend frontend; - - /* revision of the chip */ - u8 revision; - - /* last QAM value set */ - u8 qam; -}; - -static int debug; -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "at76c651: " args); \ - } while (0) - - -#if ! defined(__powerpc__) -static __inline__ int __ilog2(unsigned long x) -{ - int i; - - if (x == 0) - return -1; - - for (i = 0; x != 0; i++) - x >>= 1; - - return i - 1; -} -#endif - -static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data) -{ - int ret; - u8 buf[] = { reg, data }; - struct i2c_msg msg = - { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - dprintk("%s: writereg error " - "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, data, ret); - - msleep(10); - - return (ret != 1) ? -EREMOTEIO : 0; -} - -static u8 at76c651_readreg(struct at76c651_state* state, u8 reg) -{ - int ret; - u8 val; - struct i2c_msg msg[] = { - { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 } - }; - - ret = i2c_transfer(state->i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return val; -} - -static int at76c651_reset(struct at76c651_state* state) -{ - return at76c651_writereg(state, 0x07, 0x01); -} - -static void at76c651_disable_interrupts(struct at76c651_state* state) -{ - at76c651_writereg(state, 0x0b, 0x00); -} - -static int at76c651_set_auto_config(struct at76c651_state *state) -{ - /* - * Autoconfig - */ - - at76c651_writereg(state, 0x06, 0x01); - - /* - * Performance optimizations, should be done after autoconfig - */ - - at76c651_writereg(state, 0x10, 0x06); - at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); - at76c651_writereg(state, 0x15, 0x28); - at76c651_writereg(state, 0x20, 0x09); - at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); - at76c651_writereg(state, 0x30, 0x90); - if (state->qam == 5) - at76c651_writereg(state, 0x35, 0x2A); - - /* - * Initialize A/D-converter - */ - - if (state->revision == 0x11) { - at76c651_writereg(state, 0x2E, 0x38); - at76c651_writereg(state, 0x2F, 0x13); - } - - at76c651_disable_interrupts(state); - - /* - * Restart operation - */ - - at76c651_reset(state); - - return 0; -} - -static void at76c651_set_bbfreq(struct at76c651_state* state) -{ - at76c651_writereg(state, 0x04, 0x3f); - at76c651_writereg(state, 0x05, 0xee); -} - -static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate) -{ - u8 exponent; - u32 mantissa; - - if (symbol_rate > 9360000) - return -EINVAL; - - /* - * FREF = 57800 kHz - * exponent = 10 + floor (log2(symbol_rate / FREF)) - * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent)) - */ - - exponent = __ilog2((symbol_rate << 4) / 903125); - mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289; - - at76c651_writereg(state, 0x00, mantissa >> 13); - at76c651_writereg(state, 0x01, mantissa >> 5); - at76c651_writereg(state, 0x02, (mantissa << 3) | exponent); - - return 0; -} - -static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam) -{ - switch (qam) { - case QPSK: - state->qam = 0x02; - break; - case QAM_16: - state->qam = 0x04; - break; - case QAM_32: - state->qam = 0x05; - break; - case QAM_64: - state->qam = 0x06; - break; - case QAM_128: - state->qam = 0x07; - break; - case QAM_256: - state->qam = 0x08; - break; -#if 0 - case QAM_512: - state->qam = 0x09; - break; - case QAM_1024: - state->qam = 0x0A; - break; -#endif - default: - return -EINVAL; - - } - - return at76c651_writereg(state, 0x03, state->qam); -} - -static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion) -{ - u8 feciqinv = at76c651_readreg(state, 0x60); - - switch (inversion) { - case INVERSION_OFF: - feciqinv |= 0x02; - feciqinv &= 0xFE; - break; - - case INVERSION_ON: - feciqinv |= 0x03; - break; - - case INVERSION_AUTO: - feciqinv &= 0xFC; - break; - - default: - return -EINVAL; - } - - return at76c651_writereg(state, 0x60, feciqinv); -} - -static int at76c651_set_parameters(struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) -{ - int ret; - struct at76c651_state* state = fe->demodulator_priv; - - at76c651_writereg(state, 0x0c, 0xc3); - state->config->pll_set(fe, p); - at76c651_writereg(state, 0x0c, 0xc2); - - if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) - return ret; - - if ((ret = at76c651_set_inversion(state, p->inversion))) - return ret; - - return at76c651_set_auto_config(state); -} - -static int at76c651_set_defaults(struct dvb_frontend* fe) -{ - struct at76c651_state* state = fe->demodulator_priv; - - at76c651_set_symbol_rate(state, 6900000); - at76c651_set_qam(state, QAM_64); - at76c651_set_bbfreq(state); - at76c651_set_auto_config(state); - - if (state->config->pll_init) { - at76c651_writereg(state, 0x0c, 0xc3); - state->config->pll_init(fe); - at76c651_writereg(state, 0x0c, 0xc2); - } - - return 0; -} - -static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct at76c651_state* state = fe->demodulator_priv; - u8 sync; - - /* - * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) - */ - sync = at76c651_readreg(state, 0x80); - *status = 0; - - if (sync & (0x04 | 0x10)) /* AGC1 || TIM */ - *status |= FE_HAS_SIGNAL; - if (sync & 0x10) /* TIM */ - *status |= FE_HAS_CARRIER; - if (sync & 0x80) /* FEC */ - *status |= FE_HAS_VITERBI; - if (sync & 0x40) /* CAR */ - *status |= FE_HAS_SYNC; - if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */ - *status |= FE_HAS_LOCK; - - return 0; -} - -static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16; - *ber |= at76c651_readreg(state, 0x82) << 8; - *ber |= at76c651_readreg(state, 0x83); - *ber *= 10; - - return 0; -} - -static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct at76c651_state* state = fe->demodulator_priv; - - u8 gain = ~at76c651_readreg(state, 0x91); - *strength = (gain << 8) | gain; - - return 0; -} - -static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *snr = 0xFFFF - - ((at76c651_readreg(state, 0x8F) << 8) | - at76c651_readreg(state, 0x90)); - - return 0; -} - -static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *ucblocks = at76c651_readreg(state, 0x82); - - return 0; -} - -static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings) -{ - fesettings->min_delay_ms = 50; - fesettings->step_size = 0; - fesettings->max_drift = 0; - return 0; -} - -static void at76c651_release(struct dvb_frontend* fe) -{ - struct at76c651_state* state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops at76c651_ops; - -struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, - struct i2c_adapter* i2c) -{ - struct at76c651_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->qam = 0; - - /* check if the demod is there */ - if (at76c651_readreg(state, 0x0e) != 0x65) goto error; - - /* finalise state setup */ - state->i2c = i2c; - state->revision = at76c651_readreg(state, 0x0f) & 0xfe; - memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops)); - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops at76c651_ops = { - - .info = { - .name = "Atmel AT76C651B DVB-C", - .type = FE_QAM, - .frequency_min = 48250000, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER - }, - - .release = at76c651_release, - - .init = at76c651_set_defaults, - - .set_frontend = at76c651_set_parameters, - .get_tune_settings = at76c651_get_tune_settings, - - .read_status = at76c651_read_status, - .read_ber = at76c651_read_ber, - .read_signal_strength = at76c651_read_signal_strength, - .read_snr = at76c651_read_snr, - .read_ucblocks = at76c651_read_ucblocks, -}; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - -MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver"); -MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(at76c651_attach); diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h deleted file mode 100644 index 34054df93608..000000000000 --- a/drivers/media/dvb/frontends/at76c651.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * at76c651.c - * - * Atmel DVB-C Frontend Driver (at76c651) - * - * Copyright (C) 2001 fnbrd <fnbrd@gmx.de> - * & 2002-2004 Andreas Oberritter <obi@linuxtv.org> - * & 2003 Wolfram Joost <dbox2@frokaschwei.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * AT76C651 - * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf - * http://www.atmel.com/atmel/acrobat/doc1320.pdf - */ - -#ifndef AT76C651_H -#define AT76C651_H - -#include <linux/dvb/frontend.h> - -struct at76c651_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); -}; - -extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, - struct i2c_adapter* i2c); - -#endif // AT76C651_H diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 1b9934ea5b06..4dcb6050d4fa 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -326,11 +326,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = { }; EXPORT_SYMBOL(dvb_pll_tuv1236d); -/* Samsung TBMV30111IN +/* Samsung TBMV30111IN / TBMV30712IN1 * used in Air2PC ATSC - 2nd generation (nxt2002) */ -struct dvb_pll_desc dvb_pll_tbmv30111in = { - .name = "Samsung TBMV30111IN", +struct dvb_pll_desc dvb_pll_samsung_tbmv = { + .name = "Samsung TBMV30111IN / TBMV30712IN1", .min = 54000000, .max = 860000000, .count = 6, @@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = { { 999999999, 44000000, 166666, 0xfc, 0x02 }, } }; -EXPORT_SYMBOL(dvb_pll_tbmv30111in); +EXPORT_SYMBOL(dvb_pll_samsung_tbmv); /* * Philips SD1878 Tuner. diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index f682c09189b3..bb8d4b4eb183 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4; extern struct dvb_pll_desc dvb_pll_tuv1236d; extern struct dvb_pll_desc dvb_pll_tdhu2; -extern struct dvb_pll_desc dvb_pll_tbmv30111in; +extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c deleted file mode 100644 index 4f263e65ba14..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - Support for B2C2/BBTI Technisat Air2PC - ATSC - - Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/* - * This driver needs external firmware. Please use the command - * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware - * or /lib/firmware (depending on configuration of firmware hotplug). - */ -#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" -#define CRC_CCIT_MASK 0x1021 - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/device.h> -#include <linux/firmware.h> -#include <linux/string.h> -#include <linux/slab.h> - -#include "dvb_frontend.h" -#include "nxt2002.h" - -struct nxt2002_state { - - struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - const struct nxt2002_config* config; - struct dvb_frontend frontend; - - /* demodulator private data */ - u8 initialised:1; -}; - -static int debug; -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "nxt2002: " args); \ - } while (0) - -static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len) -{ - /* probbably a much better way or doing this */ - u8 buf2 [256],x; - int err; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 }; - - buf2[0] = reg; - for (x = 0 ; x < len ; x++) - buf2[x+1] = buf[x]; - - if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk ("%s: i2c write error (addr %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); - return -EREMOTEIO; - } - - return 0; -} - -static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len) -{ - u8 reg2 [] = { reg }; - - struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; - - int err; - - if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { - printk ("%s: i2c read error (addr %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); - return -EREMOTEIO; - } - - return 0; -} - -static u16 nxt2002_crc(u16 crc, u8 c) -{ - - u8 i; - u16 input = (u16) c & 0xFF; - - input<<=8; - for(i=0 ;i<8 ;i++) { - if((crc ^ input) & 0x8000) - crc=(crc<<1)^CRC_CCIT_MASK; - else - crc<<=1; - input<<=1; - } - return crc; -} - -static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - /* set multi register length */ - i2c_writebytes(state,0x34,&len,1); - - /* set mutli register register */ - i2c_writebytes(state,0x35,®,1); - - /* send the actual data */ - i2c_writebytes(state,0x36,data,len); - - /* toggle the multireg write bit*/ - buf = 0x02; - i2c_writebytes(state,0x21,&buf,1); - - i2c_readbytes(state,0x21,&buf,1); - - if ((buf & 0x02) == 0) - return 0; - - dprintk("Error writing multireg register %02X\n",reg); - - return 0; -} - -static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) -{ - u8 len2; - dprintk("%s\n", __FUNCTION__); - - /* set multi register length */ - len2 = len & 0x80; - i2c_writebytes(state,0x34,&len2,1); - - /* set mutli register register */ - i2c_writebytes(state,0x35,®,1); - - /* send the actual data */ - i2c_readbytes(state,reg,data,len); - - return 0; -} - -static void nxt2002_microcontroller_stop (struct nxt2002_state* state) -{ - u8 buf[2],counter = 0; - dprintk("%s\n", __FUNCTION__); - - buf[0] = 0x80; - i2c_writebytes(state,0x22,buf,1); - - while (counter < 20) { - i2c_readbytes(state,0x31,buf,1); - if (buf[0] & 0x40) - return; - msleep(10); - counter++; - } - - dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n"); - return; -} - -static void nxt2002_microcontroller_start (struct nxt2002_state* state) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - buf = 0x00; - i2c_writebytes(state,0x22,&buf,1); -} - -static int nxt2002_writetuner (struct nxt2002_state* state, u8* data) -{ - u8 buf,count = 0; - - dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]); - - dprintk("%s\n", __FUNCTION__); - /* stop the micro first */ - nxt2002_microcontroller_stop(state); - - /* set the i2c transfer speed to the tuner */ - buf = 0x03; - i2c_writebytes(state,0x20,&buf,1); - - /* setup to transfer 4 bytes via i2c */ - buf = 0x04; - i2c_writebytes(state,0x34,&buf,1); - - /* write actual tuner bytes */ - i2c_writebytes(state,0x36,data,4); - - /* set tuner i2c address */ - buf = 0xC2; - i2c_writebytes(state,0x35,&buf,1); - - /* write UC Opmode to begin transfer */ - buf = 0x80; - i2c_writebytes(state,0x21,&buf,1); - - while (count < 20) { - i2c_readbytes(state,0x21,&buf,1); - if ((buf & 0x80)== 0x00) - return 0; - msleep(100); - count++; - } - - printk("nxt2002: timeout error writing tuner\n"); - return 0; -} - -static void nxt2002_agc_reset(struct nxt2002_state* state) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - buf = 0x08; - i2c_writebytes(state,0x08,&buf,1); - - buf = 0x00; - i2c_writebytes(state,0x08,&buf,1); - - return; -} - -static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) -{ - - struct nxt2002_state* state = fe->demodulator_priv; - u8 buf[256],written = 0,chunkpos = 0; - u16 rambase,position,crc = 0; - - dprintk("%s\n", __FUNCTION__); - dprintk("Firmware is %zu bytes\n",fw->size); - - /* Get the RAM base for this nxt2002 */ - i2c_readbytes(state,0x10,buf,1); - - if (buf[0] & 0x10) - rambase = 0x1000; - else - rambase = 0x0000; - - dprintk("rambase on this nxt2002 is %04X\n",rambase); - - /* Hold the micro in reset while loading firmware */ - buf[0] = 0x80; - i2c_writebytes(state,0x2B,buf,1); - - for (position = 0; position < fw->size ; position++) { - if (written == 0) { - crc = 0; - chunkpos = 0x28; - buf[0] = ((rambase + position) >> 8); - buf[1] = (rambase + position) & 0xFF; - buf[2] = 0x81; - /* write starting address */ - i2c_writebytes(state,0x29,buf,3); - } - written++; - chunkpos++; - - if ((written % 4) == 0) - i2c_writebytes(state,chunkpos,&fw->data[position-3],4); - - crc = nxt2002_crc(crc,fw->data[position]); - - if ((written == 255) || (position+1 == fw->size)) { - /* write remaining bytes of firmware */ - i2c_writebytes(state, chunkpos+4-(written %4), - &fw->data[position-(written %4) + 1], - written %4); - buf[0] = crc << 8; - buf[1] = crc & 0xFF; - - /* write crc */ - i2c_writebytes(state,0x2C,buf,2); - - /* do a read to stop things */ - i2c_readbytes(state,0x2A,buf,1); - - /* set transfer mode to complete */ - buf[0] = 0x80; - i2c_writebytes(state,0x2B,buf,1); - - written = 0; - } - } - - printk ("done.\n"); - return 0; -}; - -static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u32 freq = 0; - u16 tunerfreq = 0; - u8 buf[4]; - - freq = 44000 + ( p->frequency / 1000 ); - - dprintk("freq = %d p->frequency = %d\n",freq,p->frequency); - - tunerfreq = freq * 24/4000; - - buf[0] = (tunerfreq >> 8) & 0x7F; - buf[1] = (tunerfreq & 0xFF); - - if (p->frequency <= 214000000) { - buf[2] = 0x84 + (0x06 << 3); - buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02; - } else if (p->frequency <= 721000000) { - buf[2] = 0x84 + (0x07 << 3); - buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08; - } else if (p->frequency <= 841000000) { - buf[2] = 0x84 + (0x0E << 3); - buf[3] = 0x08; - } else { - buf[2] = 0x84 + (0x0F << 3); - buf[3] = 0x02; - } - - /* write frequency information */ - nxt2002_writetuner(state,buf); - - /* reset the agc now that tuning has been completed */ - nxt2002_agc_reset(state); - - /* set target power level */ - switch (p->u.vsb.modulation) { - case QAM_64: - case QAM_256: - buf[0] = 0x74; - break; - case VSB_8: - buf[0] = 0x70; - break; - default: - return -EINVAL; - break; - } - i2c_writebytes(state,0x42,buf,1); - - /* configure sdm */ - buf[0] = 0x87; - i2c_writebytes(state,0x57,buf,1); - - /* write sdm1 input */ - buf[0] = 0x10; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x58,buf,2); - - /* write sdmx input */ - switch (p->u.vsb.modulation) { - case QAM_64: - buf[0] = 0x68; - break; - case QAM_256: - buf[0] = 0x64; - break; - case VSB_8: - buf[0] = 0x60; - break; - default: - return -EINVAL; - break; - } - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x5C,buf,2); - - /* write adc power lpf fc */ - buf[0] = 0x05; - i2c_writebytes(state,0x43,buf,1); - - /* write adc power lpf fc */ - buf[0] = 0x05; - i2c_writebytes(state,0x43,buf,1); - - /* write accumulator2 input */ - buf[0] = 0x80; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x4B,buf,2); - - /* write kg1 */ - buf[0] = 0x00; - i2c_writebytes(state,0x4D,buf,1); - - /* write sdm12 lpf fc */ - buf[0] = 0x44; - i2c_writebytes(state,0x55,buf,1); - - /* write agc control reg */ - buf[0] = 0x04; - i2c_writebytes(state,0x41,buf,1); - - /* write agc ucgp0 */ - switch (p->u.vsb.modulation) { - case QAM_64: - buf[0] = 0x02; - break; - case QAM_256: - buf[0] = 0x03; - break; - case VSB_8: - buf[0] = 0x00; - break; - default: - return -EINVAL; - break; - } - i2c_writebytes(state,0x30,buf,1); - - /* write agc control reg */ - buf[0] = 0x00; - i2c_writebytes(state,0x41,buf,1); - - /* write accumulator2 input */ - buf[0] = 0x80; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x49,buf,2); - nxt2002_writereg_multibyte(state,0x4B,buf,2); - - /* write agc control reg */ - buf[0] = 0x04; - i2c_writebytes(state,0x41,buf,1); - - nxt2002_microcontroller_start(state); - - /* adjacent channel detection should be done here, but I don't - have any stations with this need so I cannot test it */ - - return 0; -} - -static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 lock; - i2c_readbytes(state,0x31,&lock,1); - - *status = 0; - if (lock & 0x20) { - *status |= FE_HAS_SIGNAL; - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_LOCK; - } - return 0; -} - -static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[3]; - - nxt2002_readreg_multibyte(state,0xE6,b,3); - - *ber = ((b[0] << 8) + b[1]) * 8; - - return 0; -} - -static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[2]; - u16 temp = 0; - - /* setup to read cluster variance */ - b[0] = 0x00; - i2c_writebytes(state,0xA1,b,1); - - /* get multreg val */ - nxt2002_readreg_multibyte(state,0xA6,b,2); - - temp = (b[0] << 8) | b[1]; - *strength = ((0x7FFF - temp) & 0x0FFF) * 16; - - return 0; -} - -static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr) -{ - - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[2]; - u16 temp = 0, temp2; - u32 snrdb = 0; - - /* setup to read cluster variance */ - b[0] = 0x00; - i2c_writebytes(state,0xA1,b,1); - - /* get multreg val from 0xA6 */ - nxt2002_readreg_multibyte(state,0xA6,b,2); - - temp = (b[0] << 8) | b[1]; - temp2 = 0x7FFF - temp; - - /* snr will be in db */ - if (temp2 > 0x7F00) - snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) ); - else if (temp2 > 0x7EC0) - snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) ); - else if (temp2 > 0x7C00) - snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) ); - else - snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) ); - - /* the value reported back from the frontend will be FFFF=32db 0000=0db */ - - *snr = snrdb * (0xFFFF/32000); - - return 0; -} - -static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[3]; - - nxt2002_readreg_multibyte(state,0xE6,b,3); - *ucblocks = b[2]; - - return 0; -} - -static int nxt2002_sleep(struct dvb_frontend* fe) -{ - return 0; -} - -static int nxt2002_init(struct dvb_frontend* fe) -{ - struct nxt2002_state* state = fe->demodulator_priv; - const struct firmware *fw; - int ret; - u8 buf[2]; - - if (!state->initialised) { - /* request the firmware, this will block until someone uploads it */ - printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); - ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE); - printk("nxt2002: Waiting for firmware upload(2)...\n"); - if (ret) { - printk("nxt2002: no firmware upload (timeout or file not found?)\n"); - return ret; - } - - ret = nxt2002_load_firmware(fe, fw); - if (ret) { - printk("nxt2002: writing firmware to device failed\n"); - release_firmware(fw); - return ret; - } - printk("nxt2002: firmware upload complete\n"); - - /* Put the micro into reset */ - nxt2002_microcontroller_stop(state); - - /* ensure transfer is complete */ - buf[0]=0; - i2c_writebytes(state,0x2B,buf,1); - - /* Put the micro into reset for real this time */ - nxt2002_microcontroller_stop(state); - - /* soft reset everything (agc,frontend,eq,fec)*/ - buf[0] = 0x0F; - i2c_writebytes(state,0x08,buf,1); - buf[0] = 0x00; - i2c_writebytes(state,0x08,buf,1); - - /* write agc sdm configure */ - buf[0] = 0xF1; - i2c_writebytes(state,0x57,buf,1); - - /* write mod output format */ - buf[0] = 0x20; - i2c_writebytes(state,0x09,buf,1); - - /* write fec mpeg mode */ - buf[0] = 0x7E; - buf[1] = 0x00; - i2c_writebytes(state,0xE9,buf,2); - - /* write mux selection */ - buf[0] = 0x00; - i2c_writebytes(state,0xCC,buf,1); - - state->initialised = 1; - } - - return 0; -} - -static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) -{ - fesettings->min_delay_ms = 500; - fesettings->step_size = 0; - fesettings->max_drift = 0; - return 0; -} - -static void nxt2002_release(struct dvb_frontend* fe) -{ - struct nxt2002_state* state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops nxt2002_ops; - -struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, - struct i2c_adapter* i2c) -{ - struct nxt2002_state* state = NULL; - u8 buf [] = {0,0,0,0,0}; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops)); - state->initialised = 0; - - /* Check the first 5 registers to ensure this a revision we can handle */ - - i2c_readbytes(state, 0x00, buf, 5); - if (buf[0] != 0x04) goto error; /* device id */ - if (buf[1] != 0x02) goto error; /* fab id */ - if (buf[2] != 0x11) goto error; /* month */ - if (buf[3] != 0x20) goto error; /* year msb */ - if (buf[4] != 0x00) goto error; /* year lsb */ - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops nxt2002_ops = { - - .info = { - .name = "Nextwave nxt2002 VSB/QAM frontend", - .type = FE_ATSC, - .frequency_min = 54000000, - .frequency_max = 860000000, - /* stepsize is just a guess */ - .frequency_stepsize = 166666, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256 - }, - - .release = nxt2002_release, - - .init = nxt2002_init, - .sleep = nxt2002_sleep, - - .set_frontend = nxt2002_setup_frontend_parameters, - .get_tune_settings = nxt2002_get_tune_settings, - - .read_status = nxt2002_read_status, - .read_ber = nxt2002_read_ber, - .read_signal_strength = nxt2002_read_signal_strength, - .read_snr = nxt2002_read_snr, - .read_ucblocks = nxt2002_read_ucblocks, - -}; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - -MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); -MODULE_AUTHOR("Taylor Jacob"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(nxt2002_attach); diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h deleted file mode 100644 index 462301f577ee..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Driver for the Nxt2002 demodulator -*/ - -#ifndef NXT2002_H -#define NXT2002_H - -#include <linux/dvb/frontend.h> -#include <linux/firmware.h> - -struct nxt2002_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* request firmware for device */ - int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); -}; - -extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, - struct i2c_adapter* i2c); - -#endif // NXT2002_H diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 78d2b93d35b9..9e3535394509 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -1,9 +1,10 @@ /* * Support for NXT2002 and NXT2004 - VSB/QAM * - * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) + * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com> + * Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net> * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net> - * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) + * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.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 @@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write sdm1 input */ buf[0] = 0x10; buf[1] = 0x00; - nxt200x_writebytes(state, 0x58, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x58, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x58, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write sdmx input */ switch (p->u.vsb.modulation) { @@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, break; } buf[1] = 0x00; - nxt200x_writebytes(state, 0x5C, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x5C, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x5C, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write adc power lpf fc */ buf[0] = 0x05; @@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; - nxt200x_writebytes(state, 0x4B, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write kg1 */ buf[0] = 0x00; @@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; - nxt200x_writebytes(state, 0x49, buf,2); - nxt200x_writebytes(state, 0x4B, buf,2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x49, buf, 2); + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x49, buf, 2); + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write agc control reg */ buf[0] = 0x04; @@ -1199,7 +1241,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); -MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob"); +MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(nxt200x_attach); diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c deleted file mode 100644 index d1cabb6a0a13..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * tda80xx.c - * - * Philips TDA8044 / TDA8083 QPSK demodulator driver - * - * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net> - * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/config.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/threads.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/irq.h> -#include <asm/div64.h> - -#include "dvb_frontend.h" -#include "tda80xx.h" - -enum { - ID_TDA8044 = 0x04, - ID_TDA8083 = 0x05, -}; - - -struct tda80xx_state { - - struct i2c_adapter* i2c; - - struct dvb_frontend_ops ops; - - /* configuration settings */ - const struct tda80xx_config* config; - - struct dvb_frontend frontend; - - u32 clk; - int afc_loop; - struct work_struct worklet; - fe_code_rate_t code_rate; - fe_spectral_inversion_t spectral_inversion; - fe_status_t status; - u8 id; -}; - -static int debug = 1; -#define dprintk if (debug) printk - -static u8 tda8044_inittab_pre[] = { - 0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, - 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58, - 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, - 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00, - 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -static u8 tda8044_inittab_post[] = { - 0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, - 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50, - 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, - 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c, - 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -static u8 tda8083_inittab[] = { - 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea, - 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10, - 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8, - 0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00, - 0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -static __inline__ u32 tda80xx_div(u32 a, u32 b) -{ - return (a + (b / 2)) / b; -} - -static __inline__ u32 tda80xx_gcd(u32 a, u32 b) -{ - u32 r; - - while ((r = a % b)) { - a = b; - b = r; - } - - return b; -} - -static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len) -{ - int ret; - struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; - - ret = i2c_transfer(state->i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (reg %02x, ret == %i)\n", - __FUNCTION__, reg, ret); - - mdelay(10); - - return (ret == 2) ? 0 : -EREMOTEIO; -} - -static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len) -{ - int ret; - u8 wbuf[len + 1]; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 }; - - wbuf[0] = reg; - memcpy(&wbuf[1], buf, len); - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret); - - mdelay(10); - - return (ret == 1) ? 0 : -EREMOTEIO; -} - -static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg) -{ - u8 val; - - tda80xx_read(state, reg, &val, 1); - - return val; -} - -static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data) -{ - return tda80xx_write(state, reg, &data, 1); -} - -static int tda80xx_set_parameters(struct tda80xx_state* state, - fe_spectral_inversion_t inversion, - u32 symbol_rate, - fe_code_rate_t fec_inner) -{ - u8 buf[15]; - u64 ratio; - u32 clk; - u32 k; - u32 sr = symbol_rate; - u32 gcd; - u8 scd; - - if (symbol_rate > (state->clk * 3) / 16) - scd = 0; - else if (symbol_rate > (state->clk * 3) / 32) - scd = 1; - else if (symbol_rate > (state->clk * 3) / 64) - scd = 2; - else - scd = 3; - - clk = scd ? (state->clk / (scd * 2)) : state->clk; - - /* - * Viterbi decoder: - * Differential decoding off - * Spectral inversion unknown - * QPSK modulation - */ - if (inversion == INVERSION_ON) - buf[0] = 0x60; - else if (inversion == INVERSION_OFF) - buf[0] = 0x20; - else - buf[0] = 0x00; - - /* - * CLK ratio: - * system clock frequency is up to 64 or 96 MHz - * - * formula: - * r = k * clk / symbol_rate - * - * k: 2^21 for caa 0..3, - * 2^20 for caa 4..5, - * 2^19 for caa 6..7 - */ - if (symbol_rate <= (clk * 3) / 32) - k = (1 << 19); - else if (symbol_rate <= (clk * 3) / 16) - k = (1 << 20); - else - k = (1 << 21); - - gcd = tda80xx_gcd(clk, sr); - clk /= gcd; - sr /= gcd; - - gcd = tda80xx_gcd(k, sr); - k /= gcd; - sr /= gcd; - - ratio = (u64)k * (u64)clk; - do_div(ratio, sr); - - buf[1] = ratio >> 16; - buf[2] = ratio >> 8; - buf[3] = ratio; - - /* nyquist filter roll-off factor 35% */ - buf[4] = 0x20; - - clk = scd ? (state->clk / (scd * 2)) : state->clk; - - /* Anti Alias Filter */ - if (symbol_rate < (clk * 3) / 64) - printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate); - else if (symbol_rate <= clk / 16) - buf[4] |= 0x07; - else if (symbol_rate <= (clk * 3) / 32) - buf[4] |= 0x06; - else if (symbol_rate <= clk / 8) - buf[4] |= 0x05; - else if (symbol_rate <= (clk * 3) / 16) - buf[4] |= 0x04; - else if (symbol_rate <= clk / 4) - buf[4] |= 0x03; - else if (symbol_rate <= (clk * 3) / 8) - buf[4] |= 0x02; - else if (symbol_rate <= clk / 2) - buf[4] |= 0x01; - else - buf[4] |= 0x00; - - /* Sigma Delta converter */ - buf[5] = 0x00; - - /* FEC: Possible puncturing rates */ - if (fec_inner == FEC_NONE) - buf[6] = 0x00; - else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9)) - buf[6] = (1 << (8 - fec_inner)); - else if (fec_inner == FEC_AUTO) - buf[6] = 0xff; - else - return -EINVAL; - - /* carrier lock detector threshold value */ - buf[7] = 0x30; - /* AFC1: proportional part settings */ - buf[8] = 0x42; - /* AFC1: integral part settings */ - buf[9] = 0x98; - /* PD: Leaky integrator SCPC mode */ - buf[10] = 0x28; - /* AFC2, AFC1 controls */ - buf[11] = 0x30; - /* PD: proportional part settings */ - buf[12] = 0x42; - /* PD: integral part settings */ - buf[13] = 0x99; - /* AGC */ - buf[14] = 0x50 | scd; - - printk("symbol_rate=%u clk=%u\n", symbol_rate, clk); - - return tda80xx_write(state, 0x01, buf, sizeof(buf)); -} - -static int tda80xx_set_clk(struct tda80xx_state* state) -{ - u8 buf[2]; - - /* CLK proportional part */ - buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */ - /* CLK integral part */ - buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */ - - return tda80xx_write(state, 0x17, buf, sizeof(buf)); -} - -#if 0 -static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state) -{ - /* a constant value is nonsense here imho */ - return tda80xx_writereg(state, 0x22, 0xf9); -} -#endif - -static int tda80xx_close_loop(struct tda80xx_state* state) -{ - u8 buf[2]; - - /* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */ - buf[0] = 0x68; - /* AFC1: Loop closed, CAR Feedback: 8192 */ - buf[1] = 0x70; - - return tda80xx_write(state, 0x0b, buf, sizeof(buf)); -} - -static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt) -{ - schedule_work(priv); - - return IRQ_HANDLED; -} - -static void tda80xx_read_status_int(struct tda80xx_state* state) -{ - u8 val; - - static const fe_spectral_inversion_t inv_tab[] = { - INVERSION_OFF, INVERSION_ON - }; - - static const fe_code_rate_t fec_tab[] = { - FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, - FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, - }; - - val = tda80xx_readreg(state, 0x02); - - state->status = 0; - - if (val & 0x01) /* demodulator lock */ - state->status |= FE_HAS_SIGNAL; - if (val & 0x02) /* clock recovery lock */ - state->status |= FE_HAS_CARRIER; - if (val & 0x04) /* viterbi lock */ - state->status |= FE_HAS_VITERBI; - if (val & 0x08) /* deinterleaver lock (packet sync) */ - state->status |= FE_HAS_SYNC; - if (val & 0x10) /* derandomizer lock (frame sync) */ - state->status |= FE_HAS_LOCK; - if (val & 0x20) /* frontend can not lock */ - state->status |= FE_TIMEDOUT; - - if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) { - printk("tda80xx: closing loop\n"); - tda80xx_close_loop(state); - state->afc_loop = 0; - } - - if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) { - val = tda80xx_readreg(state, 0x0e); - state->code_rate = fec_tab[val & 0x07]; - if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK)) - state->spectral_inversion = inv_tab[(val >> 7) & 0x01]; - else - state->spectral_inversion = INVERSION_AUTO; - } - else { - state->code_rate = FEC_AUTO; - } -} - -static void tda80xx_worklet(void *priv) -{ - struct tda80xx_state *state = priv; - - tda80xx_writereg(state, 0x00, 0x04); - enable_irq(state->config->irq); - - tda80xx_read_status_int(state); -} - -static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state) -{ - size_t i; - - for (i = 0; i < 100; i++) { - if (tda80xx_readreg(state, 0x02) & 0x80) - break; - msleep(10); - } -} - -static int tda8044_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - int ret; - - /* - * this function is a mess... - */ - - if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre)))) - return ret; - - tda80xx_writereg(state, 0x0f, 0x50); -#if 1 - tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */ - tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */ - //tda80xx_writereg(state, 0x00, 0x04); - tda80xx_writereg(state, 0x00, 0x0C); -#endif - //tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */ - - tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post)); - - if (state->config->pll_init) { - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_init(fe); - tda80xx_writereg(state, 0x1c, 0x00); - } - - return 0; -} - -static int tda8083_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab)); - - if (state->config->pll_init) { - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_init(fe); - tda80xx_writereg(state, 0x1c, 0x00); - } - - return 0; -} - -static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (voltage) { - case SEC_VOLTAGE_13: - return tda80xx_writereg(state, 0x20, state->config->volt13setting); - case SEC_VOLTAGE_18: - return tda80xx_writereg(state, 0x20, state->config->volt18setting); - case SEC_VOLTAGE_OFF: - return tda80xx_writereg(state, 0x20, 0); - default: - return -EINVAL; - } -} - -static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (tone) { - case SEC_TONE_OFF: - return tda80xx_writereg(state, 0x29, 0x00); - case SEC_TONE_ON: - return tda80xx_writereg(state, 0x29, 0x80); - default: - return -EINVAL; - } -} - -static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (cmd->msg_len > 6) - return -EINVAL; - - tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3)); - tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len); - tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3)); - tda80xx_wait_diseqc_fifo(state); - - return 0; -} - -static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (cmd) { - case SEC_MINI_A: - tda80xx_writereg(state, 0x29, 0x14); - break; - case SEC_MINI_B: - tda80xx_writereg(state, 0x29, 0x1c); - break; - default: - return -EINVAL; - } - - tda80xx_wait_diseqc_fifo(state); - - return 0; -} - -static int tda80xx_sleep(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_writereg(state, 0x00, 0x02); /* enter standby */ - - return 0; -} - -static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_set(fe, p); - tda80xx_writereg(state, 0x1c, 0x00); - - tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); - tda80xx_set_clk(state); - //tda80xx_set_scpc_freq_offset(state); - state->afc_loop = 1; - - return 0; -} - -static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (!state->config->irq) - tda80xx_read_status_int(state); - - p->inversion = state->spectral_inversion; - p->u.qpsk.fec_inner = state->code_rate; - - return 0; -} - -static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (!state->config->irq) - tda80xx_read_status_int(state); - *status = state->status; - - return 0; -} - -static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct tda80xx_state* state = fe->demodulator_priv; - int ret; - u8 buf[3]; - - if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf)))) - return ret; - - *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; - - return 0; -} - -static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - u8 gain = ~tda80xx_readreg(state, 0x01); - *strength = (gain << 8) | gain; - - return 0; -} - -static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - u8 quality = tda80xx_readreg(state, 0x08); - *snr = (quality << 8) | quality; - - return 0; -} - -static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - *ucblocks = tda80xx_readreg(state, 0x0f); - if (*ucblocks == 0xff) - *ucblocks = 0xffffffff; - - return 0; -} - -static int tda80xx_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch(state->id) { - case ID_TDA8044: - return tda8044_init(fe); - - case ID_TDA8083: - return tda8083_init(fe); - } - return 0; -} - -static void tda80xx_release(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (state->config->irq) - free_irq(state->config->irq, &state->worklet); - - kfree(state); -} - -static struct dvb_frontend_ops tda80xx_ops; - -struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, - struct i2c_adapter* i2c) -{ - struct tda80xx_state* state = NULL; - int ret; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops)); - state->spectral_inversion = INVERSION_AUTO; - state->code_rate = FEC_AUTO; - state->status = 0; - state->afc_loop = 0; - - /* check if the demod is there */ - if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error; - state->id = tda80xx_readreg(state, 0x00); - - switch (state->id) { - case ID_TDA8044: - state->clk = 96000000; - printk("tda80xx: Detected tda8044\n"); - break; - - case ID_TDA8083: - state->clk = 64000000; - printk("tda80xx: Detected tda8083\n"); - break; - - default: - goto error; - } - - /* setup IRQ */ - if (state->config->irq) { - INIT_WORK(&state->worklet, tda80xx_worklet, state); - if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) { - printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret); - goto error; - } - } - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops tda80xx_ops = { - - .info = { - .name = "Philips TDA80xx DVB-S", - .type = FE_QPSK, - .frequency_min = 500000, - .frequency_max = 2700000, - .frequency_stepsize = 125, - .symbol_rate_min = 4500000, - .symbol_rate_max = 45000000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | - FE_CAN_MUTE_TS - }, - - .release = tda80xx_release, - - .init = tda80xx_init, - .sleep = tda80xx_sleep, - - .set_frontend = tda80xx_set_frontend, - .get_frontend = tda80xx_get_frontend, - - .read_status = tda80xx_read_status, - .read_ber = tda80xx_read_ber, - .read_signal_strength = tda80xx_read_signal_strength, - .read_snr = tda80xx_read_snr, - .read_ucblocks = tda80xx_read_ucblocks, - - .diseqc_send_master_cmd = tda80xx_send_diseqc_msg, - .diseqc_send_burst = tda80xx_send_diseqc_burst, - .set_tone = tda80xx_set_tone, - .set_voltage = tda80xx_set_voltage, -}; - -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver"); -MODULE_AUTHOR("Felix Domke, Andreas Oberritter"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(tda80xx_attach); diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h deleted file mode 100644 index cd639a0aad55..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * tda80xx.c - * - * Philips TDA8044 / TDA8083 QPSK demodulator driver - * - * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net> - * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef TDA80XX_H -#define TDA80XX_H - -#include <linux/dvb/frontend.h> - -struct tda80xx_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* IRQ to use (0=>no IRQ used) */ - u32 irq; - - /* Register setting to use for 13v */ - u8 volt13setting; - - /* Register setting to use for 18v */ - u8 volt18setting; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); -}; - -extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, - struct i2c_adapter* i2c); - -#endif // TDA80XX_H diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 27494901975f..d36369e9e88f 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110) av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); break; + case 0x0004: // Galaxis DVB-S rev1.3 + /* ALPS BSRV2 */ + av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; + } + break; + case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ /* Grundig 29504-451 */ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); @@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE"); MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T"); MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6"); +MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3"); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), @@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), + MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004), MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006), MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008), MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e), MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), -/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 6ea30df2e823..fafd25fab835 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -273,8 +273,6 @@ struct av7110 { extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid); -extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config); - extern int av7110_ir_init(struct av7110 *av7110); extern void av7110_ir_exit(struct av7110 *av7110); diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 9138132ad25f..617e4f6c0ed7 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data) } +static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) +{ + int ret = 0; + + dprintk(4, "%p\n", av7110); + if (av7110) { + ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); + av7110->ir_config = ir_config; + } + return ret; +} + + static int av7110_ir_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) { @@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, } -int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) -{ - int ret = 0; - - dprintk(4, "%p\n", av7110); - if (av7110) { - ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); - av7110->ir_config = ir_config; - } - return ret; -} - - static void ir_handler(struct av7110 *av7110, u32 ircom) { dprintk(4, "ircommand = %08x\n", ircom); diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index aa4c4c521880..578b20085082 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { we can capture, of the first and second field. */ .vbistart = { 7,320 }, },{ - .v4l2_id = V4L2_STD_NTSC_M, + .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC", .Fsc = 28636363, .swidth = 768, diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index 297c32ab51e3..840fe0177121 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c @@ -167,29 +167,32 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user if (kp->clipcount > 2048) return -EINVAL; if (kp->clipcount) { - struct v4l2_clip32 *uclips = compat_ptr(up->clips); - struct v4l2_clip *kclips; + struct v4l2_clip32 __user *uclips; + struct v4l2_clip __user *kclips; int n = kp->clipcount; + compat_caddr_t p; + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); kp->clips = kclips; while (--n >= 0) { - if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) || - copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c))) + if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) + return -EFAULT; + if (put_user(n ? kclips + 1 : NULL, &kclips->next)) return -EFAULT; - kclips->next = n ? kclips + 1 : 0; uclips += 1; kclips += 1; } } else - kp->clips = 0; + kp->clips = NULL; return 0; } static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) || - copy_to_user(&up->w, &kp->w, sizeof(up->w)) || + if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || put_user(kp->clipcount, &up->clipcount)) @@ -199,33 +202,29 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) || - copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) + return -EFAULT; return 0; } static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) || - copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) + return -EFAULT; return 0; } static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) || - copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) + return -EFAULT; return 0; } static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) || - copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) + return -EFAULT; return 0; } @@ -279,18 +278,16 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) || - copy_from_user(kp, up, sizeof(struct v4l2_standard))) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) + return -EFAULT; return 0; } static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) || - copy_to_user(up, kp, sizeof(struct v4l2_standard))) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) + return -EFAULT; return 0; } @@ -328,18 +325,16 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) || - copy_from_user(kp, up, sizeof(struct v4l2_tuner))) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) + return -EFAULT; return 0; } static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) || - copy_to_user(up, kp, sizeof(struct v4l2_tuner))) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) + return -EFAULT; return 0; } @@ -380,11 +375,13 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user break; case V4L2_MEMORY_USERPTR: { - unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); + compat_long_t tmp; - if(get_user(kp->length, &up->length) || - get_user(kp->m.userptr, &tmp)) - return -EFAULT; + if (get_user(kp->length, &up->length) || + get_user(tmp, &up->m.userptr)) + return -EFAULT; + + kp->m.userptr = (unsigned long)compat_ptr(tmp); } break; case V4L2_MEMORY_OVERLAY: @@ -468,33 +465,29 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) || - copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) + return -EFAULT; return 0; } static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) || - copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) + return -EFAULT; return 0; } static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) || - copy_from_user(kp, up, sizeof(struct v4l2_input))) - return -EFAULT; + if (copy_from_user(kp, up, sizeof(struct v4l2_input))) + return -EFAULT; return 0; } static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) || - copy_to_user(up, kp, sizeof(struct v4l2_input))) - return -EFAULT; + if (copy_to_user(up, kp, sizeof(struct v4l2_input))) + return -EFAULT; return 0; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index c66c2c1f4809..08ffd1f325fc 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client) cx25840_write(client, 0x808, 0xff); cx25840_write(client, 0x80b, 0x10); } else if (std & V4L2_STD_NTSC) { - /* NTSC */ - if (state->pvr150_workaround) { - /* Certain Hauppauge PVR150 models have a hardware bug - that causes audio to drop out. For these models the - audio standard must be set explicitly. - To be precise: it affects cards with tuner models - 85, 99 and 112 (model numbers from tveeprom). */ - if (std == V4L2_STD_NTSC_M_JP) { - /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0x2f); - } else { - /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0x1f); - } - /* South Korea uses the A2-M (aka Zweiton M) audio - standard, and should set 0x808 to 0x3f, but I don't - know how to detect this. */ - } else if (std == V4L2_STD_NTSC_M_JP) { + /* Certain Hauppauge PVR150 models have a hardware bug + that causes audio to drop out. For these models the + audio standard must be set explicitly. + To be precise: it affects cards with tuner models + 85, 99 and 112 (model numbers from tveeprom). */ + int hw_fix = state->pvr150_workaround; + + if (std == V4L2_STD_NTSC_M_JP) { /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0xf7); + cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7); + } else if (std == V4L2_STD_NTSC_M_KR) { + /* South Korea uses A2 audio standard */ + cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8); } else { /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0xf6); + cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); } - /* South Korea uses the A2-M (aka Zweiton M) audio standard, - and should set 0x808 to 0xf8, but I don't know how to - detect this. */ cx25840_write(client, 0x80b, 0x00); } @@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) u8 fmt=0; /* zero is autodetect */ /* First tests should be against specific std */ - if (std & V4L2_STD_NTSC_M_JP) { + if (std == V4L2_STD_NTSC_M_JP) { fmt=0x2; - } else if (std & V4L2_STD_NTSC_443) { + } else if (std == V4L2_STD_NTSC_443) { fmt=0x3; - } else if (std & V4L2_STD_PAL_M) { + } else if (std == V4L2_STD_PAL_M) { fmt=0x5; - } else if (std & V4L2_STD_PAL_N) { + } else if (std == V4L2_STD_PAL_N) { fmt=0x6; - } else if (std & V4L2_STD_PAL_Nc) { + } else if (std == V4L2_STD_PAL_Nc) { fmt=0x7; - } else if (std & V4L2_STD_PAL_60) { + } else if (std == V4L2_STD_PAL_60) { fmt=0x8; } else { /* Then, test against generic ones */ @@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) } switch (fmt) { - case 0x1: return V4L2_STD_NTSC_M; + case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 53308911ae6e..e99dfbbf3e95 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -32,6 +32,7 @@ config VIDEO_CX88_DVB config VIDEO_CX88_ALSA tristate "ALSA DMA audio support" depends on VIDEO_CX88 && SND && EXPERIMENTAL + select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on Conexant 2388x based TV cards. @@ -48,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS default y depends on VIDEO_CX88_DVB select DVB_MT352 + select VIDEO_CX88_VP3054 select DVB_OR51132 select DVB_CX22702 select DVB_LGDT330X @@ -69,6 +71,16 @@ config VIDEO_CX88_DVB_MT352 This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator. +config VIDEO_CX88_VP3054 + tristate "VP-3054 Secondary I2C Bus Support" + default m + depends on DVB_MT352 + ---help--- + This adds DVB-T support for cards based on the + Connexant 2388x chip and the MT352 demodulator, + which also require support for the VP-3054 + Secondary I2C bus, such at DNTV Live! DVB-T Pro. + config VIDEO_CX88_DVB_OR51132 bool "OR51132 ATSC Support" default y diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 6e5eaa22619e..2b902784facc 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o cx8802-objs := cx88-mpeg.o obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o -obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o +obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o +obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core @@ -18,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 -extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 +extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index a2e36a1e5f59..2acccd6d49bc 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); * BOARD Specific: Sets audio DMA */ -int _cx88_start_audio_dma(snd_cx88_card_t *chip) +static int _cx88_start_audio_dma(snd_cx88_card_t *chip) { struct cx88_buffer *buf = chip->buf; struct cx88_core *core=chip->core; @@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip) /* * BOARD Specific: Resets audio DMA */ -int _cx88_stop_audio_dma(snd_cx88_card_t *chip) +static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) { struct cx88_core *core=chip->core; dprintk(1, "Stopping audio DMA\n"); @@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -struct pci_device_id cx88_audio_pci_tbl[] = { +static struct pci_device_id cx88_audio_pci_tbl[] = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index ad2f565f522c..1bc999247fdc 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1246,6 +1246,11 @@ struct cx88_subid cx88_subids[] = { .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, },{ .subvendor = 0x18ac, + .subdevice = 0xdb54, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, + /* Re-branded DViCO: DigitalNow DVB-T Dual */ + },{ + .subvendor = 0x18ac, .subdevice = 0xdb11, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, /* Re-branded DViCO: UltraView DVB-T Plus */ @@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) switch (tv.model) { case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ + case 34519: /* WinTV-PCI-FM */ case 90002: /* Nova-T-PCI (9002) */ case 92001: /* Nova-S-Plus (Video and IR) */ case 92002: /* Nova-S-Plus (Video and IR) */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8d6d6a6cf785..3720f24a25cf 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) int cx88_start_audio_dma(struct cx88_core *core) { + /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */ + int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4; /* setup fifo + format */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0); - cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */ - cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */ + cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */ + cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */ /* start dma */ cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index da2ad5c4b553..165d948624a3 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) switch (core->board) { case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: + case CX88_BOARD_KWORLD_DVB_T_CX22702: ir_codes = ir_codes_dntv_live_dvb_t; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index dff3893f32fd..e5ee8bceb210 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, { int ret, byte; + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + em28xx_regdbg("req=%02x, reg=%02x ", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, @@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) u8 val; int ret; + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + em28xx_regdbg("req=%02x, reg=%02x:", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, @@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int ret; /*usb_control_msg seems to expect a kmalloced buffer */ - unsigned char *bufs = kmalloc(len, GFP_KERNEL); + unsigned char *bufs; + + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + + bufs = kmalloc(len, GFP_KERNEL); em28xx_regdbg("req=%02x reg=%02x:", req, reg); @@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, bufs, len, HZ); - mdelay(5); /* FIXME: magic number */ + msleep(5); /* FIXME: magic number */ kfree(bufs); return ret; } @@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) return ret; else if (((u8) ret) & 0x01) { - em28xx_warn ("AC97 command still being exectuted: not handled properly!\n"); + em28xx_warn ("AC97 command still being executed: not handled properly!\n"); } return 0; } diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 0591a705b7a1..6ca8631bc36d 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ret = dev->em28xx_read_reg(dev, 0x05); if (ret == 0x80 + len - 1) return len; - mdelay(5); + msleep(5); } em28xx_warn("i2c write timed out\n"); return -EIO; @@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) return -ENODEV; else if (msg == 0x84) return 0; - mdelay(5); + msleep(5); } return -ENODEV; } @@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf, msgs[i].len, i == num - 1); - if (rc < 0) - goto err; } + if (rc < 0) + goto err; if (i2c_debug>=2) printk("\n"); } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index eea304f75176..94a14a2bb6d6 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -6,6 +6,9 @@ Mauro Carvalho Chehab <mchehab@brturbo.com.br> Sascha Sommer <saschasommer@freenet.de> + Some parts based on SN9C10x PC Camera Controllers GPL driver made + by Luca Risolia <luca.risolia@studio.unibo.it> + 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 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 0b6c2096ec66..aad4a18aafd6 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -484,7 +484,7 @@ static struct saa7146_ext_vv vv_data = { }; static struct saa7146_extension extension = { - .name = "hexium HV-PCI6/Orion", + .name = "hexium HV-PCI6 Orion", .flags = 0, // SAA7146_USE_I2C_IRQ, .pci_tbl = &pci_tbl[0], diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c64718aec9cb..5a35d3b6550d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_FLYVIDEO2000] = { /* "TC Wan" <tcwan@cs.usm.my> */ - .name = "LifeView FlyVIDEO2000", + .name = "LifeView/Typhoon FlyVIDEO2000", .audio_clock = 0x00200000, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .radio_type = UNSET, @@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x000, }, }, - [SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = { - .name = "Typhoon DVB-T Duo Digital/Analog Cardbus", + [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = { + .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, - /* .gpiomask = 0xe000, */ + .gpiomask = 0x00200000, .inputs = {{ .name = name_tv, .vmux = 1, .amux = TV, - /* .gpio = 0x0000, */ + .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, },{ + .name = name_svideo, /* S-Video signal on S-Video input */ + .vmux = 8, + .amux = LINE2, + },{ .name = name_comp1, /* Composite signal on S-Video input */ .vmux = 0, .amux = LINE2, - /* .gpio = 0x4000, */ },{ .name = name_comp2, /* Composite input */ .vmux = 3, .amux = LINE2, - /* .gpio = 0x4000, */ - },{ - .name = name_svideo, /* S-Video signal on S-Video input */ - .vmux = 8, - .amux = LINE2, - /* .gpio = 0x4000, */ }}, .radio = { .name = name_radio, - .amux = LINE2, - }, - .mute = { - .name = name_mute, - .amux = LINE1, + .amux = TV, + .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, }, [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = { @@ -2701,6 +2695,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_FLYVIDEO2000, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x4e42, /* Typhoon */ + .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ + .driver_data = SAA7134_BOARD_FLYVIDEO2000, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, .subdevice = 0x0212, /* minipci, LR212 */ @@ -2935,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, .subdevice = 0x0502, /* Cardbus version */ - .driver_data = SAA7134_BOARD_FLYDVBTDUO, + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -2980,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x1370, /* cardbus version */ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4e42, - .subdevice = 0x0502, - .driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS, + .subvendor = 0x4e42, /* Typhoon */ + .subdevice = 0x0502, /* LifeView LR502 OEM */ + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -3206,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); break; - case SAA7134_BOARD_FLYDVBTDUO: - case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: + case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: /* turn the fan on */ saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 399f9952596c..1a536e865277 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; - case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: + case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e70eae8d29bb..3261d8bebdd1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -185,7 +185,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 #define SAA7134_BOARD_ADS_INSTANT_TV 58 #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 -#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60 +#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60 #define SAA7134_BOARD_PHILIPS_TOUGH 61 #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62 #define SAA7134_BOARD_KWORLD_XPERT 63 diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 54fc33011ffb..9d769264a329 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev) { struct saa7146 *saa = pci_get_drvdata(pdev); - memset(saa, 0, sizeof(*saa)); saa->user = 0; /* reset the saa7146 */ saawrite(0xffff0000, SAA7146_MC1); @@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev) } if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto errvid; + goto errfree; } if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto erraud; + goto errfree; } /* allocate 81920 byte buffer for clipping */ if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); - goto errosd; + goto errfree; } /* setup clipping registers */ saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); @@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev) I2CBusScan(saa); return 0; -errosd: +errfree: vfree(saa->osdbuf); - saa->osdbuf = NULL; -erraud: vfree(saa->audbuf); - saa->audbuf = NULL; -errvid: vfree(saa->vidbuf); - saa->vidbuf = NULL; + saa->audbuf = saa->osdbuf = saa->vidbuf = NULL; err: return -ENOMEM; } diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 5815649bdc78..0d54f6c1982b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = { cAudioIF_6_5 | cVideoIF_38_90 ), },{ - .std = V4L2_STD_NTSC_M, + .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC-M", .b = ( cNegativeFmTV | cQSS ), @@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t) tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; @@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev) /* ----------------------------------------------------------------------- */ static struct i2c_driver driver = { - .id = -1, /* FIXME */ + .id = I2C_DRIVERID_TDA9887, .attach_adapter = tda9887_probe, .detach_client = tda9887_detach, .command = tda9887_command, diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 2995b22acb43..e7ee619d62c5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[3] = 0xa4; i2c_master_send(c,buffer,4); default_tuner_init(c); + break; default: default_tuner_init(c); break; @@ -365,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t) tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; @@ -448,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) printk("%02x ",buffer[i]); printk("\n"); } - /* TEA5767 autodetection code - only for addr = 0xc0 */ + /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { case 0x42: diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 6d03b9b05c6e..c8e5ad0e8185 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9840_SW, t); } +static int tda9840_checkit(struct CHIPSTATE *chip) +{ + int rc; + rc = chip_read(chip); + /* lower 5 bits should be 0 */ + return ((rc & 0x1f) == 0) ? 1 : 0; +} + /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tda985x */ @@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = { .addr_hi = I2C_TDA9840 >> 1, .registers = 5, + .checkit = tda9840_checkit, .getmode = tda9840_getmode, .setmode = tda9840_setmode, .checkmode = generic_checkmode, diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index fad9ea0ae4f2..1864423b3046 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) static inline void tvp5150_reset(struct i2c_client *c) { - u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom; + u8 msb_id, lsb_id, msb_rom, lsb_rom; struct tvp5150 *decoder = i2c_get_clientdata(c); - type=tvp5150_read(c,TVP5150_AUTOSW_MSK); msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); - if (type==0xdc) { - ver_656=tvp5150_read(c,TVP5150_REV_SELECT); - tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656); - } else if (type==0xfc) { - tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */ + tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id); + + /* ITU-T BT.656.4 timing */ + tvp5150_write(c,TVP5150_REV_SELECT,0); } else { - tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type); + if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */ + tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + } else { + tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id); + tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom); + } } - tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom); /* Initializes TVP5150 to its default values */ tvp5150_write_inittab(c, tvp5150_init_default); @@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c, } case DECODER_GET_STATUS: { + int *iarg = arg; + int status; + int res=0; + status = tvp5150_read(c, 0x88); + if(status&0x08){ + res |= DECODER_STATUS_COLOR; + } + if(status&0x04 && status&0x02){ + res |= DECODER_STATUS_GOOD; + } + *iarg=res; break; } diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 8a2e2657f4c2..33ace373241c 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -29,6 +29,8 @@ # For mptctl: #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL # +# For mptfc: +#CFLAGS_mptfc.o += -DMPT_DEBUG_FC #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index d890b2b8a93e..9a2c7605d49c 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -81,6 +81,10 @@ MODULE_LICENSE("GPL"); /* * cmd line parameters */ +static int mpt_msi_enable; +module_param(mpt_msi_enable, int, 0); +MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); + #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT 20000 @@ -174,7 +178,7 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); -static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); +static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); /* module entry point */ @@ -313,7 +317,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) if (ioc->bus_type == FC) mpt_fc_log_info(ioc, log_info); else if (ioc->bus_type == SPI) - mpt_sp_log_info(ioc, log_info); + mpt_spi_log_info(ioc, log_info); else if (ioc->bus_type == SAS) mpt_sas_log_info(ioc, log_info); } @@ -1444,6 +1448,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pci_irq = -1; if (pdev->irq) { + if (mpt_msi_enable && !pci_enable_msi(pdev)) + printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name); + r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); if (r < 0) { @@ -1483,6 +1490,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) list_del(&ioc->list); free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(pdev); + if (ioc->alt_ioc) + ioc->alt_ioc->alt_ioc = NULL; iounmap(mem); kfree(ioc); pci_set_drvdata(pdev, NULL); @@ -2136,6 +2147,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) if (ioc->pci_irq != -1) { free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); ioc->pci_irq = -1; } @@ -2157,6 +2170,10 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) sz_last = ioc->alloc_total; dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); + + if (ioc->alt_ioc) + ioc->alt_ioc->alt_ioc = NULL; + kfree(ioc); } @@ -2770,13 +2787,16 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* RAID FW may take a long time to enable */ - if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { - rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); + if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || + (ioc->bus_type == SAS)) { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, + (u32*)&port_enable, reply_sz, (u16*)&reply_buf, + 300 /*seconds*/, sleepFlag); } else { - rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); + rc = mpt_handshake_req_reply_wait(ioc, req_sz, + (u32*)&port_enable, reply_sz, (u16*)&reply_buf, + 30 /*seconds*/, sleepFlag); } return rc; } @@ -4387,6 +4407,138 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +static void +mptbase_raid_process_event_data(MPT_ADAPTER *ioc, + MpiEventDataRaid_t * pRaidEventData) +{ + int volume; + int reason; + int disk; + int status; + int flags; + int state; + + volume = pRaidEventData->VolumeID; + reason = pRaidEventData->ReasonCode; + disk = pRaidEventData->PhysDiskNum; + status = le32_to_cpu(pRaidEventData->SettingsStatus); + flags = (status >> 0) & 0xff; + state = (status >> 8) & 0xff; + + if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { + return; + } + + if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && + reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || + (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", + ioc->name, disk); + } else { + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", + ioc->name, volume); + } + + switch(reason) { + case MPI_EVENT_RAID_RC_VOLUME_CREATED: + printk(MYIOC_s_INFO_FMT " volume has been created\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_DELETED: + + printk(MYIOC_s_INFO_FMT " volume has been deleted\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED: + printk(MYIOC_s_INFO_FMT " volume settings have been changed\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: + printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n", + ioc->name, + state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL + ? "optimal" + : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED + ? "degraded" + : state == MPI_RAIDVOL0_STATUS_STATE_FAILED + ? "failed" + : "state unknown", + flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED + ? ", enabled" : "", + flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED + ? ", quiesced" : "", + flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS + ? ", resync in progress" : "" ); + break; + + case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED: + printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n", + ioc->name, disk); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: + printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n", + ioc->name); + break; + + case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: + printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n", + ioc->name, + state == MPI_PHYSDISK0_STATUS_ONLINE + ? "online" + : state == MPI_PHYSDISK0_STATUS_MISSING + ? "missing" + : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE + ? "not compatible" + : state == MPI_PHYSDISK0_STATUS_FAILED + ? "failed" + : state == MPI_PHYSDISK0_STATUS_INITIALIZING + ? "initializing" + : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED + ? "offline requested" + : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED + ? "failed requested" + : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE + ? "offline" + : "state unknown", + flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC + ? ", out of sync" : "", + flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED + ? ", quiesced" : "" ); + break; + + case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED: + printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n", + ioc->name, disk); + break; + + case MPI_EVENT_RAID_RC_SMART_DATA: + printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n", + ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ); + break; + + case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: + printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n", + ioc->name, disk); + break; + } +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure @@ -4598,6 +4750,14 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; MpiDeviceInfo_t *pdevice = NULL; + /* + * Save "Set to Avoid SCSI Bus Resets" flag + */ + ioc->spi_data.bus_reset = + (le32_to_cpu(pPP2->PortFlags) & + MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ? + 0 : 1 ; + /* Save the Port Page 2 data * (reformat into a 32bit quantity) */ @@ -5967,6 +6127,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } } break; + case MPI_EVENT_INTEGRATED_RAID: + mptbase_raid_process_event_data(ioc, + (MpiEventDataRaid_t *)pEventReply->Data); + break; default: break; } @@ -6046,7 +6210,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mpt_sp_log_info - Log information returned from SCSI Parallel IOC. + * mpt_spi_log_info - Log information returned from SCSI Parallel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @mr: Pointer to MPT reply frame * @log_info: U32 LogInfo word from the IOC @@ -6054,7 +6218,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) * Refer to lsi/sp_log.h. */ static void -mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) +mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) { u32 info = log_info & 0x00FF0000; char *desc = "unknown"; diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 47053ac65068..ea2649ecad1f 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.06" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06" +#define MPT_LINUX_VERSION_COMMON "3.03.07" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -123,7 +123,7 @@ #define MPT_MAX_FRAME_SIZE 128 #define MPT_DEFAULT_FRAME_SIZE 128 -#define MPT_REPLY_FRAME_SIZE 0x40 /* Must be a multiple of 8 */ +#define MPT_REPLY_FRAME_SIZE 0x50 /* Must be a multiple of 8 */ #define MPT_SG_REQ_128_SCALE 1 #define MPT_SG_REQ_96_SCALE 2 @@ -510,9 +510,10 @@ struct mptfc_rport_info { struct list_head list; struct fc_rport *rport; - VirtDevice *vdev; + struct scsi_target *starget; FCDevicePage0_t pg0; u8 flags; + u8 remap_needed; }; /* @@ -631,6 +632,7 @@ typedef struct _MPT_ADAPTER struct mutex sas_topology_mutex; MPT_SAS_MGMT sas_mgmt; int num_ports; + struct work_struct mptscsih_persistTask; struct list_head fc_rports; spinlock_t fc_rport_lock; /* list and ri flags */ @@ -803,6 +805,12 @@ typedef struct _mpt_sge { #define dreplyprintk(x) #endif +#ifdef DMPT_DEBUG_FC +#define dfcprintk(x) printk x +#else +#define dfcprintk(x) +#endif + #ifdef MPT_DEBUG_TM #define dtmprintk(x) printk x #define DBG_DUMP_TM_REQUEST_FRAME(mfp) \ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index b102c7666d0e..c3a3499bce2a 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -93,10 +93,11 @@ static int mptfcDoneCtx = -1; static int mptfcTaskCtx = -1; static int mptfcInternalCtx = -1; /* Used only for internal commands */ -int mptfc_slave_alloc(struct scsi_device *device); +static int mptfc_target_alloc(struct scsi_target *starget); +static int mptfc_slave_alloc(struct scsi_device *sdev); static int mptfc_qcmd(struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)); - + void (*done)(struct scsi_cmnd *)); +static void mptfc_target_destroy(struct scsi_target *starget); static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); static void __devexit mptfc_remove(struct pci_dev *pdev); @@ -107,10 +108,10 @@ static struct scsi_host_template mptfc_driver_template = { .name = "MPT FC Host", .info = mptscsih_info, .queuecommand = mptfc_qcmd, - .target_alloc = mptscsih_target_alloc, + .target_alloc = mptfc_target_alloc, .slave_alloc = mptfc_slave_alloc, .slave_configure = mptscsih_slave_configure, - .target_destroy = mptscsih_target_destroy, + .target_destroy = mptfc_target_destroy, .slave_destroy = mptscsih_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, @@ -348,14 +349,33 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) } static void +mptfc_remap_sdev(struct scsi_device *sdev, void *arg) +{ + VirtDevice *vdev; + VirtTarget *vtarget; + struct scsi_target *starget; + + starget = scsi_target(sdev); + if (starget->hostdata == arg) { + vtarget = arg; + vdev = sdev->hostdata; + if (vdev) { + vdev->bus_id = vtarget->bus_id; + vdev->target_id = vtarget->target_id; + } + } +} + +static void mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) { struct fc_rport_identifiers rport_ids; struct fc_rport *rport; struct mptfc_rport_info *ri; - int match = 0; - u64 port_name; + int new_ri = 1; + u64 pn; unsigned long flags; + VirtTarget *vtarget; if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) return; @@ -363,14 +383,14 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) /* scan list looking for a match */ spin_lock_irqsave(&ioc->fc_rport_lock, flags); list_for_each_entry(ri, &ioc->fc_rports, list) { - port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; - if (port_name == rport_ids.port_name) { /* match */ + pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; + if (pn == rport_ids.port_name) { /* match */ list_move_tail(&ri->list, &ioc->fc_rports); - match = 1; + new_ri = 0; break; } } - if (!match) { /* allocate one */ + if (new_ri) { /* allocate one */ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); if (!ri) @@ -382,40 +402,43 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) ri->pg0 = *pg0; /* add/update pg0 data */ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; + /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */ if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); - rport = fc_remote_port_add(ioc->sh,channel, &rport_ids); + rport = fc_remote_port_add(ioc->sh, channel, &rport_ids); spin_lock_irqsave(&ioc->fc_rport_lock, flags); if (rport) { - if (*((struct mptfc_rport_info **)rport->dd_data) != ri) { - ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; - ri->vdev = NULL; - ri->rport = rport; - *((struct mptfc_rport_info **)rport->dd_data) = ri; - } - rport->dev_loss_tmo = mptfc_dev_loss_tmo; + ri->rport = rport; + if (new_ri) /* may have been reset by user */ + rport->dev_loss_tmo = mptfc_dev_loss_tmo; + *((struct mptfc_rport_info **)rport->dd_data) = ri; /* * if already mapped, remap here. If not mapped, - * slave_alloc will allocate vdev and map + * target_alloc will allocate vtarget and map, + * slave_alloc will fill in vdev from vtarget. */ - if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) { - ri->vdev->target_id = ri->pg0.CurrentTargetID; - ri->vdev->bus_id = ri->pg0.CurrentBus; - ri->vdev->vtarget->target_id = ri->vdev->target_id; - ri->vdev->vtarget->bus_id = ri->vdev->bus_id; + if (ri->starget) { + vtarget = ri->starget->hostdata; + if (vtarget) { + vtarget->target_id = pg0->CurrentTargetID; + vtarget->bus_id = pg0->CurrentBus; + starget_for_each_device(ri->starget, + vtarget,mptfc_remap_sdev); + } + ri->remap_needed = 0; } - #ifdef MPT_DEBUG - printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " "rport tid %d, tmo %d\n", - ioc->sh->host_no, + ioc->name, + oc->sh->host_no, pg0->PortIdentifier, pg0->WWNN, pg0->WWPN, pg0->CurrentTargetID, ri->rport->scsi_target_id, - ri->rport->dev_loss_tmo); - #endif + ri->rport->dev_loss_tmo)); } else { list_del(&ri->list); kfree(ri); @@ -427,6 +450,65 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) } /* + * OS entry point to allow for host driver to free allocated memory + * Called if no device present or device being unloaded + */ +static void +mptfc_target_destroy(struct scsi_target *starget) +{ + struct fc_rport *rport; + struct mptfc_rport_info *ri; + + rport = starget_to_rport(starget); + if (rport) { + ri = *((struct mptfc_rport_info **)rport->dd_data); + if (ri) /* better be! */ + ri->starget = NULL; + } + if (starget->hostdata) + kfree(starget->hostdata); + starget->hostdata = NULL; +} + +/* + * OS entry point to allow host driver to alloc memory + * for each scsi target. Called once per device the bus scan. + * Return non-zero if allocation fails. + */ +static int +mptfc_target_alloc(struct scsi_target *starget) +{ + VirtTarget *vtarget; + struct fc_rport *rport; + struct mptfc_rport_info *ri; + int rc; + + vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); + if (!vtarget) + return -ENOMEM; + starget->hostdata = vtarget; + + rc = -ENODEV; + rport = starget_to_rport(starget); + if (rport) { + ri = *((struct mptfc_rport_info **)rport->dd_data); + if (ri) { /* better be! */ + vtarget->target_id = ri->pg0.CurrentTargetID; + vtarget->bus_id = ri->pg0.CurrentBus; + ri->starget = starget; + ri->remap_needed = 0; + rc = 0; + } + } + if (rc != 0) { + kfree(vtarget); + starget->hostdata = NULL; + } + + return rc; +} + +/* * OS entry point to allow host driver to alloc memory * for each scsi device. Called once per device the bus scan. * Return non-zero if allocation fails. @@ -440,7 +522,6 @@ mptfc_slave_alloc(struct scsi_device *sdev) VirtDevice *vdev; struct scsi_target *starget; struct fc_rport *rport; - struct mptfc_rport_info *ri; unsigned long flags; @@ -451,55 +532,44 @@ mptfc_slave_alloc(struct scsi_device *sdev) hd = (MPT_SCSI_HOST *)sdev->host->hostdata; - vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - memset(vdev, 0, sizeof(VirtDevice)); spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); - if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) { - spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); - kfree(vdev); - return -ENODEV; - } - sdev->hostdata = vdev; starget = scsi_target(sdev); vtarget = starget->hostdata; + if (vtarget->num_luns == 0) { + vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | MPT_TARGET_FLAGS_VALID_INQUIRY; hd->Targets[sdev->id] = vtarget; } - vtarget->target_id = vdev->target_id; - vtarget->bus_id = vdev->bus_id; - vdev->vtarget = vtarget; vdev->ioc_id = hd->ioc->id; vdev->lun = sdev->lun; - vdev->target_id = ri->pg0.CurrentTargetID; - vdev->bus_id = ri->pg0.CurrentBus; - - ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; - ri->vdev = vdev; + vdev->target_id = vtarget->target_id; + vdev->bus_id = vtarget->bus_id; spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); vtarget->num_luns++; -#ifdef MPT_DEBUG - printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " "CurrentTargetID %d, %x %llx %llx\n", - sdev->host->host_no, - vtarget->num_luns, - sdev->id, ri->pg0.CurrentTargetID, - ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN); -#endif + ioc->name, + sdev->host->host_no, + vtarget->num_luns, + sdev->id, ri->pg0.CurrentTargetID, + ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); return 0; } @@ -507,6 +577,7 @@ mptfc_slave_alloc(struct scsi_device *sdev) static int mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { + struct mptfc_rport_info *ri; struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); int err; @@ -516,6 +587,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) done(SCpnt); return 0; } + ri = *((struct mptfc_rport_info **)rport->dd_data); + if (unlikely(ri->remap_needed)) + return SCSI_MLQUEUE_HOST_BUSY; + return mptscsih_qcmd(SCpnt,done); } @@ -591,16 +666,20 @@ mptfc_rescan_devices(void *arg) ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| MPT_RPORT_INFO_FLAGS_MISSING); + ri->remap_needed = 1; fc_remote_port_delete(ri->rport); /* * remote port not really deleted 'cause * binding is by WWPN and driver only - * registers FCP_TARGETs + * registers FCP_TARGETs but cannot trust + * data structures. */ - #ifdef MPT_DEBUG - printk ("mptfc_rescan.%d: %llx deleted\n", - ioc->sh->host_no, ri->pg0.WWPN); - #endif + ri->rport = NULL; + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_rescan.%d: %llx deleted\n", + ioc->name, + ioc->sh->host_no, + ri->pg0.WWPN)); } } spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); @@ -872,9 +951,8 @@ mptfc_init(void) } error = pci_register_driver(&mptfc_driver); - if (error) { + if (error) fc_release_transport(mptfc_transport_template); - } return error; } @@ -885,7 +963,8 @@ mptfc_init(void) * @pdev: Pointer to pci_dev structure * */ -static void __devexit mptfc_remove(struct pci_dev *pdev) +static void __devexit +mptfc_remove(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct mptfc_rport_info *p, *n; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 5a06d8d8694e..2512d0e6155e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1; enum mptsas_hotplug_action { MPTSAS_ADD_DEVICE, MPTSAS_DEL_DEVICE, + MPTSAS_ADD_RAID, + MPTSAS_DEL_RAID, }; struct mptsas_hotplug_event { @@ -114,6 +116,7 @@ struct mptsas_hotplug_event { struct mptsas_devinfo { u16 handle; /* unique id to address this device */ + u16 handle_parent; /* unique id to address parent device */ u8 phy_id; /* phy number of parent device */ u8 port_id; /* sas physical port this device is assoc'd with */ @@ -301,9 +304,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) } mutex_unlock(&hd->ioc->sas_topology_mutex); - printk("No matching SAS device found!!\n"); kfree(vdev); - return -ENODEV; + return -ENXIO; out: vtarget->ioc_id = vdev->ioc_id; @@ -321,6 +323,7 @@ mptsas_slave_destroy(struct scsi_device *sdev) struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; + VirtDevice *vdev; /* * Handle hotplug removal case. @@ -344,8 +347,29 @@ mptsas_slave_destroy(struct scsi_device *sdev) out: mutex_unlock(&hd->ioc->sas_topology_mutex); /* - * TODO: Issue target reset to flush firmware outstanding commands. + * Issue target reset to flush firmware outstanding commands. */ + vdev = sdev->hostdata; + if (vdev->configured_lun){ + if (mptscsih_TMHandler(hd, + MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + vdev->bus_id, + vdev->target_id, + 0, 0, 5 /* 5 second timeout */) + < 0){ + + /* The TM request failed! + * Fatal error case. + */ + printk(MYIOC_s_WARN_FMT + "Error processing TaskMgmt id=%d TARGET_RESET\n", + hd->ioc->name, + vdev->target_id); + + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + } + } mptscsih_slave_destroy(sdev); } @@ -714,6 +738,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, mptsas_print_device_pg0(buffer); device_info->handle = le16_to_cpu(buffer->DevHandle); + device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; device_info->id = buffer->TargetID; @@ -863,6 +888,26 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, return error; } +/* + * Returns true if there is a scsi end device + */ +static inline int +mptsas_is_end_device(struct mptsas_devinfo * attached) +{ + if ((attached->handle) && + (attached->device_info & + MPI_SAS_DEVICE_INFO_END_DEVICE) && + ((attached->device_info & + MPI_SAS_DEVICE_INFO_SSP_TARGET) | + (attached->device_info & + MPI_SAS_DEVICE_INFO_STP_TARGET) | + (attached->device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE))) + return 1; + else + return 0; +} + static void mptsas_parse_device_info(struct sas_identify *identify, struct mptsas_devinfo *device_info) @@ -1227,7 +1272,7 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) } static struct mptsas_phyinfo * -mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) +mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) { struct mptsas_portinfo *port_info; struct mptsas_phyinfo *phy_info = NULL; @@ -1239,12 +1284,12 @@ mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) */ mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(port_info, &ioc->sas_topology, list) { - for (i = 0; i < port_info->num_phys; i++) { - if (port_info->phy_info[i].attached.handle == handle) { - phy_info = &port_info->phy_info[i]; - break; - } - } + for (i = 0; i < port_info->num_phys; i++) + if (mptsas_is_end_device(&port_info->phy_info[i].attached)) + if (port_info->phy_info[i].attached.id == id) { + phy_info = &port_info->phy_info[i]; + break; + } } mutex_unlock(&ioc->sas_topology_mutex); @@ -1258,36 +1303,58 @@ mptsas_hotplug_work(void *arg) MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; + struct scsi_device *sdev; char *ds = NULL; - - if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) - ds = "ssp"; - if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) - ds = "stp"; - if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) - ds = "sata"; + struct mptsas_devinfo sas_device; switch (ev->event_type) { case MPTSAS_DEL_DEVICE: - printk(MYIOC_s_INFO_FMT - "removing %s device, channel %d, id %d, phy %d\n", - ioc->name, ds, ev->channel, ev->id, ev->phy_id); - phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle); + phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); if (!phy_info) { printk("mptsas: remove event for non-existant PHY.\n"); break; } + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + ds = "ssp"; + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + ds = "stp"; + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + ds = "sata"; + + printk(MYIOC_s_INFO_FMT + "removing %s device, channel %d, id %d, phy %d\n", + ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); + if (phy_info->rphy) { sas_rphy_delete(phy_info->rphy); phy_info->rphy = NULL; } break; case MPTSAS_ADD_DEVICE: - printk(MYIOC_s_INFO_FMT - "attaching %s device, channel %d, id %d, phy %d\n", - ioc->name, ds, ev->channel, ev->id, ev->phy_id); + + /* + * When there is no sas address, + * RAID volumes are being deleted, + * and hidden phy disk are being added. + * We don't know the SAS data yet, + * so lookup sas device page to get + * pertaining info + */ + if (!ev->sas_address) { + if (mptsas_sas_device_pg0(ioc, + &sas_device, ev->id, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT))) + break; + ev->handle = sas_device.handle; + ev->parent_handle = sas_device.handle_parent; + ev->channel = sas_device.channel; + ev->phy_id = sas_device.phy_id; + ev->sas_address = sas_device.sas_address; + ev->device_info = sas_device.device_info; + } phy_info = mptsas_find_phyinfo_by_parent(ioc, ev->parent_handle, ev->phy_id); @@ -1310,10 +1377,23 @@ mptsas_hotplug_work(void *arg) phy_info->attached.sas_address = ev->sas_address; phy_info->attached.device_info = ev->device_info; + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + ds = "ssp"; + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + ds = "stp"; + if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + ds = "sata"; + + printk(MYIOC_s_INFO_FMT + "attaching %s device, channel %d, id %d, phy %d\n", + ioc->name, ds, ev->channel, ev->id, ev->phy_id); + + rphy = sas_rphy_alloc(phy_info->phy); if (!rphy) break; /* non-fatal: an rphy can be added later */ + rphy->scsi_target_id = phy_info->attached.id; mptsas_parse_device_info(&rphy->identify, &phy_info->attached); if (sas_rphy_add(rphy)) { sas_rphy_free(rphy); @@ -1322,6 +1402,40 @@ mptsas_hotplug_work(void *arg) phy_info->rphy = rphy; break; + case MPTSAS_ADD_RAID: + sdev = scsi_device_lookup( + ioc->sh, + ioc->num_ports, + ev->id, + 0); + if (sdev) { + scsi_device_put(sdev); + break; + } + printk(MYIOC_s_INFO_FMT + "attaching device, channel %d, id %d\n", + ioc->name, ioc->num_ports, ev->id); + scsi_add_device(ioc->sh, + ioc->num_ports, + ev->id, + 0); + mpt_findImVolumes(ioc); + break; + case MPTSAS_DEL_RAID: + sdev = scsi_device_lookup( + ioc->sh, + ioc->num_ports, + ev->id, + 0); + if (!sdev) + break; + printk(MYIOC_s_INFO_FMT + "removing device, channel %d, id %d\n", + ioc->name, ioc->num_ports, ev->id); + scsi_remove_device(sdev); + scsi_device_put(sdev); + mpt_findImVolumes(ioc); + break; } kfree(ev); @@ -1372,23 +1486,94 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); } +static void +mptscsih_send_raid_event(MPT_ADAPTER *ioc, + EVENT_DATA_RAID *raid_event_data) +{ + struct mptsas_hotplug_event *ev; + RAID_VOL0_STATUS * volumeStatus; + + if (ioc->bus_type != SAS) + return; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + return; + } + + memset(ev,0,sizeof(struct mptsas_hotplug_event)); + INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + ev->ioc = ioc; + ev->id = raid_event_data->VolumeID; + + switch (raid_event_data->ReasonCode) { + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + ev->event_type = MPTSAS_ADD_DEVICE; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + ev->event_type = MPTSAS_DEL_DEVICE; + break; + case MPI_EVENT_RAID_RC_VOLUME_DELETED: + ev->event_type = MPTSAS_DEL_RAID; + break; + case MPI_EVENT_RAID_RC_VOLUME_CREATED: + ev->event_type = MPTSAS_ADD_RAID; + break; + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: + volumeStatus = (RAID_VOL0_STATUS *) & + raid_event_data->SettingsStatus; + ev->event_type = (volumeStatus->State == + MPI_RAIDVOL0_STATUS_STATE_FAILED) ? + MPTSAS_DEL_RAID : MPTSAS_ADD_RAID; + break; + default: + break; + } + schedule_work(&ev->work); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* work queue thread to clear the persitency table */ +static void +mptscsih_sas_persist_clear_table(void * arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); +} + static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { + int rc=1; u8 event = le32_to_cpu(reply->Event) & 0xFF; if (!ioc->sh) - return 1; + goto out; switch (event) { case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: mptscsih_send_sas_event(ioc, (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); - return 1; /* currently means nothing really */ - + break; + case MPI_EVENT_INTEGRATED_RAID: + mptscsih_send_raid_event(ioc, + (EVENT_DATA_RAID *)reply->Data); + break; + case MPI_EVENT_PERSISTENT_TABLE_FULL: + INIT_WORK(&ioc->mptscsih_persistTask, + mptscsih_sas_persist_clear_table, + (void *)ioc); + schedule_work(&ioc->mptscsih_persistTask); + break; default: - return mptscsih_event_process(ioc, reply); + rc = mptscsih_event_process(ioc, reply); + break; } + out: + + return rc; } static int diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index cdac5578fdf2..05789e505464 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -144,7 +144,6 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); @@ -159,11 +158,9 @@ static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); -static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget); +static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice); static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -static struct work_struct mptscsih_persistTask; - #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); @@ -563,11 +560,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) MPT_SCSI_HOST *hd; SCSIIORequest_t *pScsiReq; SCSIIOReply_t *pScsiReply; - u16 req_idx; + u16 req_idx, req_idx_MR; hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + req_idx_MR = (mr != NULL) ? + le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; + if ((req_idx != req_idx_MR) || + (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) { + printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n", + ioc->name); + printk (MYIOC_s_ERR_FMT + "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n", + ioc->name, req_idx, req_idx_MR, mf, mr, + hd->ScsiLookup[req_idx_MR]); + return 0; + } + sc = hd->ScsiLookup[req_idx]; if (sc == NULL) { MPIHeader_t *hdr = (MPIHeader_t *)mf; @@ -730,6 +740,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + sc->resid=0; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ if (scsi_status == MPI_SCSI_STATUS_BUSY) @@ -789,7 +801,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ default: @@ -1530,7 +1541,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * * Returns 0 for SUCCESS or -1 if FAILED. */ -static int +int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; @@ -1721,6 +1732,20 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun return retval; } +static int +mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) +{ + switch (ioc->bus_type) { + case FC: + return 40; + case SAS: + return 10; + case SPI: + default: + return 2; + } +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant @@ -1792,7 +1817,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, vdev->bus_id, vdev->target_id, vdev->lun, - ctx2abort, 2 /* 2 second timeout */); + ctx2abort, mptscsih_get_tm_timeout(ioc)); printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", hd->ioc->name, @@ -1843,7 +1868,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, vdev->bus_id, vdev->target_id, - 0, 0, 5 /* 5 second timeout */); + 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", hd->ioc->name, @@ -1893,7 +1918,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */); + vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -2016,6 +2041,42 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static void +mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) +{ + char *desc; + + switch (response_code) { + case MPI_SCSITASKMGMT_RSP_TM_COMPLETE: + desc = "The task completed."; + break; + case MPI_SCSITASKMGMT_RSP_INVALID_FRAME: + desc = "The IOC received an invalid frame status."; + break; + case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: + desc = "The task type is not supported."; + break; + case MPI_SCSITASKMGMT_RSP_TM_FAILED: + desc = "The requested task failed."; + break; + case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED: + desc = "The task completed successfully."; + break; + case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN: + desc = "The LUN request is invalid."; + break; + case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: + desc = "The task is in the IOC queue and has not been sent to target."; + break; + default: + desc = "unknown"; + break; + } + printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", + ioc->name, response_code, desc); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver * @ioc: Pointer to MPT_ADAPTER structure @@ -2064,6 +2125,11 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ tmType = pScsiTmReq->TaskType; + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && + pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); @@ -2255,7 +2321,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev) vtarget->luns[0] &= ~(1 << vdevice->lun); vtarget->num_luns--; if (vtarget->num_luns == 0) { - mptscsih_negotiate_to_asyn_narrow(hd, vtarget); + mptscsih_negotiate_to_asyn_narrow(hd, vdevice); if (hd->ioc->bus_type == SPI) { if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) { hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; @@ -2585,16 +2651,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* work queue thread to clear the persitency table */ -static void -mptscsih_sas_persist_clear_table(void * arg) -{ - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; - - mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { @@ -2656,13 +2712,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; } - /* Persistent table is full. */ - case MPI_EVENT_PERSISTENT_TABLE_FULL: - INIT_WORK(&mptscsih_persistTask, - mptscsih_sas_persist_clear_table,(void *)ioc); - schedule_work(&mptscsih_persistTask); - break; - case MPI_EVENT_NONE: /* 00 */ case MPI_EVENT_LOG_DATA: /* 01 */ case MPI_EVENT_STATE_CHANGE: /* 02 */ @@ -3863,8 +3912,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) * */ static void -mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) +mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice) { + VirtTarget *vtarget = vdevice->vtarget; MPT_ADAPTER *ioc= hd->ioc; SCSIDevicePage1_t *pcfg1Data; CONFIGPARMS cfg; @@ -3874,7 +3924,8 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) int requested, configuration, data,i; u8 flags, factor; - if (ioc->bus_type != SPI) + if ((ioc->bus_type != SPI) || + (!vdevice->configured_lun)) return; if (!ioc->spi_data.sdp1length) @@ -3910,7 +3961,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) } mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, &configuration, flags); - dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " + dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " "offset=0 negoFlags=%x request=%x config=%x\n", id, flags, requested, configuration)); pcfg1Data->RequestedParameters = cpu_to_le32(requested); @@ -3923,7 +3974,7 @@ mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget) flags = vtarget->negoFlags; mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, &configuration, flags); - dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " + dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " "offset=0 negoFlags=%x request=%x config=%x\n", vtarget->target_id, flags, requested, configuration)); pcfg1Data->RequestedParameters = cpu_to_le32(requested); @@ -5620,5 +5671,6 @@ EXPORT_SYMBOL(mptscsih_event_process); EXPORT_SYMBOL(mptscsih_ioc_reset); EXPORT_SYMBOL(mptscsih_change_queue_depth); EXPORT_SYMBOL(mptscsih_timer_expired); +EXPORT_SYMBOL(mptscsih_TMHandler); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index d3cba12f4bd9..44b248d51ea3 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -108,3 +108,4 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); +extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 7dce29277cb7..f148dfa39117 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -384,6 +384,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptspi_probe; } + /* + * issue internal bus reset + */ + if (ioc->spi_data.bus_reset) + mptscsih_TMHandler(hd, + MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + 0, 0, 0, 0, 5); + scsi_scan_host(sh); return 0; @@ -445,7 +453,7 @@ static void __exit mptspi_exit(void) { pci_unregister_driver(&mptspi_driver); - + mpt_reset_deregister(mptspiDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h index 90628562851e..184974cc734d 100644 --- a/drivers/message/i2o/core.h +++ b/drivers/message/i2o/core.h @@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *); #define I2O_IN_PORT 0x40 #define I2O_OUT_PORT 0x44 +/* Motorola/Freescale specific register offset */ +#define I2O_MOTOROLA_PORT_OFFSET 0x10400 + #define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index f9e5a23697a1..c08ddac3717d 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -732,7 +732,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); - if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) + if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) status = SUCCESS; return status; diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index d698d7709c31..4f1515cae5dc 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -88,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) struct device *dev = &pdev->dev; int i; + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "%s: device already claimed\n", c->name); + return -ENODEV; + } + for (i = 0; i < 6; i++) { /* Skip I/O spaces */ if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { @@ -163,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) c->in_port = c->base.virt + I2O_IN_PORT; c->out_port = c->base.virt + I2O_OUT_PORT; + /* Motorola/Freescale chip does not follow spec */ + if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { + /* Check if CPU is enabled */ + if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { + printk(KERN_INFO "%s: MPC82XX needs CPU running to " + "service I2O.\n", c->name); + i2o_pci_free(c); + return -ENODEV; + } else { + c->irq_status += I2O_MOTOROLA_PORT_OFFSET; + c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; + c->in_port += I2O_MOTOROLA_PORT_OFFSET; + c->out_port += I2O_MOTOROLA_PORT_OFFSET; + printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", + c->name); + } + } + if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { i2o_pci_free(c); return -ENOMEM; @@ -298,7 +321,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, struct i2o_controller *c; int rc; struct pci_dev *i960 = NULL; - int pci_dev_busy = 0; + int enabled = pdev->is_enabled; printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); @@ -308,16 +331,12 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, return -ENODEV; } - if ((rc = pci_enable_device(pdev))) { - printk(KERN_WARNING "i2o: couldn't enable device %s\n", - pci_name(pdev)); - return rc; - } - - if (pci_request_regions(pdev, OSM_DESCRIPTION)) { - printk(KERN_ERR "i2o: device already claimed\n"); - return -ENODEV; - } + if (!enabled) + if ((rc = pci_enable_device(pdev))) { + printk(KERN_WARNING "i2o: couldn't enable device %s\n", + pci_name(pdev)); + return rc; + } if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", @@ -395,9 +414,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_pci_alloc(c))) { printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " - " failed\n", c->name); - if (rc == -ENODEV) - pci_dev_busy = 1; + "failed\n", c->name); goto free_controller; } @@ -425,7 +442,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, i2o_iop_free(c); disable: - if (!pci_dev_busy) + if (!enabled) pci_disable_device(pdev); return rc; diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c index 7e98434cfa37..9783caf49696 100644 --- a/drivers/misc/ibmasm/uart.c +++ b/drivers/misc/ibmasm/uart.c @@ -50,7 +50,7 @@ void ibmasm_register_uart(struct service_processor *sp) memset(&uport, 0, sizeof(struct uart_port)); uport.irq = sp->irq; uport.uartclk = 3686400; - uport.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ; + uport.flags = UPF_SHARE_IRQ; uport.iotype = UPIO_MEM; uport.membase = iomem_base; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c483a863b116..5d397b7a5497 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -65,7 +65,7 @@ config MMC_AU1X depends on SOC_AU1X00 && MMC help This selects the AMD Alchemy(R) Multimedia card interface. - iIf you have a Alchemy platform with a MMC slot, say Y or M here. + If you have a Alchemy platform with a MMC slot, say Y or M here. If unsure, say N. diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index aaf04638054e..227c39a7c1b4 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -194,7 +194,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); - switch(cmd->flags) { + switch (mmc_rsp_type(cmd->flags)) { case MMC_RSP_R1: mmccmd |= SD_CMD_RT_1; break; @@ -483,34 +483,35 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status) cmd = mrq->cmd; cmd->error = MMC_ERR_NONE; - if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) { - - /* Techincally, we should be getting all 48 bits of the response - * (SD_RESP1 + SD_RESP2), but because our response omits the CRC, - * our data ends up being shifted 8 bits to the right. In this case, - * that means that the OSR data starts at bit 31, so we can just - * read RESP0 and return that - */ - - cmd->resp[0] = au_readl(host->iobase + SD_RESP0); - } - else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) { - u32 r[4]; - int i; - - r[0] = au_readl(host->iobase + SD_RESP3); - r[1] = au_readl(host->iobase + SD_RESP2); - r[2] = au_readl(host->iobase + SD_RESP1); - r[3] = au_readl(host->iobase + SD_RESP0); - - /* The CRC is omitted from the response, so really we only got - * 120 bytes, but the engine expects 128 bits, so we have to shift - * things up - */ - - for(i = 0; i < 4; i++) { - cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; - if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + u32 r[4]; + int i; + + r[0] = au_readl(host->iobase + SD_RESP3); + r[1] = au_readl(host->iobase + SD_RESP2); + r[2] = au_readl(host->iobase + SD_RESP1); + r[3] = au_readl(host->iobase + SD_RESP0); + + /* The CRC is omitted from the response, so really + * we only got 120 bytes, but the engine expects + * 128 bits, so we have to shift things up + */ + + for(i = 0; i < 4; i++) { + cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; + if (i != 3) + cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; + } + } else { + /* Techincally, we should be getting all 48 bits of + * the response (SD_RESP1 + SD_RESP2), but because + * our response omits the CRC, our data ends up + * being shifted 8 bits to the right. In this case, + * that means that the OSR data starts at bit 31, + * so we can just read RESP0 and return that + */ + cmd->resp[0] = au_readl(host->iobase + SD_RESP0); } } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index bfca5c176e88..1888060c5e0c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -211,7 +211,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, appcmd.opcode = MMC_APP_CMD; appcmd.arg = rca << 16; - appcmd.flags = MMC_RSP_R1; + appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; appcmd.retries = 0; memset(appcmd.resp, 0, sizeof(appcmd.resp)); appcmd.data = NULL; @@ -331,7 +331,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) cmd.opcode = MMC_SELECT_CARD; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) @@ -358,7 +358,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) struct mmc_command cmd; cmd.opcode = SD_APP_SET_BUS_WIDTH; cmd.arg = SD_BUS_WIDTH_4; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_app_cmd(host, card->rca, &cmd, CMD_RETRIES); @@ -386,7 +386,7 @@ static void mmc_deselect_cards(struct mmc_host *host) cmd.opcode = MMC_SELECT_CARD; cmd.arg = 0; - cmd.flags = MMC_RSP_NONE; + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; mmc_wait_for_cmd(host, &cmd, 0); } @@ -677,7 +677,7 @@ static void mmc_idle_cards(struct mmc_host *host) cmd.opcode = MMC_GO_IDLE_STATE; cmd.arg = 0; - cmd.flags = MMC_RSP_NONE; + cmd.flags = MMC_RSP_NONE | MMC_CMD_BC; mmc_wait_for_cmd(host, &cmd, 0); @@ -738,7 +738,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) cmd.opcode = MMC_SEND_OP_COND; cmd.arg = ocr; - cmd.flags = MMC_RSP_R3; + cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; for (i = 100; i; i--) { err = mmc_wait_for_cmd(host, &cmd, 0); @@ -766,7 +766,7 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) cmd.opcode = SD_APP_OP_COND; cmd.arg = ocr; - cmd.flags = MMC_RSP_R3; + cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; for (i = 100; i; i--) { err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); @@ -805,7 +805,7 @@ static void mmc_discover_cards(struct mmc_host *host) cmd.opcode = MMC_ALL_SEND_CID; cmd.arg = 0; - cmd.flags = MMC_RSP_R2; + cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err == MMC_ERR_TIMEOUT) { @@ -835,7 +835,7 @@ static void mmc_discover_cards(struct mmc_host *host) cmd.opcode = SD_SEND_RELATIVE_ADDR; cmd.arg = 0; - cmd.flags = MMC_RSP_R6; + cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) @@ -856,7 +856,7 @@ static void mmc_discover_cards(struct mmc_host *host) } else { cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) @@ -878,7 +878,7 @@ static void mmc_read_csds(struct mmc_host *host) cmd.opcode = MMC_SEND_CSD; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R2; + cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) { @@ -920,7 +920,7 @@ static void mmc_read_scrs(struct mmc_host *host) cmd.opcode = MMC_APP_CMD; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, 0); if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) { @@ -932,7 +932,7 @@ static void mmc_read_scrs(struct mmc_host *host) cmd.opcode = SD_APP_SEND_SCR; cmd.arg = 0; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; memset(&data, 0, sizeof(struct mmc_data)); @@ -1003,7 +1003,7 @@ static void mmc_check_cards(struct mmc_host *host) cmd.opcode = MMC_SEND_STATUS; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err == MMC_ERR_NONE) diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 5b014c370e80..8eb2a2ede64b 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -171,14 +171,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.mrq.data = &brq.data; brq.cmd.arg = req->sector << 9; - brq.cmd.flags = MMC_RSP_R1; + brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; brq.data.timeout_ns = card->csd.tacc_ns * 10; brq.data.timeout_clks = card->csd.tacc_clks * 10; brq.data.blksz_bits = md->block_bits; brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); brq.stop.opcode = MMC_STOP_TRANSMISSION; brq.stop.arg = 0; - brq.stop.flags = MMC_RSP_R1B; + brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; if (rq_data_dir(req) == READ) { brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; @@ -223,7 +223,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) cmd.opcode = MMC_SEND_STATUS; cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, 5); if (err) { printk(KERN_ERR "%s: error %d requesting status\n", @@ -430,7 +430,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) mmc_card_claim_host(card); cmd.opcode = MMC_SET_BLOCKLEN; cmd.arg = 1 << md->block_bits; - cmd.flags = MMC_RSP_R1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, 5); mmc_card_release_host(card); diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 634ef53e85a5..37ee7f8dc82f 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -124,15 +124,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) } c |= cmd->opcode | MCI_CPSM_ENABLE; - switch (cmd->flags & MMC_RSP_MASK) { - case MMC_RSP_NONE: - default: - break; - case MMC_RSP_LONG: - c |= MCI_CPSM_LONGRSP; - case MMC_RSP_SHORT: + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) + c |= MCI_CPSM_LONGRSP; c |= MCI_CPSM_RESPONSE; - break; } if (/*interrupt*/0) c |= MCI_CPSM_INTERRUPT; diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index ee8f8a0420d1..285d7d068097 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -178,14 +178,15 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, if (cmd->flags & MMC_RSP_BUSY) cmdat |= CMDAT_BUSY; - switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) { - case MMC_RSP_SHORT | MMC_RSP_CRC: +#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) + switch (RSP_TYPE(mmc_resp_type(cmd))) { + case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */ cmdat |= CMDAT_RESP_SHORT; break; - case MMC_RSP_SHORT: + case RSP_TYPE(MMC_RSP_R3): cmdat |= CMDAT_RESP_R3; break; - case MMC_RSP_LONG | MMC_RSP_CRC: + case RSP_TYPE(MMC_RSP_R2): cmdat |= CMDAT_RESP_R2; break; default: diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index f25757625361..3be397d436fa 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -459,7 +459,7 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) /* * Do we expect a reply? */ - if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) { + if (cmd->flags & MMC_RSP_PRESENT) { /* * Read back status. */ @@ -476,10 +476,10 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) cmd->error = MMC_ERR_BADCRC; /* All ok */ else { - if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) - wbsd_get_short_reply(host, cmd); - else + if (cmd->flags & MMC_RSP_136) wbsd_get_long_reply(host, cmd); + else + wbsd_get_short_reply(host, cmd); } } diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index effa0d7a73ac..205bb7083335 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -301,7 +301,7 @@ config MTD_JEDEC config MTD_XIP bool "XIP aware MTD support" - depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARM + depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP default y if XIP_KERNEL help This allows MTD support to work with flash memory which is also diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index 701620b6baed..8b3784e2de89 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -110,8 +110,9 @@ static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const voi { while (len > 0) { map_word d; - d.x[0] = *((uint32_t*)from)++; + d.x[0] = *((uint32_t*)from); dc21285_write32(map, d, to); + from += 4; to += 4; len -= 4; } @@ -121,8 +122,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi { while (len > 0) { map_word d; - d.x[0] = *((uint16_t*)from)++; + d.x[0] = *((uint16_t*)from); dc21285_write16(map, d, to); + from += 2; to += 2; len -= 2; } @@ -131,8 +133,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len) { map_word d; - d.x[0] = *((uint8_t*)from)++; + d.x[0] = *((uint8_t*)from); dc21285_write8(map, d, to); + from++; to++; len--; } diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c index 9e21e6c02f80..0f915ac3102e 100644 --- a/drivers/mtd/maps/tsunami_flash.c +++ b/drivers/mtd/maps/tsunami_flash.c @@ -62,7 +62,7 @@ static void tsunami_flash_copy_to( static struct map_info tsunami_flash_map = { .name = "flash chip on the Tsunami TIG bus", .size = MAX_TIG_FLASH_SIZE, - .phys = NO_XIP; + .phys = NO_XIP, .bankwidth = 1, .read = tsunami_flash_read8, .copy_from = tsunami_flash_copy_from, diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7488ee7f7caf..7f47124f118d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -753,9 +753,11 @@ enum tx_desc_status { enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 }; struct vortex_extra_stats { - unsigned long tx_deferred; - unsigned long tx_multiple_collisions; - unsigned long rx_bad_ssd; + unsigned long tx_deferred; + unsigned long tx_max_collisions; + unsigned long tx_multiple_collisions; + unsigned long tx_single_collisions; + unsigned long rx_bad_ssd; }; struct vortex_private { @@ -863,12 +865,14 @@ static struct { const char str[ETH_GSTRING_LEN]; } ethtool_stats_keys[] = { { "tx_deferred" }, + { "tx_max_collisions" }, { "tx_multiple_collisions" }, + { "tx_single_collisions" }, { "rx_bad_ssd" }, }; /* number of ETHTOOL_GSTATS u64's */ -#define VORTEX_NUM_STATS 3 +#define VORTEX_NUM_STATS 5 static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, int chip_idx, int card_idx); @@ -2108,9 +2112,12 @@ vortex_error(struct net_device *dev, int status) iowrite8(0, ioaddr + TxStatus); if (tx_status & 0x30) { /* txJabber or txUnderrun */ do_tx_reset = 1; - } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ - do_tx_reset = 1; - reset_mask = 0x0108; /* Reset interface logic, but not download logic */ + } else if (tx_status & 0x08) { /* maxCollisions */ + vp->xstats.tx_max_collisions++; + if (vp->drv_flags & MAX_COLLISION_RESET) { + do_tx_reset = 1; + reset_mask = 0x0108; /* Reset interface logic, but not download logic */ + } } else { /* Merely re-enable the transmitter. */ iowrite16(TxEnable, ioaddr + EL3_CMD); } @@ -2926,7 +2933,6 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev) EL3WINDOW(6); vp->stats.tx_carrier_errors += ioread8(ioaddr + 0); vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1); - vp->stats.collisions += ioread8(ioaddr + 3); vp->stats.tx_window_errors += ioread8(ioaddr + 4); vp->stats.rx_fifo_errors += ioread8(ioaddr + 5); vp->stats.tx_packets += ioread8(ioaddr + 6); @@ -2939,10 +2945,15 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev) vp->stats.tx_bytes += ioread16(ioaddr + 12); /* Extra stats for get_ethtool_stats() */ vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2); + vp->xstats.tx_single_collisions += ioread8(ioaddr + 3); vp->xstats.tx_deferred += ioread8(ioaddr + 8); EL3WINDOW(4); vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12); + vp->stats.collisions = vp->xstats.tx_multiple_collisions + + vp->xstats.tx_single_collisions + + vp->xstats.tx_max_collisions; + { u8 up = ioread8(ioaddr + 13); vp->stats.rx_bytes += (up & 0x0f) << 16; @@ -3036,8 +3047,10 @@ static void vortex_get_ethtool_stats(struct net_device *dev, spin_unlock_irqrestore(&vp->lock, flags); data[0] = vp->xstats.tx_deferred; - data[1] = vp->xstats.tx_multiple_collisions; - data[2] = vp->xstats.rx_bad_ssd; + data[1] = vp->xstats.tx_max_collisions; + data[2] = vp->xstats.tx_multiple_collisions; + data[3] = vp->xstats.tx_single_collisions; + data[4] = vp->xstats.rx_bad_ssd; } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index adfba44dac5a..2beac55b57d6 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -586,6 +586,7 @@ struct rtl8139_private { dma_addr_t tx_bufs_dma; signed char phys[4]; /* MII device addresses. */ char twistie, twist_row, twist_col; /* Twister tune state. */ + unsigned int watchdog_fired : 1; unsigned int default_port : 4; /* Last dev->if_port value. */ unsigned int have_thread : 1; spinlock_t lock; @@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); static void rtl8139_thread (void *_data); +static void rtl8139_tx_timeout_task(void *_data); static struct ethtool_ops rtl8139_ethtool_ops; /* write MMIO register, with flush */ @@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data) { struct net_device *dev = _data; struct rtl8139_private *tp = netdev_priv(dev); - unsigned long thr_delay; + unsigned long thr_delay = next_tick; - if (rtnl_shlock_nowait() == 0) { + if (tp->watchdog_fired) { + tp->watchdog_fired = 0; + rtl8139_tx_timeout_task(_data); + } else if (rtnl_shlock_nowait() == 0) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); - - thr_delay = next_tick; } else { /* unlikely race. mitigate with fast poll. */ thr_delay = HZ / 2; @@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp) if (tp->have_thread) { cancel_rearming_delayed_work(&tp->thread); tp->have_thread = 0; - } + } else + flush_scheduled_work(); } static inline void rtl8139_tx_clear (struct rtl8139_private *tp) @@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ } - -static void rtl8139_tx_timeout (struct net_device *dev) +static void rtl8139_tx_timeout_task (void *_data) { + struct net_device *dev = _data; struct rtl8139_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; int i; u8 tmp8; - unsigned long flags; printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), @@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev) if (tmp8 & CmdTxEnb) RTL_W8 (ChipCmd, CmdRxEnb); - spin_lock(&tp->rx_lock); + spin_lock_bh(&tp->rx_lock); /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irq(&tp->lock); rtl8139_tx_clear (tp); - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irq(&tp->lock); /* ...and finally, reset everything */ if (netif_running(dev)) { rtl8139_hw_start (dev); netif_wake_queue (dev); } - spin_unlock(&tp->rx_lock); + spin_unlock_bh(&tp->rx_lock); } +static void rtl8139_tx_timeout (struct net_device *dev) +{ + struct rtl8139_private *tp = netdev_priv(dev); + + if (!tp->have_thread) { + INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); + schedule_delayed_work(&tp->thread, next_tick); + } else + tp->watchdog_fired = 1; + +} static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) { diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1421941487c4..47c72a63dfe1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -4,9 +4,10 @@ # menu "Network device support" + depends on NET config NETDEVICES - depends on NET + default y if UML bool "Network device support" ---help--- You can say N here if you don't intend to connect your Linux box to @@ -23,9 +24,6 @@ config NETDEVICES If unsure, say Y. -# All the following symbols are dependent on NETDEVICES - do not repeat -# that for each of the symbols. -if NETDEVICES config IFB tristate "Intermediate Functional Block support" @@ -1914,6 +1912,15 @@ config E1000_NAPI If in doubt, say N. +config E1000_DISABLE_PACKET_SPLIT + bool "Disable Packet Split for PCI express adapters" + depends on E1000 + help + Say Y here if you want to use the legacy receive path for PCI express + hadware. + + If in doubt, say N. + source "drivers/net/ixp2000/Kconfig" config MYRI_SBUS @@ -2024,13 +2031,28 @@ config SKGE It does not support the link failover and network management features that "portable" vendor supplied sk98lin driver does. + This driver supports adapters based on the original Yukon chipset: + Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T, + Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872. + + It does not support the newer Yukon2 chipset: a separate driver, + sky2, is provided for Yukon2-based adapters. + + To compile this driver as a module, choose M here: the module + will be called skge. This is recommended. config SKY2 tristate "SysKonnect Yukon2 support (EXPERIMENTAL)" depends on PCI && EXPERIMENTAL select CRC32 ---help--- - This driver support the Marvell Yukon 2 Gigabit Ethernet adapter. + This driver supports Gigabit Ethernet adapters based on the the + Marvell Yukon 2 chipset: + Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/ + 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21 + + This driver does not support the original Yukon chipset: a seperate + driver, skge, is provided for Yukon-based adapters. To compile this driver as a module, choose M here: the module will be called sky2. This is recommended. @@ -2040,8 +2062,15 @@ config SK98LIN depends on PCI ---help--- Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx - compliant Gigabit Ethernet Adapter. The following adapters are supported - by this driver: + compliant Gigabit Ethernet Adapter. + + This driver supports the original Yukon chipset. A cleaner driver is + also available (skge) which seems to work better than this one. + + This driver does not support the newer Yukon2 chipset. A seperate + driver, sky2, is provided to support Yukon2-based adapters. + + The following adapters are supported by this driver: - 3Com 3C940 Gigabit LOM Ethernet Adapter - 3Com 3C941 Gigabit LOM Ethernet Adapter - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter @@ -2686,8 +2715,6 @@ config NETCONSOLE If you want to log kernel messages over the network, enable this. See <file:Documentation/networking/netconsole.txt> for details. -endif #NETDEVICES - config NETPOLL def_bool NETCONSOLE diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index b8953de5664a..b508812e97ac 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -1002,6 +1002,8 @@ static int __devinit ace_init(struct net_device *dev) mac1 = 0; for(i = 0; i < 4; i++) { + int tmp; + mac1 = mac1 << 8; tmp = read_eeprom_byte(dev, 0x8c+i); if (tmp < 0) { @@ -1012,6 +1014,8 @@ static int __devinit ace_init(struct net_device *dev) } mac2 = 0; for(i = 4; i < 8; i++) { + int tmp; + mac2 = mac2 << 8; tmp = read_eeprom_byte(dev, 0x8c+i); if (tmp < 0) { diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h index c68ba9c2ef46..fd2750b269c8 100644 --- a/drivers/net/appletalk/cops.h +++ b/drivers/net/appletalk/cops.h @@ -51,7 +51,7 @@ struct ltfirmware { unsigned int length; - unsigned char * data; + const unsigned char *data; }; #define DAYNA 1 diff --git a/drivers/net/b44.c b/drivers/net/b44.c index df9d6e80c4f2..c3267e4e1bb0 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1399,7 +1399,6 @@ static int b44_open(struct net_device *dev) b44_init_rings(bp); b44_init_hw(bp); - netif_carrier_off(dev); b44_check_phy(bp); err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev); @@ -1464,7 +1463,7 @@ static int b44_close(struct net_device *dev) #endif b44_halt(bp); b44_free_rings(bp); - netif_carrier_off(bp->dev); + netif_carrier_off(dev); spin_unlock_irq(&bp->lock); @@ -2000,6 +1999,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev, dev->irq = pdev->irq; SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); + netif_carrier_off(dev); + err = b44_get_invariants(bp); if (err) { printk(KERN_ERR PFX "Problem fetching invariants of chip, " diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 49fa1e4413fa..a24200d0a616 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1,6 +1,6 @@ /* bnx2.c: Broadcom NX2 network driver. * - * Copyright (c) 2004, 2005 Broadcom Corporation + * Copyright (c) 2004, 2005, 2006 Broadcom Corporation * * 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 @@ -14,8 +14,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.30" -#define DRV_MODULE_RELDATE "October 11, 2005" +#define DRV_MODULE_VERSION "1.4.31" +#define DRV_MODULE_RELDATE "January 19, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -316,6 +316,10 @@ bnx2_enable_int(struct bnx2 *bp) u32 val; REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx); + + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); val = REG_RD(bp, BNX2_HC_COMMAND); @@ -1171,7 +1175,8 @@ bnx2_init_5708s_phy(struct bnx2 *bp) } if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || - (CHIP_ID(bp) == CHIP_ID_5708_B0)) { + (CHIP_ID(bp) == CHIP_ID_5708_B0) || + (CHIP_ID(bp) == CHIP_ID_5708_B1)) { /* increase tx signal amplitude */ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_TX_MISC); @@ -1326,44 +1331,78 @@ bnx2_set_mac_loopback(struct bnx2 *bp) return 0; } +static int bnx2_test_link(struct bnx2 *); + +static int +bnx2_set_phy_loopback(struct bnx2 *bp) +{ + u32 mac_mode; + int rc, i; + + spin_lock_bh(&bp->phy_lock); + rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | + BMCR_SPEED1000); + spin_unlock_bh(&bp->phy_lock); + if (rc) + return rc; + + for (i = 0; i < 10; i++) { + if (bnx2_test_link(bp) == 0) + break; + udelay(10); + } + + mac_mode = REG_RD(bp, BNX2_EMAC_MODE); + mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | + BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | + BNX2_EMAC_MODE_25G); + + mac_mode |= BNX2_EMAC_MODE_PORT_GMII; + REG_WR(bp, BNX2_EMAC_MODE, mac_mode); + bp->link_up = 1; + return 0; +} + static int -bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) +bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent) { int i; u32 val; - if (bp->fw_timed_out) - return -EBUSY; - bp->fw_wr_seq++; msg_data |= bp->fw_wr_seq; REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); /* wait for an acknowledgement. */ - for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) { - udelay(5); + for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) { + msleep(10); val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB); if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) break; } + if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0) + return 0; /* If we timed out, inform the firmware that this is the case. */ - if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) && - ((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) { + if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) { + if (!silent) + printk(KERN_ERR PFX "fw sync timeout, reset code = " + "%x\n", msg_data); msg_data &= ~BNX2_DRV_MSG_CODE; msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); - bp->fw_timed_out = 1; - return -EBUSY; } + if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK) + return -EIO; + return 0; } @@ -1657,7 +1696,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) rmb(); while (sw_cons != hw_cons) { unsigned int len; - u16 status; + u32 status; struct sw_bd *rx_buf; struct sk_buff *skb; @@ -1673,7 +1712,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) rx_hdr = (struct l2_fhdr *) skb->data; len = rx_hdr->l2_fhdr_pkt_len - 4; - if (rx_hdr->l2_fhdr_errors & + if ((status = rx_hdr->l2_fhdr_status) & (L2_FHDR_ERRORS_BAD_CRC | L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT | @@ -1732,15 +1771,13 @@ reuse_rx: } - status = rx_hdr->l2_fhdr_status; skb->ip_summed = CHECKSUM_NONE; if (bp->rx_csum && (status & (L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_UDP_DATAGRAM))) { - u16 cksum = rx_hdr->l2_fhdr_tcp_udp_xsum; - - if (cksum == 0xffff) + if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM | + L2_FHDR_ERRORS_UDP_XSUM)) == 0)) skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -1794,7 +1831,7 @@ static irqreturn_t bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = dev_instance; - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); prefetch(bp->status_blk); REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, @@ -1814,7 +1851,7 @@ static irqreturn_t bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = dev_instance; - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); /* When using INTx, it is possible for the interrupt to arrive * at the CPU before the status block posted prior to the @@ -1859,7 +1896,7 @@ bnx2_has_work(struct bnx2 *bp) static int bnx2_poll(struct net_device *dev, int *budget) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if ((bp->status_blk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != @@ -1891,9 +1928,20 @@ bnx2_poll(struct net_device *dev, int *budget) if (!bnx2_has_work(bp)) { netif_rx_complete(dev); + if (likely(bp->flags & USING_MSI_FLAG)) { + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bp->last_status_idx); + return 0; + } + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT | + bp->last_status_idx); + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - bp->last_status_idx); + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bp->last_status_idx); return 0; } @@ -1906,7 +1954,7 @@ bnx2_poll(struct net_device *dev, int *budget) static void bnx2_set_rx_mode(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); u32 rx_mode, sort_mode; int i; @@ -1916,11 +1964,11 @@ bnx2_set_rx_mode(struct net_device *dev) BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG); sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN; #ifdef BCM_VLAN - if (!bp->vlgrp) { + if (!bp->vlgrp && !(bp->flags & ASF_ENABLE_FLAG)) rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; - } #else - rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; + if (!(bp->flags & ASF_ENABLE_FLAG)) + rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; #endif if (dev->flags & IFF_PROMISC) { /* Promiscuous mode. */ @@ -2338,7 +2386,6 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) val |= BNX2_EMAC_MODE_PORT_MII | BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD | - BNX2_EMAC_MODE_FORCE_LINK | BNX2_EMAC_MODE_MPKT; REG_WR(bp, BNX2_EMAC_MODE, val); @@ -2374,7 +2421,8 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; } - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg); + if (!(bp->flags & NO_WOL_FLAG)) + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 0); pmcsr &= ~PCI_PM_CTRL_STATE_MASK; if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || @@ -2708,9 +2756,16 @@ bnx2_init_nvram(struct bnx2 *bp) if (j == entry_count) { bp->flash_info = NULL; printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n"); - rc = -ENODEV; + return -ENODEV; } + val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2); + val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK; + if (val) + bp->flash_size = val; + else + bp->flash_size = bp->flash_info->total_size; + return rc; } @@ -3014,16 +3069,14 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); udelay(5); + /* Wait for the firmware to tell us it is ok to issue a reset. */ + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1); + /* Deposit a driver reset signature so the firmware knows that * this is a soft reset. */ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE, BNX2_DRV_RESET_SIGNATURE_MAGIC); - bp->fw_timed_out = 0; - - /* Wait for the firmware to tell us it is ok to issue a reset. */ - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code); - /* Do a dummy read to force the chip to complete all current transaction * before we issue a reset. */ val = REG_RD(bp, BNX2_MISC_ID); @@ -3062,10 +3115,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) return -ENODEV; } - bp->fw_timed_out = 0; - /* Wait for the firmware to finish its initialization. */ - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code); + rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0); + if (rc) + return rc; if (CHIP_ID(bp) == CHIP_ID_5706_A0) { /* Adjust the voltage regular to two steps lower. The default @@ -3083,6 +3136,7 @@ static int bnx2_init_chip(struct bnx2 *bp) { u32 val; + int rc; /* Make sure the interrupt is not active. */ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); @@ -3098,7 +3152,7 @@ bnx2_init_chip(struct bnx2 *bp) val |= (0x2 << 20) | (1 << 11); - if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz = 133)) + if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133)) val |= (1 << 23); if ((CHIP_NUM(bp) == CHIP_NUM_5706) && @@ -3218,17 +3272,22 @@ bnx2_init_chip(struct bnx2 *bp) REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE); + if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) & + BNX2_PORT_FEATURE_ASF_ENABLED) + bp->flags |= ASF_ENABLE_FLAG; + /* Initialize the receive filter. */ bnx2_set_rx_mode(bp->dev); - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET); + rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, + 0); REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); udelay(20); - return 0; + return rc; } @@ -3880,26 +3939,33 @@ bnx2_test_memory(struct bnx2 *bp) return ret; } +#define BNX2_MAC_LOOPBACK 0 +#define BNX2_PHY_LOOPBACK 1 + static int -bnx2_test_loopback(struct bnx2 *bp) +bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) { unsigned int pkt_size, num_pkts, i; struct sk_buff *skb, *rx_skb; unsigned char *packet; - u16 rx_start_idx, rx_idx, send_idx; - u32 send_bseq, val; + u16 rx_start_idx, rx_idx; + u32 val; dma_addr_t map; struct tx_bd *txbd; struct sw_bd *rx_buf; struct l2_fhdr *rx_hdr; int ret = -ENODEV; - if (!netif_running(bp->dev)) - return -ENODEV; - - bp->loopback = MAC_LOOPBACK; - bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_DIAG); - bnx2_set_mac_loopback(bp); + if (loopback_mode == BNX2_MAC_LOOPBACK) { + bp->loopback = MAC_LOOPBACK; + bnx2_set_mac_loopback(bp); + } + else if (loopback_mode == BNX2_PHY_LOOPBACK) { + bp->loopback = 0; + bnx2_set_phy_loopback(bp); + } + else + return -EINVAL; pkt_size = 1514; skb = dev_alloc_skb(pkt_size); @@ -3921,11 +3987,9 @@ bnx2_test_loopback(struct bnx2 *bp) udelay(5); rx_start_idx = bp->status_blk->status_rx_quick_consumer_index0; - send_idx = 0; - send_bseq = 0; num_pkts = 0; - txbd = &bp->tx_desc_ring[send_idx]; + txbd = &bp->tx_desc_ring[TX_RING_IDX(bp->tx_prod)]; txbd->tx_bd_haddr_hi = (u64) map >> 32; txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff; @@ -3933,13 +3997,11 @@ bnx2_test_loopback(struct bnx2 *bp) txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END; num_pkts++; - send_idx = NEXT_TX_BD(send_idx); - - send_bseq += pkt_size; - - REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, send_idx); - REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, send_bseq); + bp->tx_prod = NEXT_TX_BD(bp->tx_prod); + bp->tx_prod_bseq += pkt_size; + REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, bp->tx_prod); + REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq); udelay(100); @@ -3952,7 +4014,7 @@ bnx2_test_loopback(struct bnx2 *bp) pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); - if (bp->status_blk->status_tx_quick_consumer_index0 != send_idx) { + if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) { goto loopback_test_done; } @@ -3971,7 +4033,7 @@ bnx2_test_loopback(struct bnx2 *bp) pci_unmap_addr(rx_buf, mapping), bp->rx_buf_size, PCI_DMA_FROMDEVICE); - if (rx_hdr->l2_fhdr_errors & + if (rx_hdr->l2_fhdr_status & (L2_FHDR_ERRORS_BAD_CRC | L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT | @@ -3998,6 +4060,30 @@ loopback_test_done: return ret; } +#define BNX2_MAC_LOOPBACK_FAILED 1 +#define BNX2_PHY_LOOPBACK_FAILED 2 +#define BNX2_LOOPBACK_FAILED (BNX2_MAC_LOOPBACK_FAILED | \ + BNX2_PHY_LOOPBACK_FAILED) + +static int +bnx2_test_loopback(struct bnx2 *bp) +{ + int rc = 0; + + if (!netif_running(bp->dev)) + return BNX2_LOOPBACK_FAILED; + + bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); + spin_lock_bh(&bp->phy_lock); + bnx2_init_phy(bp); + spin_unlock_bh(&bp->phy_lock); + if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK)) + rc |= BNX2_MAC_LOOPBACK_FAILED; + if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK)) + rc |= BNX2_PHY_LOOPBACK_FAILED; + return rc; +} + #define NVRAM_SIZE 0x200 #define CRC32_RESIDUAL 0xdebb20e3 @@ -4167,7 +4253,7 @@ bnx2_restart_timer: static int bnx2_open(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int rc; bnx2_set_power_state(bp, PCI_D0); @@ -4280,7 +4366,7 @@ bnx2_reset_task(void *data) static void bnx2_tx_timeout(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); /* This allows the netif to be shutdown gracefully before resetting */ schedule_work(&bp->reset_task); @@ -4291,7 +4377,7 @@ bnx2_tx_timeout(struct net_device *dev) static void bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); bnx2_netif_stop(bp); @@ -4305,7 +4391,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) static void bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); bnx2_netif_stop(bp); @@ -4326,7 +4412,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) static int bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); dma_addr_t mapping; struct tx_bd *txbd; struct sw_bd *tx_buf; @@ -4455,7 +4541,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) static int bnx2_close(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); u32 reset_code; /* Calling flush_scheduled_work() may deadlock because @@ -4467,7 +4553,9 @@ bnx2_close(struct net_device *dev) bnx2_netif_stop(bp); del_timer_sync(&bp->timer); - if (bp->wol) + if (bp->flags & NO_WOL_FLAG) + reset_code = BNX2_DRV_MSG_CODE_UNLOAD; + else if (bp->wol) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; else reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; @@ -4501,7 +4589,7 @@ bnx2_close(struct net_device *dev) static struct net_device_stats * bnx2_get_stats(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); struct statistics_block *stats_blk = bp->stats_blk; struct net_device_stats *net_stats = &bp->net_stats; @@ -4575,7 +4663,7 @@ bnx2_get_stats(struct net_device *dev) static int bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); cmd->supported = SUPPORTED_Autoneg; if (bp->phy_flags & PHY_SERDES_FLAG) { @@ -4622,7 +4710,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); u8 autoneg = bp->autoneg; u8 req_duplex = bp->req_duplex; u16 req_line_speed = bp->req_line_speed; @@ -4694,7 +4782,7 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static void bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); @@ -4702,15 +4790,14 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0'; info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0'; info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0'; - info->fw_version[6] = (bp->fw_ver & 0xff) + '0'; - info->fw_version[1] = info->fw_version[3] = info->fw_version[5] = '.'; - info->fw_version[7] = 0; + info->fw_version[1] = info->fw_version[3] = '.'; + info->fw_version[5] = 0; } static void bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if (bp->flags & NO_WOL_FLAG) { wol->supported = 0; @@ -4729,7 +4816,7 @@ bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; @@ -4749,7 +4836,7 @@ bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int bnx2_nway_reset(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); u32 bmcr; if (!(bp->autoneg & AUTONEG_SPEED)) { @@ -4785,19 +4872,19 @@ bnx2_nway_reset(struct net_device *dev) static int bnx2_get_eeprom_len(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); - if (bp->flash_info == 0) + if (bp->flash_info == NULL) return 0; - return (int) bp->flash_info->total_size; + return (int) bp->flash_size; } static int bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *eebuf) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int rc; /* parameters already validated in ethtool_get_eeprom */ @@ -4811,7 +4898,7 @@ static int bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *eebuf) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int rc; /* parameters already validated in ethtool_set_eeprom */ @@ -4824,7 +4911,7 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, static int bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); memset(coal, 0, sizeof(struct ethtool_coalesce)); @@ -4846,7 +4933,7 @@ bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) static int bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); bp->rx_ticks = (u16) coal->rx_coalesce_usecs; if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff; @@ -4890,7 +4977,7 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) static void bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); ering->rx_max_pending = MAX_RX_DESC_CNT; ering->rx_mini_max_pending = 0; @@ -4907,7 +4994,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) static int bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if ((ering->rx_pending > MAX_RX_DESC_CNT) || (ering->tx_pending > MAX_TX_DESC_CNT) || @@ -4930,7 +5017,7 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) static void bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0); epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0); @@ -4940,7 +5027,7 @@ bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) static int bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); bp->req_flow_ctrl = 0; if (epause->rx_pause) @@ -4967,7 +5054,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) static u32 bnx2_get_rx_csum(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); return bp->rx_csum; } @@ -4975,7 +5062,7 @@ bnx2_get_rx_csum(struct net_device *dev) static int bnx2_set_rx_csum(struct net_device *dev, u32 data) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); bp->rx_csum = data; return 0; @@ -5124,7 +5211,7 @@ bnx2_self_test_count(struct net_device *dev) static void bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); if (etest->flags & ETH_TEST_FL_OFFLINE) { @@ -5140,10 +5227,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) buf[1] = 1; etest->flags |= ETH_TEST_FL_FAILED; } - if (bnx2_test_loopback(bp) != 0) { - buf[2] = 1; + if ((buf[2] = bnx2_test_loopback(bp)) != 0) etest->flags |= ETH_TEST_FL_FAILED; - } if (!netif_running(bp->dev)) { bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); @@ -5200,7 +5285,7 @@ static void bnx2_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *buf) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int i; u32 *hw_stats = (u32 *) bp->stats_blk; u8 *stats_len_arr = NULL; @@ -5240,7 +5325,7 @@ bnx2_get_ethtool_stats(struct net_device *dev, static int bnx2_phys_id(struct net_device *dev, u32 data) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int i; u32 save; @@ -5312,7 +5397,7 @@ static int bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); int err; switch(cmd) { @@ -5354,7 +5439,7 @@ static int bnx2_change_mac_addr(struct net_device *dev, void *p) { struct sockaddr *addr = p; - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; @@ -5370,7 +5455,7 @@ bnx2_change_mac_addr(struct net_device *dev, void *p) static int bnx2_change_mtu(struct net_device *dev, int new_mtu) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE)) @@ -5391,7 +5476,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) static void poll_bnx2(struct net_device *dev) { - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); disable_irq(bp->pdev->irq); bnx2_interrupt(bp->pdev->irq, dev, NULL); @@ -5409,7 +5494,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - bp = dev->priv; + bp = netdev_priv(dev); bp->flags = 0; bp->phy_flags = 0; @@ -5629,6 +5714,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } } + if (CHIP_NUM(bp) == CHIP_NUM_5708) + bp->flags |= NO_WOL_FLAG; + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { bp->tx_quick_cons_trip_int = bp->tx_quick_cons_trip; @@ -5725,7 +5813,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->ethtool_ops = &bnx2_ethtool_ops; dev->weight = 64; - bp = dev->priv; + bp = netdev_priv(dev); #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) dev->poll_controller = poll_bnx2; @@ -5784,7 +5872,7 @@ static void __devexit bnx2_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); flush_scheduled_work(); @@ -5803,7 +5891,7 @@ static int bnx2_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); u32 reset_code; if (!netif_running(dev)) @@ -5812,7 +5900,9 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) bnx2_netif_stop(bp); netif_device_detach(dev); del_timer_sync(&bp->timer); - if (bp->wol) + if (bp->flags & NO_WOL_FLAG) + reset_code = BNX2_DRV_MSG_CODE_UNLOAD; + else if (bp->wol) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; else reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; @@ -5826,7 +5916,7 @@ static int bnx2_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2 *bp = dev->priv; + struct bnx2 *bp = netdev_priv(dev); if (!netif_running(dev)) return 0; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 76bb5f1a250b..9f691cbd666b 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -1,6 +1,6 @@ /* bnx2.h: Broadcom NX2 network driver. * - * Copyright (c) 2004, 2005 Broadcom Corporation + * Copyright (c) 2004, 2005, 2006 Broadcom Corporation * * 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 @@ -277,19 +277,7 @@ struct statistics_block { * l2_fhdr definition */ struct l2_fhdr { -#if defined(__BIG_ENDIAN) - u16 l2_fhdr_errors; - u16 l2_fhdr_status; -#elif defined(__LITTLE_ENDIAN) - u16 l2_fhdr_status; - u16 l2_fhdr_errors; -#endif - #define L2_FHDR_ERRORS_BAD_CRC (1<<1) - #define L2_FHDR_ERRORS_PHY_DECODE (1<<2) - #define L2_FHDR_ERRORS_ALIGNMENT (1<<3) - #define L2_FHDR_ERRORS_TOO_SHORT (1<<4) - #define L2_FHDR_ERRORS_GIANT_FRAME (1<<5) - + u32 l2_fhdr_status; #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0) #define L2_FHDR_STATUS_RULE_P2 (1<<3) #define L2_FHDR_STATUS_RULE_P3 (1<<4) @@ -301,6 +289,14 @@ struct l2_fhdr { #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14) #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15) + #define L2_FHDR_ERRORS_BAD_CRC (1<<17) + #define L2_FHDR_ERRORS_PHY_DECODE (1<<18) + #define L2_FHDR_ERRORS_ALIGNMENT (1<<19) + #define L2_FHDR_ERRORS_TOO_SHORT (1<<20) + #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21) + #define L2_FHDR_ERRORS_TCP_XSUM (1<<28) + #define L2_FHDR_ERRORS_UDP_XSUM (1<<31) + u32 l2_fhdr_hash; #if defined(__BIG_ENDIAN) u16 l2_fhdr_pkt_len; @@ -3956,6 +3952,7 @@ struct bnx2 { #define NO_WOL_FLAG 8 #define USING_DAC_FLAG 0x10 #define USING_MSI_FLAG 0x20 +#define ASF_ENABLE_FLAG 0x40 u32 phy_flags; #define PHY_SERDES_FLAG 1 @@ -3986,6 +3983,7 @@ struct bnx2 { #define CHIP_ID_5706_A2 0x57060020 #define CHIP_ID_5708_A0 0x57080000 #define CHIP_ID_5708_B0 0x57081000 +#define CHIP_ID_5708_B1 0x57081010 #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) @@ -3998,7 +3996,7 @@ struct bnx2 { u16 bus_speed_mhz; u8 wol; - u8 fw_timed_out; + u8 pad; u16 fw_wr_seq; u16 fw_drv_pulse_wr_seq; @@ -4074,6 +4072,7 @@ struct bnx2 { struct net_device_stats net_stats; struct flash_spec *flash_info; + u32 flash_size; }; static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); @@ -4172,7 +4171,7 @@ struct fw_info { * the firmware has timed out, the driver will assume there is no firmware * running and there won't be any firmware-driver synchronization during a * driver reset. */ -#define FW_ACK_TIME_OUT_MS 50 +#define FW_ACK_TIME_OUT_MS 100 #define BNX2_DRV_RESET_SIGNATURE 0x00000000 @@ -4275,6 +4274,9 @@ struct fw_info { #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100 #define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200 +#define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040 +#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000 + #define BNX2_DEV_INFO_BC_REV 0x0000004c #define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050 diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index ab07a4900e9a..0c21bd849814 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -1,6 +1,6 @@ /* bnx2_fw.h: Broadcom NX2 network driver. * - * Copyright (c) 2004, 2005 Broadcom Corporation + * Copyright (c) 2004, 2005, 2006 Broadcom Corporation * * 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 @@ -978,20 +978,20 @@ static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; static int bnx2_RXP_b06FwReleaseMajor = 0x1; static int bnx2_RXP_b06FwReleaseMinor = 0x0; static int bnx2_RXP_b06FwReleaseFix = 0x0; -static u32 bnx2_RXP_b06FwStartAddr = 0x08003104; +static u32 bnx2_RXP_b06FwStartAddr = 0x08003184; static u32 bnx2_RXP_b06FwTextAddr = 0x08000000; -static int bnx2_RXP_b06FwTextLen = 0x562c; -static u32 bnx2_RXP_b06FwDataAddr = 0x08005660; +static int bnx2_RXP_b06FwTextLen = 0x588c; +static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0; static int bnx2_RXP_b06FwDataLen = 0x0; -static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000; -static int bnx2_RXP_b06FwRodataLen = 0x0; -static u32 bnx2_RXP_b06FwBssAddr = 0x08005680; -static int bnx2_RXP_b06FwBssLen = 0x1394; -static u32 bnx2_RXP_b06FwSbssAddr = 0x08005660; -static int bnx2_RXP_b06FwSbssLen = 0x18; -static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = { - 0x0a000c41, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e352e, - 0x38000000, 0x02050803, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, +static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890; +static int bnx2_RXP_b06FwRodataLen = 0x28; +static u32 bnx2_RXP_b06FwBssAddr = 0x08005900; +static int bnx2_RXP_b06FwBssLen = 0x13a4; +static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0; +static int bnx2_RXP_b06FwSbssLen = 0x1c; +static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = { + 0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e, + 0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -1513,408 +1513,435 @@ static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425660, - 0x3c030800, 0x24636a14, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, - 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x26103104, 0x3c1c0800, - 0x279c5660, 0x0e001035, 0x00000000, 0x0000000d, 0x3c080800, 0x8d023100, - 0x2c420080, 0x50400001, 0xad003100, 0x8d073100, 0x3c040800, 0x24840100, - 0x8f460100, 0x00071840, 0x00671821, 0x00031940, 0x00641021, 0xac460000, - 0x8f450104, 0x00831021, 0xac450004, 0x8f460108, 0xac460008, 0x8f45010c, - 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, 0xac450014, 0x8f460124, - 0xac460018, 0x8f450128, 0xac45001c, 0x8f464010, 0xac460020, 0x8f454014, - 0xac450024, 0x8f464018, 0xac460028, 0x8f45401c, 0xac45002c, 0x8f464020, - 0xac460030, 0x8f454024, 0xac450034, 0x8f464028, 0xac460038, 0x8f45402c, - 0xac45003c, 0x8f464030, 0xac460040, 0x8f454034, 0xac450044, 0x8f464038, - 0xac460048, 0x8f45403c, 0xac45004c, 0x8f464040, 0xac460050, 0x8f454044, - 0xac450054, 0x8f464048, 0xac460058, 0x8f45404c, 0x24e70001, 0x00402021, - 0xad073100, 0x03e00008, 0xac85005c, 0x8f820004, 0x9743010c, 0x00804821, - 0x00403021, 0x30421000, 0x10400010, 0x306affff, 0x30c20020, 0x1440000e, - 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, 0x3463ffff, - 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, 0x0a000cb1, - 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, 0x00405821, - 0x8f820010, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, 0x00c24024, - 0x3c031000, 0x15030015, 0x3c020001, 0x31420200, 0x54400012, 0x3c020001, - 0x9744010e, 0x24020003, 0xa342018b, 0x97850012, 0x24020002, 0x34e30002, - 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, 0xa744018e, - 0xa74501a6, 0xaf4801b8, 0x03e00008, 0x00001021, 0x3c020001, 0x00c21024, - 0x10400039, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, - 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, - 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000cec, 0x00021400, 0x9743011e, - 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x24020003, - 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, 0x3c02ffff, - 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, - 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f820010, 0x30434000, - 0x10600016, 0x00404021, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000, - 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b, - 0x3c020800, 0x24425680, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f, - 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01244825, 0x11200039, - 0x3c021000, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3046ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, - 0x8f85000c, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, - 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000d41, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, - 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, + 0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b, + 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, + 0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d, + 0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d, + 0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e, + 0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, + 0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004, + 0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824, + 0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008, + 0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020, + 0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, + 0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, + 0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, + 0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, + 0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012, + 0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002, + 0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, + 0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001, + 0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a, + 0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003, + 0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c, + 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, + 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, + 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, + 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, + 0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00, + 0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821, + 0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942, + 0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004, + 0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002, + 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, + 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, + 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x03e00008, 0x00001021, 0x00c21024, 0x104000e3, 0x3c020800, - 0x8c430030, 0x10600040, 0x31024000, 0x1040003e, 0x3c030f00, 0x00c31824, - 0x3c020100, 0x0043102b, 0x1440003a, 0x3c030800, 0x9742010e, 0x34e70002, + 0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800, + 0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824, + 0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, 0x24020080, 0x24030002, - 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, - 0x9742011e, 0x0a000d86, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, - 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, + 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080, + 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, + 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008, + 0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034, + 0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000, + 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002, + 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190, + 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, + 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, + 0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00, + 0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004, + 0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000, + 0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f, + 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001, + 0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, + 0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e, + 0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, + 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, + 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, + 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, + 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000, + 0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f, + 0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, + 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, + 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, + 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, + 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c, + 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, + 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001, + 0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004, + 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, + 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, + 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, - 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, + 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, - 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, - 0x3c030800, 0x8c620024, 0x30420008, 0x1040003e, 0x34e80002, 0x3c020f00, - 0x00c21024, 0x1440003b, 0x8d620034, 0x31420200, 0x10400038, 0x8d620034, - 0x9742010e, 0x30e7fffb, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, - 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, - 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000dca, 0x00021400, 0x9743011e, - 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, - 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, - 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, - 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x8d620034, 0x8f860004, 0x1040001a, 0x30c20100, 0x10400018, 0x3c020f00, - 0x00c21024, 0x3c030200, 0x10430014, 0x00000000, 0x8f82000c, 0x10400004, - 0x00000000, 0x9742011c, 0x0a000df8, 0x3044ffff, 0x9742011e, 0x3044ffff, - 0x3c030800, 0x8c620038, 0x3c030800, 0x2463003c, 0x2442ffff, 0x00822024, - 0x00831821, 0x90620000, 0x24420004, 0x0a000e0d, 0x000229c0, 0x00000000, - 0x00061602, 0x3042000f, 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, - 0x0062182b, 0x50600001, 0x24050800, 0x9742010e, 0x3107ffff, 0x3c038000, + 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024, + 0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf450180, 0xa742018c, - 0xa746018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000e26, - 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, - 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, - 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, - 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, - 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100, - 0x104000f9, 0x3c020800, 0x8c440024, 0x24030001, 0x14830038, 0x00404821, - 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, - 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, - 0x9743011c, 0x9742011e, 0x0a000e65, 0x00021400, 0x9743011e, 0x9742011c, - 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, - 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, - 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, - 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, - 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, - 0x00001021, 0x30820001, 0x10400037, 0x30ea0004, 0x9742010e, 0x30e8fffb, + 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002, + 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190, + 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024, + 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, + 0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e, + 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180, + 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, + 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, + 0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, + 0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, - 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, - 0x0a000e9f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, - 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, - 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, - 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, - 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, - 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420004, - 0x10400039, 0x8d220024, 0x9742010e, 0x30e8fffb, 0x3c038000, 0x24420004, - 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, - 0x97840006, 0x8f85000c, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c, - 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000eda, - 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, - 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, - 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, - 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, - 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420008, 0x10400036, - 0x00000000, 0x9742010e, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, - 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, - 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000f14, 0x00021400, 0x9743011e, - 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, - 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, - 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, + 0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, + 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, + 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x1540004a, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, 0xa4800010, - 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024, - 0x30420001, 0x10400037, 0x00001021, 0x9742010e, 0x34e60002, 0x3c038000, - 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, 0xa742018c, - 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000f5e, - 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, - 0x8f840010, 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, + 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070, + 0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003, + 0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880, + 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021, + 0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000, + 0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000, + 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021, + 0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080, + 0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400, + 0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880, + 0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00, + 0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400, + 0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982, + 0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026, + 0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000, + 0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080, + 0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800, + 0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800, + 0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104, + 0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004, + 0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010, + 0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014, + 0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000, + 0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c, + 0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001, + 0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024, + 0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001, + 0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009, + 0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78, + 0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006, + 0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021, + 0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124, + 0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010, + 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, + 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000, + 0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009, + 0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047, + 0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b, + 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000, + 0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002, + 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, + 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000, + 0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000, + 0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, + 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, + 0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040, + 0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea, + 0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8, + 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, + 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, + 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800, + 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001, + 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000, + 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, + 0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd, + 0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002, + 0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000, + 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, + 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, + 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800, + 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001, + 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000, + 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, + 0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, + 0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188, + 0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, - 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, + 0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe8, - 0xafbf0010, 0x8f460128, 0x8f84000c, 0xaf460020, 0x8f450104, 0x8f420100, - 0x24030800, 0xaf850004, 0xaf820010, 0xaf4301b8, 0x1080000a, 0x3c020800, - 0x8c430034, 0x10600007, 0x30a22000, 0x10400005, 0x34a30100, 0x8f820008, - 0xaf830004, 0x24420001, 0xaf820008, 0x3c020800, 0x8c4300c0, 0x10600006, - 0x3c030800, 0x8c6200c4, 0x24040001, 0x24420001, 0x0a000fc0, 0xac6200c4, - 0x8f820004, 0x3c030010, 0x00431024, 0x14400009, 0x3c02001f, 0x3c030800, - 0x8c620020, 0x00002021, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, - 0x00402021, 0x3442ff00, 0x14c20009, 0x2403bfff, 0x3c030800, 0x8c620020, - 0x24040001, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, 0x00402021, - 0x8f820010, 0x00431024, 0x14400006, 0x00000000, 0xaf400048, 0x0e001144, - 0xaf400040, 0x0a000fc0, 0x00402021, 0x0e0014c9, 0x00000000, 0x00402021, - 0x10800005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000, - 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, - 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148, - 0x3c027000, 0x00621824, 0x3c023000, 0x10620021, 0x0043102b, 0x14400006, - 0x3c024000, 0x3c022000, 0x10620009, 0x3c024000, 0x0a00102b, 0x00000000, - 0x10620045, 0x3c025000, 0x10620047, 0x3c024000, 0x0a00102b, 0x00000000, + 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, + 0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, - 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0xaf4301b8, 0x0a00102b, - 0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff, - 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d, - 0x36053000, 0x0a001012, 0x3c038000, 0x12020007, 0x00000000, 0x0a00101f, - 0x00000000, 0x0e00111f, 0x00000000, 0x0a001010, 0x00402021, 0x0e001131, - 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144, - 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00102b, 0x3c024000, 0x0000000d, - 0x00000000, 0x24000295, 0x0a00102b, 0x3c024000, 0x0e0013a7, 0x00000000, - 0x0a00102b, 0x3c024000, 0x0e001552, 0x00000000, 0x3c024000, 0xaf420178, - 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, 0x3c04600c, 0xafbf0014, - 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024, - 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808, - 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001, - 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574, - 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff, - 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x34420200, 0xae021980, - 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, 0x10400004, 0x32020002, - 0x0e000f7d, 0x00000000, 0x32020002, 0x1040fff6, 0x00000000, 0x0e000fcb, - 0x00000000, 0x0a00105c, 0x00000000, 0x27bdffe8, 0x3c04600c, 0xafbf0014, - 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024, - 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808, - 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001, - 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574, - 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff, - 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x8fbf0014, 0x34420200, - 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x30a5ffff, 0x30c6ffff, - 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x97830006, 0x8f82000c, 0xaf440180, 0xa745018c, 0xa746018e, - 0x10400005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a0010ad, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, - 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, - 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, - 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, - 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, 0x27bdffe0, - 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff, - 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, - 0x24020003, 0x0600001d, 0x36053000, 0x0a00110a, 0x3c038000, 0x12020007, - 0x00000000, 0x0a001117, 0x00000000, 0x0e00111f, 0x00000000, 0x0a001108, - 0x00402021, 0x0e001131, 0x00000000, 0x00402021, 0x36053000, 0x3c038000, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, - 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00111b, - 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000295, 0x8fbf0018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d, - 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821, - 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008, - 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e, - 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821, - 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024, - 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0xafbf0048, - 0x93620023, 0x30420010, 0x1440025b, 0x24020001, 0x93420116, 0x93630005, - 0x34424000, 0x30630001, 0x14600005, 0x03425821, 0x0e001548, 0x00000000, - 0x0a0013a5, 0x8fbf0048, 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, - 0x00641824, 0x10600012, 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, + 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, + 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, + 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, + 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000, + 0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000, + 0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, + 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, + 0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, + 0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880, + 0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, + 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, + 0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880, + 0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, + 0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c, + 0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f, + 0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890, + 0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4, + 0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023, + 0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002, + 0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003, + 0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200, + 0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002, + 0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200, + 0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004, + 0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003, + 0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002, + 0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821, + 0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4, + 0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c, + 0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054, + 0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010, + 0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001, + 0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c, + 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012, + 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, + 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a, + 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, + 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a, + 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013, + 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0, + 0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000, + 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c, + 0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229, + 0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038, + 0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040, + 0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d, + 0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004, + 0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020, + 0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff, + 0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001, + 0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180, + 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022, + 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, + 0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023, + 0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001, + 0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020, + 0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, + 0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a, + 0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c, + 0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021, + 0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8, + 0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823, + 0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800, + 0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026, + 0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821, + 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff, + 0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800, + 0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4, + 0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010, + 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000, + 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000, + 0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff, + 0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0, + 0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, + 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d, + 0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b, + 0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2, + 0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004, + 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037, + 0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800, + 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, + 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, + 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a, + 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012, + 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024, + 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000, + 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c, + 0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c, + 0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003, + 0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004, + 0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e, + 0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015, + 0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018, + 0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020, + 0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011, + 0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b, + 0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020, + 0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c, + 0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005, + 0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a, + 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c, + 0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020, + 0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006, + 0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001, + 0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021, + 0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6, + 0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000, + 0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024, + 0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010, + 0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002, + 0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023, + 0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c, + 0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c, + 0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020, + 0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9, + 0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023, + 0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a, + 0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020, + 0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7, + 0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022, + 0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009, + 0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018, + 0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8, + 0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e, + 0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413, + 0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, + 0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, + 0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, + 0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, + 0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, + 0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c, + 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008, + 0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02, + 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f, + 0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046, + 0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e, + 0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b, + 0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02, + 0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e, + 0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b, + 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000, + 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a, + 0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff, + 0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, + 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, + 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, + 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821, + 0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144, + 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, + 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, + 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000, + 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821, + 0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88, + 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144, + 0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028, + 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808, + 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b, + 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008, + 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004, + 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, + 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005, + 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b, + 0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000, + 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, + 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b, + 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008, + 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, + 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010, + 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8, + 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, + 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004, + 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8, + 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, + 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b, + 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, + 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4, + 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008, + 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011, + 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000, + 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040, + 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008, + 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, + 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4, + 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001, + 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025, + 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, - 0x0a001181, 0xa0a3000a, 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, - 0x3c038000, 0x27450180, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, - 0x8f420128, 0xaca20000, 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, - 0x24020002, 0xa0a3000a, 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, - 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, - 0xaca40018, 0x0e001548, 0xaf4201b8, 0x0a0013a5, 0x8fbf0048, 0x8f820000, - 0x10400016, 0x00000000, 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, - 0x00000000, 0x8ca3000c, 0x8f620030, 0x1462020c, 0x24020001, 0x8ca30010, - 0x8f62002c, 0x14620208, 0x24020001, 0x9763003a, 0x95620000, 0x14430204, - 0x24020001, 0x97630038, 0x95620002, 0x14430200, 0x24020001, 0xaf400048, - 0xaf400054, 0xaf400040, 0x8f690040, 0x8f6a0048, 0x01497023, 0x05c10004, - 0x00000000, 0x0000000d, 0x00000000, 0x24000169, 0x9742011a, 0x3046ffff, - 0x10c00004, 0x8d680004, 0x01061021, 0x0a0011b8, 0x2445ffff, 0x01002821, - 0x916c000d, 0xa7a00020, 0xa3a0001a, 0xafa00028, 0x9362003f, 0x31830004, - 0x1060003a, 0x304700ff, 0x24040012, 0x14e40006, 0x24020001, 0x3c040800, - 0x8c830028, 0x24630001, 0x0a00128d, 0xac830028, 0x8f620044, 0x15020010, - 0x27a60010, 0x27450180, 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, - 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x8f620044, 0x01021023, - 0x0440001a, 0x010a1023, 0x044100ae, 0x24020001, 0x3c020800, 0x8c4300d8, - 0x10600004, 0x24020001, 0xa7a20020, 0x0a0011ee, 0xafa90028, 0x2402001a, - 0xa7a20020, 0x24020020, 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, - 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x0a001272, 0x00000000, 0x0a00128d, 0x24020001, 0x01286823, - 0x19a00016, 0x00cd102a, 0x54400007, 0x318c00fe, 0x55a6000f, 0x010d4021, - 0x31820001, 0x5440000c, 0x010d4021, 0x318c00fe, 0x00c06821, 0x3c040800, - 0x8c8300c8, 0x00003021, 0x24020001, 0xa7a20020, 0xafa90028, 0x24630001, - 0x0a001212, 0xac8300c8, 0x00cd1023, 0x0a001212, 0x3046ffff, 0x00006821, - 0x2542ffff, 0x00a21823, 0x1860001e, 0x0066102a, 0x14400018, 0x01402821, - 0x97a20020, 0x3c040800, 0x8c8300cc, 0xafa90028, 0x34420001, 0x24630001, - 0xa7a20020, 0x01091026, 0x2c420001, 0xac8300cc, 0x2dc30001, 0x00431024, - 0x1440000a, 0x00c01821, 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x00c31023, - 0x3046ffff, 0x0a00123d, 0x318c00f6, 0x01091023, 0x18400008, 0x97a20020, - 0x3c040800, 0x8c8300d4, 0xafa80028, 0x34420400, 0x24630001, 0xa7a20020, - 0xac8300d4, 0x31820002, 0x1040001c, 0x31820010, 0x8f620044, 0x1502000d, - 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001, - 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, - 0x00000000, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001, - 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, - 0x00000000, 0x54400003, 0x8d6a0008, 0x0a00128d, 0x24020001, 0x8f630054, - 0x2542ffff, 0x00431023, 0x1840002e, 0x97a20020, 0x27a60010, 0x3c040800, - 0x8c8300d0, 0x27450180, 0x3c078000, 0xafa90028, 0x34420001, 0x24630001, - 0xa7a20020, 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, - 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, - 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, - 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, - 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, - 0x3c031000, 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a0013a5, - 0x8fbf0048, 0x31820020, 0x10400011, 0x00000000, 0x95620012, 0x0046102b, - 0x10400008, 0x97a20020, 0x95660012, 0x10c00003, 0x01061021, 0x0a00129e, - 0x2445ffff, 0x01002821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004, - 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x38e3000a, 0x2c630001, 0x38e2000c, - 0x2c420001, 0x00621825, 0x14600003, 0x2402000e, 0x54e2002a, 0x00003021, - 0x50c00008, 0x9564000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a0012b6, - 0x2445ffff, 0x01002821, 0x9564000e, 0x93630035, 0x8f62004c, 0x00642004, - 0x008a2021, 0x00821023, 0x1840001d, 0x00000000, 0x8f620018, 0x01021023, - 0x1c40000f, 0x97a20020, 0x8f620018, 0x15020016, 0x00000000, 0x8f62001c, - 0x01421023, 0x1c400008, 0x97a20020, 0x8f62001c, 0x1542000f, 0x00000000, - 0x8f620058, 0x00821023, 0x1840000b, 0x97a20020, 0xafa50028, 0xafa80034, - 0xafaa0038, 0xafa4003c, 0x34420020, 0x0a0012da, 0xa7a20020, 0x01204021, - 0x01002821, 0x8f640058, 0x8f62004c, 0x01421023, 0x18400009, 0x00000000, - 0x8f620054, 0x01421023, 0x1c400005, 0x97a20020, 0xafa50028, 0xafaa0024, - 0x0a0012f2, 0x34420040, 0x9742011a, 0x1440000c, 0x24020014, 0x8f620058, - 0x14820009, 0x24020014, 0x8f63004c, 0x8f620054, 0x10620004, 0x97a20020, - 0xafa50028, 0x34420080, 0xa7a20020, 0x24020014, 0x10e2000a, 0x28e20015, - 0x10400005, 0x2402000c, 0x10e20006, 0x31820001, 0x0a001333, 0x00000000, - 0x24020016, 0x14e20035, 0x31820001, 0x8f620084, 0x24420001, 0x15420031, - 0x31820001, 0x24020014, 0x10e20021, 0x28e20015, 0x10400005, 0x2402000c, - 0x10e20008, 0x31820001, 0x0a001333, 0x00000000, 0x24020016, 0x10e2000c, - 0x31820001, 0x0a001333, 0x00000000, 0x97a30020, 0x2402000e, 0xafa50028, - 0xa3a70022, 0xa3a20023, 0xafaa0024, 0x34630054, 0x0a001332, 0xa7a30020, - 0x97a20020, 0x93a4001a, 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, - 0xafaa0024, 0x3442005d, 0x34840002, 0xa7a20020, 0x0a001332, 0xa3a4001a, - 0x97a20020, 0x24030012, 0xa3a30023, 0x93a3001a, 0xafa50028, 0xa3a70022, - 0xafaa0024, 0x3042fffe, 0x3442005c, 0x34630002, 0xa7a20020, 0xa3a3001a, - 0x31820001, 0x10400030, 0x2402000c, 0x10e20013, 0x28e2000d, 0x10400005, - 0x2402000a, 0x10e20008, 0x97a20020, 0x0a001365, 0x31820009, 0x2402000e, - 0x10e2001b, 0x31820009, 0x0a001366, 0x0002102b, 0x93a4001a, 0x24030008, - 0xafa50028, 0xa3a70022, 0xa3a30023, 0x0a001361, 0x34420013, 0x97a30020, - 0x30620004, 0x14400005, 0x93a2001a, 0x3463001b, 0xa7a30020, 0x0a001354, - 0x24030016, 0x3463001b, 0xa7a30020, 0x24030010, 0xafa50028, 0xa3a70022, - 0xa3a30023, 0x34420002, 0x0a001364, 0xa3a2001a, 0x97a20020, 0x93a4001a, - 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, 0x3442001b, 0x34840002, - 0xa7a20020, 0xa3a4001a, 0x31820009, 0x0002102b, 0x00021023, 0x30420007, - 0x10c00017, 0x34440003, 0x8f820014, 0x24030800, 0x27450180, 0x24420001, - 0xaf820014, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, 0x93440120, - 0x3c031000, 0xa4a6000e, 0xacaa0024, 0xaca80028, 0x008d2021, 0xa4a4000c, - 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a001381, 0xa7a20020, - 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028, - 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b, - 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023, - 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038, - 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x00c01021, - 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f470140, 0x8f460148, 0x3c028000, - 0x00c24024, 0x00062c02, 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, - 0x2862001a, 0x1040001f, 0x24020008, 0x106200be, 0x28620009, 0x1040000d, - 0x24020001, 0x10620046, 0x28620002, 0x50400005, 0x24020006, 0x1060002e, - 0x00a01821, 0x0a0014c4, 0x00000000, 0x1062005b, 0x00a01821, 0x0a0014c4, - 0x00000000, 0x2402000b, 0x10620084, 0x2862000c, 0x10400005, 0x24020009, - 0x106200bc, 0x00061c02, 0x0a0014c4, 0x00000000, 0x2402000e, 0x106200b7, - 0x00061c02, 0x0a0014c4, 0x00000000, 0x28620021, 0x10400009, 0x2862001f, - 0x104000c1, 0x2402001b, 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, - 0x0a0014c4, 0x00000000, 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, - 0x24020080, 0x1062005a, 0x00a01821, 0x0a0014c4, 0x00000000, 0x240200c9, - 0x106200cd, 0x30c5ffff, 0x0a0014c4, 0x00000000, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, - 0xac800004, 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, - 0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, - 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0436a08, 0x24426a08, - 0xac470008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, - 0xa082000a, 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, - 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, - 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, - 0x91026a08, 0x00002821, 0x10400002, 0x25076a08, 0x8ce50008, 0xac850004, - 0xa4830008, 0x91036a08, 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, - 0xa083000a, 0x8f420144, 0xac820024, 0x91036a08, 0x10600002, 0x00001021, - 0x8ce20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006a08, - 0x03e00008, 0xac400808, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, - 0x24020002, 0xa082000b, 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, - 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, - 0x93620005, 0x30420004, 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, - 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, - 0x93620005, 0x3c038000, 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, - 0xaf430020, 0x93620005, 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, - 0xac870000, 0xa082000b, 0xaf4301b8, 0x0a001473, 0x00061c02, 0x0000000d, - 0x03e00008, 0x00000000, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, - 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, - 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, - 0xac830024, 0x03e00008, 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, - 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, - 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, - 0x03e00008, 0xaf4301b8, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, - 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, - 0xac870000, 0xac800004, 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, - 0x03e00008, 0xaf4201b8, 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, - 0x1440fffd, 0x24020002, 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, - 0x0a00147e, 0xa082000b, 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020002, 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, - 0xa7430188, 0xaf4401a4, 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, - 0x0000000d, 0x03e00008, 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, - 0x3042003e, 0x14400011, 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, - 0x10400005, 0x00000000, 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, - 0xaf400054, 0xaf400040, 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, - 0x24020001, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020002, 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, - 0xa7430188, 0xaf4501a4, 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, - 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, - 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, - 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, - 0xa0a2000b, 0x3c021000, 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, - 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, - 0xaf4201b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, 0x03e00008, - 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, 0x00803021, - 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, - 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, - 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, - 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, - 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, 0x3c031000, - 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, 0xaf400050, - 0x27bdffe8, 0xafbf0010, 0x0e001032, 0x00000000, 0x00002021, 0x0e000c99, - 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, 0x27450180, - 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, 0xaca20004, - 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, 0x10e0000a, - 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, 0x54e20005, - 0xa0a0000a, 0x24020001, 0x0a001571, 0xa0a2000a, 0xa0a0000a, 0x3c021000, - 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, 0x00000000, - 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, - 0x03e00008, 0x00000000, 0x0a001587, 0x00a01021, 0xac860000, 0x00000000, - 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, - 0x00000000, 0x00000000 }; + 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, + 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001, + 0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008, + 0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, + 0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, + 0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, + 0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, + 0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, + 0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000, + 0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, + 0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, + 0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, + 0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, + 0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a, + 0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, + 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, + 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021, + 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, + 0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 }; static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; -static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; -static u32 bnx2_RXP_b06FwBss[(0x1394/4) + 1] = { 0x0 }; -static u32 bnx2_RXP_b06FwSbss[(0x18/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = { + 0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680, + 0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 }; +static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; static u32 bnx2_rv2p_proc1[] = { 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004, diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2582d98ef5c3..e0f51afec778 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -576,7 +576,7 @@ static int bond_update_speed_duplex(struct slave *slave) slave->duplex = DUPLEX_FULL; if (slave_dev->ethtool_ops) { - u32 res; + int res; if (!slave_dev->ethtool_ops->get_settings) { return -1; @@ -1145,7 +1145,8 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) } #define BOND_INTERSECT_FEATURES \ - (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) + (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ + NETIF_F_TSO|NETIF_F_UFO) /* * Compute the common dev->feature set available to all slaves. Some @@ -1168,6 +1169,16 @@ static int bond_compute_features(struct bonding *bond) NETIF_F_HW_CSUM))) features &= ~NETIF_F_SG; + /* + * features will include NETIF_F_TSO (NETIF_F_UFO) iff all + * slave devices support NETIF_F_TSO (NETIF_F_UFO), which + * implies that all slaves also support scatter-gather + * (NETIF_F_SG), which implies that features also includes + * NETIF_F_SG. So no need to check whether we have an + * illegal combination of NETIF_F_{TSO,UFO} and + * !NETIF_F_SG + */ + features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); bond_dev->features = features; @@ -4080,6 +4091,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, static struct ethtool_ops bond_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, + .get_tso = ethtool_op_get_tso, + .get_ufo = ethtool_op_get_ufo, .get_sg = ethtool_op_get_sg, .get_drvinfo = bond_ethtool_get_drvinfo, }; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 32d13da43a0b..041bcc583557 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -260,7 +260,7 @@ static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, char *ifname; int i, res, found, ret = count; struct slave *slave; - struct net_device *dev = 0; + struct net_device *dev = NULL; struct bonding *bond = to_bond(cd); /* Quick sanity check -- is the bond interface up? */ @@ -995,7 +995,7 @@ static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, s printk(KERN_INFO DRV_NAME ": %s: Setting primary slave to None.\n", bond->dev->name); - bond->primary_slave = 0; + bond->primary_slave = NULL; bond_select_active_slave(bond); } else { printk(KERN_INFO DRV_NAME @@ -1123,7 +1123,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b printk(KERN_INFO DRV_NAME ": %s: Setting active slave to None.\n", bond->dev->name); - bond->primary_slave = 0; + bond->primary_slave = NULL; bond_select_active_slave(bond); } else { printk(KERN_INFO DRV_NAME diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index dde631f8f685..6e295fce5c6f 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -335,6 +335,30 @@ static inline void cas_mask_intr(struct cas *cp) cas_disable_irq(cp, i); } +static inline void cas_buffer_init(cas_page_t *cp) +{ + struct page *page = cp->buffer; + atomic_set((atomic_t *)&page->lru.next, 1); +} + +static inline int cas_buffer_count(cas_page_t *cp) +{ + struct page *page = cp->buffer; + return atomic_read((atomic_t *)&page->lru.next); +} + +static inline void cas_buffer_inc(cas_page_t *cp) +{ + struct page *page = cp->buffer; + atomic_inc((atomic_t *)&page->lru.next); +} + +static inline void cas_buffer_dec(cas_page_t *cp) +{ + struct page *page = cp->buffer; + atomic_dec((atomic_t *)&page->lru.next); +} + static void cas_enable_irq(struct cas *cp, const int ring) { if (ring == 0) { /* all but TX_DONE */ @@ -472,6 +496,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page) { pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size, PCI_DMA_FROMDEVICE); + cas_buffer_dec(page); __free_pages(page->buffer, cp->page_order); kfree(page); return 0; @@ -501,6 +526,7 @@ static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags) page->buffer = alloc_pages(flags, cp->page_order); if (!page->buffer) goto page_err; + cas_buffer_init(page); page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0, cp->page_size, PCI_DMA_FROMDEVICE); return page; @@ -579,7 +605,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags) list_for_each_safe(elem, tmp, &list) { cas_page_t *page = list_entry(elem, cas_page_t, list); - if (page_count(page->buffer) > 1) + if (cas_buffer_count(page) > 1) continue; list_del(elem); @@ -1347,7 +1373,7 @@ static inline cas_page_t *cas_page_spare(struct cas *cp, const int index) cas_page_t *page = cp->rx_pages[1][index]; cas_page_t *new; - if (page_count(page->buffer) == 1) + if (cas_buffer_count(page) == 1) return page; new = cas_page_dequeue(cp); @@ -1367,7 +1393,7 @@ static cas_page_t *cas_page_swap(struct cas *cp, const int ring, cas_page_t **page1 = cp->rx_pages[1]; /* swap if buffer is in use */ - if (page_count(page0[index]->buffer) > 1) { + if (cas_buffer_count(page0[index]) > 1) { cas_page_t *new = cas_page_spare(cp, index); if (new) { page1[index] = page0[index]; @@ -2039,6 +2065,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb->len += hlen - swivel; get_page(page->buffer); + cas_buffer_inc(page); frag->page = page->buffer; frag->page_offset = off; frag->size = hlen - swivel; @@ -2063,6 +2090,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, frag++; get_page(page->buffer); + cas_buffer_inc(page); frag->page = page->buffer; frag->page_offset = 0; frag->size = hlen; @@ -2225,7 +2253,7 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num) released = 0; while (entry != last) { /* make a new buffer if it's still in use */ - if (page_count(page[entry]->buffer) > 1) { + if (cas_buffer_count(page[entry]) > 1) { cas_page_t *new = cas_page_dequeue(cp); if (!new) { /* let the timer know that we need to diff --git a/drivers/net/e100.c b/drivers/net/e100.c index bf1fd2b98bf8..24253c807e55 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2752,8 +2752,6 @@ static int e100_resume(struct pci_dev *pdev) retval = pci_enable_wake(pdev, 0, 0); if (retval) DPRINTK(PROBE,ERR, "Error clearing wake events\n"); - if(e100_hw_init(nic)) - DPRINTK(HW, ERR, "e100_hw_init failed\n"); netif_device_attach(netdev); if(netif_running(netdev)) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d252297e4db0..5cedc81786e3 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -121,7 +121,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - if(hw->media_type == e1000_media_type_copper) { + if (hw->media_type == e1000_media_type_copper) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | @@ -133,7 +133,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->advertising = ADVERTISED_TP; - if(hw->autoneg == 1) { + if (hw->autoneg == 1) { ecmd->advertising |= ADVERTISED_Autoneg; /* the e1000 autoneg seems to match ethtool nicely */ @@ -144,7 +144,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->port = PORT_TP; ecmd->phy_address = hw->phy_addr; - if(hw->mac_type == e1000_82543) + if (hw->mac_type == e1000_82543) ecmd->transceiver = XCVR_EXTERNAL; else ecmd->transceiver = XCVR_INTERNAL; @@ -160,13 +160,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->port = PORT_FIBRE; - if(hw->mac_type >= e1000_82545) + if (hw->mac_type >= e1000_82545) ecmd->transceiver = XCVR_INTERNAL; else ecmd->transceiver = XCVR_EXTERNAL; } - if(netif_carrier_ok(adapter->netdev)) { + if (netif_carrier_ok(adapter->netdev)) { e1000_get_speed_and_duplex(hw, &adapter->link_speed, &adapter->link_duplex); @@ -175,7 +175,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) /* unfortunatly FULL_DUPLEX != DUPLEX_FULL * and HALF_DUPLEX != DUPLEX_HALF */ - if(adapter->link_duplex == FULL_DUPLEX) + if (adapter->link_duplex == FULL_DUPLEX) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; @@ -205,11 +205,11 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if (ecmd->autoneg == AUTONEG_ENABLE) { hw->autoneg = 1; - if(hw->media_type == e1000_media_type_fiber) + if (hw->media_type == e1000_media_type_fiber) hw->autoneg_advertised = ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Autoneg; - else + else hw->autoneg_advertised = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | @@ -219,12 +219,12 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ADVERTISED_TP; ecmd->advertising = hw->autoneg_advertised; } else - if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) + if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) return -EINVAL; /* reset the link */ - if(netif_running(adapter->netdev)) { + if (netif_running(adapter->netdev)) { e1000_down(adapter); e1000_reset(adapter); e1000_up(adapter); @@ -241,14 +241,14 @@ e1000_get_pauseparam(struct net_device *netdev, struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - pause->autoneg = + pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if(hw->fc == e1000_fc_rx_pause) + + if (hw->fc == e1000_fc_rx_pause) pause->rx_pause = 1; - else if(hw->fc == e1000_fc_tx_pause) + else if (hw->fc == e1000_fc_tx_pause) pause->tx_pause = 1; - else if(hw->fc == e1000_fc_full) { + else if (hw->fc == e1000_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } @@ -260,31 +260,30 @@ e1000_set_pauseparam(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - + adapter->fc_autoneg = pause->autoneg; - if(pause->rx_pause && pause->tx_pause) + if (pause->rx_pause && pause->tx_pause) hw->fc = e1000_fc_full; - else if(pause->rx_pause && !pause->tx_pause) + else if (pause->rx_pause && !pause->tx_pause) hw->fc = e1000_fc_rx_pause; - else if(!pause->rx_pause && pause->tx_pause) + else if (!pause->rx_pause && pause->tx_pause) hw->fc = e1000_fc_tx_pause; - else if(!pause->rx_pause && !pause->tx_pause) + else if (!pause->rx_pause && !pause->tx_pause) hw->fc = e1000_fc_none; hw->original_fc = hw->fc; - if(adapter->fc_autoneg == AUTONEG_ENABLE) { - if(netif_running(adapter->netdev)) { + if (adapter->fc_autoneg == AUTONEG_ENABLE) { + if (netif_running(adapter->netdev)) { e1000_down(adapter); e1000_up(adapter); } else e1000_reset(adapter); - } - else + } else return ((hw->media_type == e1000_media_type_fiber) ? e1000_setup_link(hw) : e1000_force_mac_fc(hw)); - + return 0; } @@ -301,14 +300,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data) struct e1000_adapter *adapter = netdev_priv(netdev); adapter->rx_csum = data; - if(netif_running(netdev)) { + if (netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); } else e1000_reset(adapter); return 0; } - + static uint32_t e1000_get_tx_csum(struct net_device *netdev) { @@ -320,7 +319,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if(adapter->hw.mac_type < e1000_82543) { + if (adapter->hw.mac_type < e1000_82543) { if (!data) return -EINVAL; return 0; @@ -339,8 +338,8 @@ static int e1000_set_tso(struct net_device *netdev, uint32_t data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if((adapter->hw.mac_type < e1000_82544) || - (adapter->hw.mac_type == e1000_82547)) + if ((adapter->hw.mac_type < e1000_82544) || + (adapter->hw.mac_type == e1000_82547)) return data ? -EINVAL : 0; if (data) @@ -348,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) else netdev->features &= ~NETIF_F_TSO; return 0; -} +} #endif /* NETIF_F_TSO */ static uint32_t @@ -365,7 +364,7 @@ e1000_set_msglevel(struct net_device *netdev, uint32_t data) adapter->msg_enable = data; } -static int +static int e1000_get_regs_len(struct net_device *netdev) { #define E1000_REGS_LEN 32 @@ -401,7 +400,7 @@ e1000_get_regs(struct net_device *netdev, regs_buff[11] = E1000_READ_REG(hw, TIDV); regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */ - if(hw->phy_type == e1000_phy_igp) { + if (hw->phy_type == e1000_phy_igp) { e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, IGP01E1000_PHY_AGC_A); e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A & @@ -455,7 +454,7 @@ e1000_get_regs(struct net_device *netdev, e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ - if(hw->mac_type >= e1000_82540 && + if (hw->mac_type >= e1000_82540 && hw->media_type == e1000_media_type_copper) { regs_buff[26] = E1000_READ_REG(hw, MANC); } @@ -479,7 +478,7 @@ e1000_get_eeprom(struct net_device *netdev, int ret_val = 0; uint16_t i; - if(eeprom->len == 0) + if (eeprom->len == 0) return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); @@ -489,16 +488,16 @@ e1000_get_eeprom(struct net_device *netdev, eeprom_buff = kmalloc(sizeof(uint16_t) * (last_word - first_word + 1), GFP_KERNEL); - if(!eeprom_buff) + if (!eeprom_buff) return -ENOMEM; - if(hw->eeprom.type == e1000_eeprom_spi) + if (hw->eeprom.type == e1000_eeprom_spi) ret_val = e1000_read_eeprom(hw, first_word, last_word - first_word + 1, eeprom_buff); else { for (i = 0; i < last_word - first_word + 1; i++) - if((ret_val = e1000_read_eeprom(hw, first_word + i, 1, + if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1, &eeprom_buff[i]))) break; } @@ -525,10 +524,10 @@ e1000_set_eeprom(struct net_device *netdev, int max_len, first_word, last_word, ret_val = 0; uint16_t i; - if(eeprom->len == 0) + if (eeprom->len == 0) return -EOPNOTSUPP; - if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; max_len = hw->eeprom.word_size * 2; @@ -536,19 +535,19 @@ e1000_set_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if(!eeprom_buff) + if (!eeprom_buff) return -ENOMEM; ptr = (void *)eeprom_buff; - if(eeprom->offset & 1) { + if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ ret_val = e1000_read_eeprom(hw, first_word, 1, &eeprom_buff[0]); ptr++; } - if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { + if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ ret_val = e1000_read_eeprom(hw, last_word, 1, @@ -567,9 +566,9 @@ e1000_set_eeprom(struct net_device *netdev, ret_val = e1000_write_eeprom(hw, first_word, last_word - first_word + 1, eeprom_buff); - /* Update the checksum over the first part of the EEPROM if needed + /* Update the checksum over the first part of the EEPROM if needed * and flush shadow RAM for 82573 conrollers */ - if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || + if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || (hw->mac_type == e1000_82573))) e1000_update_eeprom_checksum(hw); @@ -633,7 +632,7 @@ e1000_get_ringparam(struct net_device *netdev, ring->rx_jumbo_pending = 0; } -static int +static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { @@ -670,25 +669,25 @@ e1000_set_ringparam(struct net_device *netdev, txdr = adapter->tx_ring; rxdr = adapter->rx_ring; - if((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD); rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD)); - E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); + E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD); txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD)); - E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); + E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); for (i = 0; i < adapter->num_tx_queues; i++) txdr[i].count = txdr->count; for (i = 0; i < adapter->num_rx_queues; i++) rxdr[i].count = rxdr->count; - if(netif_running(adapter->netdev)) { + if (netif_running(adapter->netdev)) { /* Try to get new resources before deleting old */ if ((err = e1000_setup_all_rx_resources(adapter))) goto err_setup_rx; @@ -708,7 +707,7 @@ e1000_set_ringparam(struct net_device *netdev, kfree(rx_old); adapter->rx_ring = rx_new; adapter->tx_ring = tx_new; - if((err = e1000_up(adapter))) + if ((err = e1000_up(adapter))) return err; } @@ -727,10 +726,10 @@ err_setup_rx: uint32_t pat, value; \ uint32_t test[] = \ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ - for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \ + for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \ E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ value = E1000_READ_REG(&adapter->hw, R); \ - if(value != (test[pat] & W & M)) { \ + if (value != (test[pat] & W & M)) { \ DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ "0x%08X expected 0x%08X\n", \ E1000_##R, value, (test[pat] & W & M)); \ @@ -746,7 +745,7 @@ err_setup_rx: uint32_t value; \ E1000_WRITE_REG(&adapter->hw, R, W & M); \ value = E1000_READ_REG(&adapter->hw, R); \ - if((W & M) != (value & M)) { \ + if ((W & M) != (value & M)) { \ DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ @@ -782,7 +781,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle); E1000_WRITE_REG(&adapter->hw, STATUS, toggle); after = E1000_READ_REG(&adapter->hw, STATUS) & toggle; - if(value != after) { + if (value != after) { DPRINTK(DRV, ERR, "failed STATUS register test got: " "0x%08X expected: 0x%08X\n", after, value); *data = 1; @@ -810,7 +809,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB); REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); - if(adapter->hw.mac_type >= e1000_82543) { + if (adapter->hw.mac_type >= e1000_82543) { REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF); REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); @@ -818,7 +817,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); - for(i = 0; i < E1000_RAR_ENTRIES; i++) { + for (i = 0; i < E1000_RAR_ENTRIES; i++) { REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF, @@ -834,7 +833,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) } - for(i = 0; i < E1000_MC_TBL_SIZE; i++) + for (i = 0; i < E1000_MC_TBL_SIZE; i++) REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF); *data = 0; @@ -850,8 +849,8 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data) *data = 0; /* Read and add up the contents of the EEPROM */ - for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) { + for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { + if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) { *data = 1; break; } @@ -859,7 +858,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data) } /* If Checksum is not Correct return error else test passed */ - if((checksum != (uint16_t) EEPROM_SUM) && !(*data)) + if ((checksum != (uint16_t) EEPROM_SUM) && !(*data)) *data = 2; return *data; @@ -888,9 +887,9 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) *data = 0; /* Hook up test interrupt handler just for this test */ - if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) { + if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) { shared_int = FALSE; - } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, + } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){ *data = 1; return -1; @@ -901,12 +900,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) msec_delay(10); /* Test each interrupt */ - for(; i < 10; i++) { + for (; i < 10; i++) { /* Interrupt to test */ mask = 1 << i; - if(!shared_int) { + if (!shared_int) { /* Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If @@ -917,8 +916,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) E1000_WRITE_REG(&adapter->hw, IMC, mask); E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); - - if(adapter->test_icr & mask) { + + if (adapter->test_icr & mask) { *data = 3; break; } @@ -935,12 +934,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) E1000_WRITE_REG(&adapter->hw, ICS, mask); msec_delay(10); - if(!(adapter->test_icr & mask)) { + if (!(adapter->test_icr & mask)) { *data = 4; break; } - if(!shared_int) { + if (!shared_int) { /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If @@ -952,7 +951,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF); msec_delay(10); - if(adapter->test_icr) { + if (adapter->test_icr) { *data = 5; break; } @@ -977,24 +976,24 @@ e1000_free_desc_rings(struct e1000_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int i; - if(txdr->desc && txdr->buffer_info) { - for(i = 0; i < txdr->count; i++) { - if(txdr->buffer_info[i].dma) + if (txdr->desc && txdr->buffer_info) { + for (i = 0; i < txdr->count; i++) { + if (txdr->buffer_info[i].dma) pci_unmap_single(pdev, txdr->buffer_info[i].dma, txdr->buffer_info[i].length, PCI_DMA_TODEVICE); - if(txdr->buffer_info[i].skb) + if (txdr->buffer_info[i].skb) dev_kfree_skb(txdr->buffer_info[i].skb); } } - if(rxdr->desc && rxdr->buffer_info) { - for(i = 0; i < rxdr->count; i++) { - if(rxdr->buffer_info[i].dma) + if (rxdr->desc && rxdr->buffer_info) { + for (i = 0; i < rxdr->count; i++) { + if (rxdr->buffer_info[i].dma) pci_unmap_single(pdev, rxdr->buffer_info[i].dma, rxdr->buffer_info[i].length, PCI_DMA_FROMDEVICE); - if(rxdr->buffer_info[i].skb) + if (rxdr->buffer_info[i].skb) dev_kfree_skb(rxdr->buffer_info[i].skb); } } @@ -1027,11 +1026,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) /* Setup Tx descriptor ring and Tx buffers */ - if(!txdr->count) - txdr->count = E1000_DEFAULT_TXD; + if (!txdr->count) + txdr->count = E1000_DEFAULT_TXD; size = txdr->count * sizeof(struct e1000_buffer); - if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) { + if (!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) { ret_val = 1; goto err_nomem; } @@ -1039,7 +1038,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) txdr->size = txdr->count * sizeof(struct e1000_tx_desc); E1000_ROUNDUP(txdr->size, 4096); - if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) { + if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) { ret_val = 2; goto err_nomem; } @@ -1058,12 +1057,12 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT); - for(i = 0; i < txdr->count; i++) { + for (i = 0; i < txdr->count; i++) { struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i); struct sk_buff *skb; unsigned int size = 1024; - if(!(skb = alloc_skb(size, GFP_KERNEL))) { + if (!(skb = alloc_skb(size, GFP_KERNEL))) { ret_val = 3; goto err_nomem; } @@ -1083,18 +1082,18 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) /* Setup Rx descriptor ring and Rx buffers */ - if(!rxdr->count) - rxdr->count = E1000_DEFAULT_RXD; + if (!rxdr->count) + rxdr->count = E1000_DEFAULT_RXD; size = rxdr->count * sizeof(struct e1000_buffer); - if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) { + if (!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) { ret_val = 4; goto err_nomem; } memset(rxdr->buffer_info, 0, size); rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) { + if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) { ret_val = 5; goto err_nomem; } @@ -1114,11 +1113,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - for(i = 0; i < rxdr->count; i++) { + for (i = 0; i < rxdr->count; i++) { struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); struct sk_buff *skb; - if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, + if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL))) { ret_val = 6; goto err_nomem; @@ -1227,15 +1226,15 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter) /* Check Phy Configuration */ e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); - if(phy_reg != 0x4100) + if (phy_reg != 0x4100) return 9; e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - if(phy_reg != 0x0070) + if (phy_reg != 0x0070) return 10; e1000_read_phy_reg(&adapter->hw, 29, &phy_reg); - if(phy_reg != 0x001A) + if (phy_reg != 0x001A) return 11; return 0; @@ -1249,7 +1248,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter) adapter->hw.autoneg = FALSE; - if(adapter->hw.phy_type == e1000_phy_m88) { + if (adapter->hw.phy_type == e1000_phy_m88) { /* Auto-MDI/MDIX Off */ e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, 0x0808); @@ -1269,14 +1268,14 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter) E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ E1000_CTRL_FD); /* Force Duplex to FULL */ - if(adapter->hw.media_type == e1000_media_type_copper && + if (adapter->hw.media_type == e1000_media_type_copper && adapter->hw.phy_type == e1000_phy_m88) { ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ } else { /* Set the ILOS bit on the fiber Nic is half * duplex link is detected. */ stat_reg = E1000_READ_REG(&adapter->hw, STATUS); - if((stat_reg & E1000_STATUS_FD) == 0) + if ((stat_reg & E1000_STATUS_FD) == 0) ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); } @@ -1285,7 +1284,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter) /* Disable the receiver on the PHY so when a cable is plugged in, the * PHY does not begin to autoneg when a cable is reconnected to the NIC. */ - if(adapter->hw.phy_type == e1000_phy_m88) + if (adapter->hw.phy_type == e1000_phy_m88) e1000_phy_disable_receiver(adapter); udelay(500); @@ -1301,14 +1300,14 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter) switch (adapter->hw.mac_type) { case e1000_82543: - if(adapter->hw.media_type == e1000_media_type_copper) { + if (adapter->hw.media_type == e1000_media_type_copper) { /* Attempt to setup Loopback mode on Non-integrated PHY. * Some PHY registers get corrupted at random, so * attempt this 10 times. */ - while(e1000_nonintegrated_phy_loopback(adapter) && + while (e1000_nonintegrated_phy_loopback(adapter) && count++ < 10); - if(count < 11) + if (count < 11) return 0; } break; @@ -1430,8 +1429,8 @@ static int e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) { frame_size &= ~1; - if(*(skb->data + 3) == 0xFF) { - if((*(skb->data + frame_size / 2 + 10) == 0xBE) && + if (*(skb->data + 3) == 0xFF) { + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && (*(skb->data + frame_size / 2 + 12) == 0xAF)) { return 0; } @@ -1450,53 +1449,53 @@ e1000_run_loopback_test(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); - /* Calculate the loop count based on the largest descriptor ring + /* Calculate the loop count based on the largest descriptor ring * The idea is to wrap the largest ring a number of times using 64 * send/receive pairs during each loop */ - if(rxdr->count <= txdr->count) + if (rxdr->count <= txdr->count) lc = ((txdr->count / 64) * 2) + 1; else lc = ((rxdr->count / 64) * 2) + 1; k = l = 0; - for(j = 0; j <= lc; j++) { /* loop count loop */ - for(i = 0; i < 64; i++) { /* send the packets */ - e1000_create_lbtest_frame(txdr->buffer_info[i].skb, + for (j = 0; j <= lc; j++) { /* loop count loop */ + for (i = 0; i < 64; i++) { /* send the packets */ + e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); - pci_dma_sync_single_for_device(pdev, + pci_dma_sync_single_for_device(pdev, txdr->buffer_info[k].dma, txdr->buffer_info[k].length, PCI_DMA_TODEVICE); - if(unlikely(++k == txdr->count)) k = 0; + if (unlikely(++k == txdr->count)) k = 0; } E1000_WRITE_REG(&adapter->hw, TDT, k); msec_delay(200); time = jiffies; /* set the start time for the receive */ good_cnt = 0; do { /* receive the sent packets */ - pci_dma_sync_single_for_cpu(pdev, + pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[l].dma, rxdr->buffer_info[l].length, PCI_DMA_FROMDEVICE); - + ret_val = e1000_check_lbtest_frame( rxdr->buffer_info[l].skb, 1024); - if(!ret_val) + if (!ret_val) good_cnt++; - if(unlikely(++l == rxdr->count)) l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's + if (unlikely(++l == rxdr->count)) l = 0; + /* time + 20 msecs (200 msecs on 2.4) is more than + * enough time to complete the receives, if it's * exceeded, break and error off */ } while (good_cnt < 64 && jiffies < (time + 20)); - if(good_cnt != 64) { + if (good_cnt != 64) { ret_val = 13; /* ret_val is the same as mis-compare */ - break; + break; } - if(jiffies >= (time + 2)) { + if (jiffies >= (time + 2)) { ret_val = 14; /* error code for time out error */ break; } @@ -1549,17 +1548,17 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) *data = 1; } else { e1000_check_for_link(&adapter->hw); - if(adapter->hw.autoneg) /* if auto_neg is set wait for it */ + if (adapter->hw.autoneg) /* if auto_neg is set wait for it */ msec_delay(4000); - if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { + if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { *data = 1; } } return *data; } -static int +static int e1000_diag_test_count(struct net_device *netdev) { return E1000_TEST_LEN; @@ -1572,7 +1571,7 @@ e1000_diag_test(struct net_device *netdev, struct e1000_adapter *adapter = netdev_priv(netdev); boolean_t if_running = netif_running(netdev); - if(eth_test->flags == ETH_TEST_FL_OFFLINE) { + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ /* save speed, duplex, autoneg settings */ @@ -1582,27 +1581,27 @@ e1000_diag_test(struct net_device *netdev, /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ - if(e1000_link_test(adapter, &data[4])) + if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; - if(if_running) + if (if_running) e1000_down(adapter); else e1000_reset(adapter); - if(e1000_reg_test(adapter, &data[0])) + if (e1000_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; e1000_reset(adapter); - if(e1000_eeprom_test(adapter, &data[1])) + if (e1000_eeprom_test(adapter, &data[1])) eth_test->flags |= ETH_TEST_FL_FAILED; e1000_reset(adapter); - if(e1000_intr_test(adapter, &data[2])) + if (e1000_intr_test(adapter, &data[2])) eth_test->flags |= ETH_TEST_FL_FAILED; e1000_reset(adapter); - if(e1000_loopback_test(adapter, &data[3])) + if (e1000_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; /* restore speed, duplex, autoneg settings */ @@ -1611,11 +1610,11 @@ e1000_diag_test(struct net_device *netdev, adapter->hw.autoneg = autoneg; e1000_reset(adapter); - if(if_running) + if (if_running) e1000_up(adapter); } else { /* Online tests */ - if(e1000_link_test(adapter, &data[4])) + if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; /* Offline tests aren't run; pass by default */ @@ -1633,7 +1632,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - switch(adapter->hw.device_id) { + switch (adapter->hw.device_id) { case E1000_DEV_ID_82542: case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: @@ -1649,7 +1648,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82571EB_FIBER: /* Wake events only supported on port A for dual fiber */ - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { + if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { wol->supported = 0; wol->wolopts = 0; return; @@ -1661,13 +1660,13 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) WAKE_BCAST | WAKE_MAGIC; wol->wolopts = 0; - if(adapter->wol & E1000_WUFC_EX) + if (adapter->wol & E1000_WUFC_EX) wol->wolopts |= WAKE_UCAST; - if(adapter->wol & E1000_WUFC_MC) + if (adapter->wol & E1000_WUFC_MC) wol->wolopts |= WAKE_MCAST; - if(adapter->wol & E1000_WUFC_BC) + if (adapter->wol & E1000_WUFC_BC) wol->wolopts |= WAKE_BCAST; - if(adapter->wol & E1000_WUFC_MAG) + if (adapter->wol & E1000_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; return; } @@ -1679,7 +1678,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - switch(adapter->hw.device_id) { + switch (adapter->hw.device_id) { case E1000_DEV_ID_82542: case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: @@ -1693,23 +1692,23 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82571EB_FIBER: /* Wake events only supported on port A for dual fiber */ - if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) return wol->wolopts ? -EOPNOTSUPP : 0; /* Fall Through */ default: - if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) + if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; adapter->wol = 0; - if(wol->wolopts & WAKE_UCAST) + if (wol->wolopts & WAKE_UCAST) adapter->wol |= E1000_WUFC_EX; - if(wol->wolopts & WAKE_MCAST) + if (wol->wolopts & WAKE_MCAST) adapter->wol |= E1000_WUFC_MC; - if(wol->wolopts & WAKE_BCAST) + if (wol->wolopts & WAKE_BCAST) adapter->wol |= E1000_WUFC_BC; - if(wol->wolopts & WAKE_MAGIC) + if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; } @@ -1727,7 +1726,7 @@ e1000_led_blink_callback(unsigned long data) { struct e1000_adapter *adapter = (struct e1000_adapter *) data; - if(test_and_change_bit(E1000_LED_ON, &adapter->led_status)) + if (test_and_change_bit(E1000_LED_ON, &adapter->led_status)) e1000_led_off(&adapter->hw); else e1000_led_on(&adapter->hw); @@ -1740,11 +1739,11 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) { struct e1000_adapter *adapter = netdev_priv(netdev); - if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) + if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); - if(adapter->hw.mac_type < e1000_82571) { - if(!adapter->blink_timer.function) { + if (adapter->hw.mac_type < e1000_82571) { + if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = e1000_led_blink_callback; adapter->blink_timer.data = (unsigned long) adapter; @@ -1782,21 +1781,21 @@ static int e1000_nway_reset(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); - if(netif_running(netdev)) { + if (netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); } return 0; } -static int +static int e1000_get_stats_count(struct net_device *netdev) { return E1000_STATS_LEN; } -static void -e1000_get_ethtool_stats(struct net_device *netdev, +static void +e1000_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { struct e1000_adapter *adapter = netdev_priv(netdev); @@ -1830,7 +1829,7 @@ e1000_get_ethtool_stats(struct net_device *netdev, /* BUG_ON(i != E1000_STATS_LEN); */ } -static void +static void e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) { #ifdef CONFIG_E1000_MQ @@ -1839,9 +1838,9 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) uint8_t *p = data; int i; - switch(stringset) { + switch (stringset) { case ETH_SS_TEST: - memcpy(data, *e1000_gstrings_test, + memcpy(data, *e1000_gstrings_test, E1000_TEST_LEN*ETH_GSTRING_LEN); break; case ETH_SS_STATS: diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 2437d362ff63..beeec0fbbeac 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -1600,10 +1600,10 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw) if(ret_val) return ret_val; - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); - if(ret_val) - return ret_val; + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + if(ret_val) + return ret_val; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -3916,7 +3916,7 @@ e1000_read_eeprom(struct e1000_hw *hw, } } - if(eeprom->use_eerd == TRUE) { + if (eeprom->use_eerd == TRUE) { ret_val = e1000_read_eeprom_eerd(hw, offset, words, data); if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) || (hw->mac_type != e1000_82573)) @@ -4423,7 +4423,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw) return -E1000_ERR_EEPROM; } - /* If STM opcode located in bits 15:8 of flop, reset firmware */ + /* If STM opcode located in bits 15:8 of flop, reset firmware */ if ((flop & 0xFF00) == E1000_STM_OPCODE) { E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET); } @@ -4431,7 +4431,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw) /* Perform the flash update */ E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD); - for (i=0; i < attempts; i++) { + for (i=0; i < attempts; i++) { eecd = E1000_READ_REG(hw, EECD); if ((eecd & E1000_EECD_FLUPD) == 0) { break; @@ -4504,6 +4504,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } + switch (hw->mac_type) { default: break; @@ -6840,7 +6841,8 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw) { uint32_t manc = 0; - if(hw->mac_type > e1000_82547_rev_2) + + if (hw->mac_type > e1000_82547_rev_2) manc = E1000_READ_REG(hw, MANC); return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : E1000_SUCCESS; diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 0b8f6f2b774b..f1219dd9dbac 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -377,6 +377,7 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask); void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask); /* Filters (multicast, vlan, receive) */ +void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count); uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr); void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value); void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index); @@ -401,7 +402,9 @@ void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); /* Port I/O is only supported on 82544 and newer */ uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port); +uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value); +void e1000_enable_pciex_master(struct e1000_hw *hw); int32_t e1000_disable_pciex_master(struct e1000_hw *hw); int32_t e1000_get_software_semaphore(struct e1000_hw *hw); void e1000_release_software_semaphore(struct e1000_hw *hw); @@ -899,14 +902,14 @@ struct e1000_ffvt_entry { #define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ #define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ #define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ -#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ -#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ -#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ -#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ -#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ -#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ -#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ +#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ +#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ +#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ +#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ +#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ +#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ +#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ +#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ #define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ #define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ @@ -1761,7 +1764,6 @@ struct e1000_hw { #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. still to be processed. */ - /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ #define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index d0a5d1656c5f..31e332935e5a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -29,11 +29,71 @@ #include "e1000.h" /* Change Log - * 6.0.58 4/20/05 - * o Accepted ethtool cleanup patch from Stephen Hemminger - * 6.0.44+ 2/15/05 - * o applied Anton's patch to resolve tx hang in hardware - * o Applied Andrew Mortons patch - e1000 stops working after resume + * 6.3.9 12/16/2005 + * o incorporate fix for recycled skbs from IBM LTC + * 6.3.7 11/18/2005 + * o Honor eeprom setting for enabling/disabling Wake On Lan + * 6.3.5 11/17/2005 + * o Fix memory leak in rx ring handling for PCI Express adapters + * 6.3.4 11/8/05 + * o Patch from Jesper Juhl to remove redundant NULL checks for kfree + * 6.3.2 9/20/05 + * o Render logic that sets/resets DRV_LOAD as inline functions to + * avoid code replication. If f/w is AMT then set DRV_LOAD only when + * network interface is open. + * o Handle DRV_LOAD set/reset in cases where AMT uses VLANs. + * o Adjust PBA partioning for Jumbo frames using MTU size and not + * rx_buffer_len + * 6.3.1 9/19/05 + * o Use adapter->tx_timeout_factor in Tx Hung Detect logic + (e1000_clean_tx_irq) + * o Support for 8086:10B5 device (Quad Port) + * 6.2.14 9/15/05 + * o In AMT enabled configurations, set/reset DRV_LOAD bit on interface + * open/close + * 6.2.13 9/14/05 + * o Invoke e1000_check_mng_mode only for 8257x controllers since it + * accesses the FWSM that is not supported in other controllers + * 6.2.12 9/9/05 + * o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER + * o set RCTL:SECRC only for controllers newer than 82543. + * o When the n/w interface comes down reset DRV_LOAD bit to notify f/w. + * This code was moved from e1000_remove to e1000_close + * 6.2.10 9/6/05 + * o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off. + * o Enable fc by default on 82573 controllers (do not read eeprom) + * o Fix rx_errors statistic not to include missed_packet_count + * o Fix rx_dropped statistic not to include missed_packet_count + (Padraig Brady) + * 6.2.9 8/30/05 + * o Remove call to update statistics from the controller ib e1000_get_stats + * 6.2.8 8/30/05 + * o Improved algorithm for rx buffer allocation/rdt update + * o Flow control watermarks relative to rx PBA size + * o Simplified 'Tx Hung' detect logic + * 6.2.7 8/17/05 + * o Report rx buffer allocation failures and tx timeout counts in stats + * 6.2.6 8/16/05 + * o Implement workaround for controller erratum -- linear non-tso packet + * following a TSO gets written back prematurely + * 6.2.5 8/15/05 + * o Set netdev->tx_queue_len based on link speed/duplex settings. + * o Fix net_stats.rx_fifo_errors <p@draigBrady.com> + * o Do not power off PHY if SoL/IDER session is active + * 6.2.4 8/10/05 + * o Fix loopback test setup/cleanup for 82571/3 controllers + * o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat + * all packets as raw + * o Prevent operations that will cause the PHY to be reset if SoL/IDER + * sessions are active and log a message + * 6.2.2 7/21/05 + * o used fixed size descriptors for all MTU sizes, reduces memory load + * 6.1.2 4/13/05 + * o Fixed ethtool diagnostics + * o Enabled flow control to take default eeprom settings + * o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent + * calls, one from mii_ioctl and other from within update_stats while + * processing MIIREG ioctl. */ char e1000_driver_name[] = "e1000"; @@ -295,7 +355,7 @@ e1000_irq_disable(struct e1000_adapter *adapter) static inline void e1000_irq_enable(struct e1000_adapter *adapter) { - if(likely(atomic_dec_and_test(&adapter->irq_sem))) { + if (likely(atomic_dec_and_test(&adapter->irq_sem))) { E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); E1000_WRITE_FLUSH(&adapter->hw); } @@ -307,17 +367,17 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter) struct net_device *netdev = adapter->netdev; uint16_t vid = adapter->hw.mng_cookie.vlan_id; uint16_t old_vid = adapter->mng_vlan_id; - if(adapter->vlgrp) { - if(!adapter->vlgrp->vlan_devices[vid]) { - if(adapter->hw.mng_cookie.status & + if (adapter->vlgrp) { + if (!adapter->vlgrp->vlan_devices[vid]) { + if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { e1000_vlan_rx_add_vid(netdev, vid); adapter->mng_vlan_id = vid; } else adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - - if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && - (vid != old_vid) && + + if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && + (vid != old_vid) && !adapter->vlgrp->vlan_devices[old_vid]) e1000_vlan_rx_kill_vid(netdev, old_vid); } @@ -401,10 +461,10 @@ e1000_up(struct e1000_adapter *adapter) /* hardware has been reset, we need to reload some things */ /* Reset the PHY if it was previously powered down */ - if(adapter->hw.media_type == e1000_media_type_copper) { + if (adapter->hw.media_type == e1000_media_type_copper) { uint16_t mii_reg; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); - if(mii_reg & MII_CR_POWER_DOWN) + if (mii_reg & MII_CR_POWER_DOWN) e1000_phy_reset(&adapter->hw); } @@ -425,16 +485,16 @@ e1000_up(struct e1000_adapter *adapter) } #ifdef CONFIG_PCI_MSI - if(adapter->hw.mac_type > e1000_82547_rev_2) { + if (adapter->hw.mac_type > e1000_82547_rev_2) { adapter->have_msi = TRUE; - if((err = pci_enable_msi(adapter->pdev))) { + if ((err = pci_enable_msi(adapter->pdev))) { DPRINTK(PROBE, ERR, "Unable to allocate MSI interrupt Error: %d\n", err); adapter->have_msi = FALSE; } } #endif - if((err = request_irq(adapter->pdev->irq, &e1000_intr, + if ((err = request_irq(adapter->pdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, netdev))) { DPRINTK(PROBE, ERR, @@ -471,7 +531,7 @@ e1000_down(struct e1000_adapter *adapter) #endif free_irq(adapter->pdev->irq, netdev); #ifdef CONFIG_PCI_MSI - if(adapter->hw.mac_type > e1000_82547_rev_2 && + if (adapter->hw.mac_type > e1000_82547_rev_2 && adapter->have_msi == TRUE) pci_disable_msi(adapter->pdev); #endif @@ -537,12 +597,12 @@ e1000_reset(struct e1000_adapter *adapter) break; } - if((adapter->hw.mac_type != e1000_82573) && + if ((adapter->hw.mac_type != e1000_82573) && (adapter->netdev->mtu > E1000_RXBUFFER_8192)) pba -= 8; /* allocate more FIFO for Tx */ - if(adapter->hw.mac_type == e1000_82547) { + if (adapter->hw.mac_type == e1000_82547) { adapter->tx_fifo_head = 0; adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; adapter->tx_fifo_size = @@ -565,9 +625,9 @@ e1000_reset(struct e1000_adapter *adapter) /* Allow time for pending master requests to run */ e1000_reset_hw(&adapter->hw); - if(adapter->hw.mac_type >= e1000_82544) + if (adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); - if(e1000_init_hw(&adapter->hw)) + if (e1000_init_hw(&adapter->hw)) DPRINTK(PROBE, ERR, "Hardware Error\n"); e1000_update_mng_vlan(adapter); /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ @@ -606,26 +666,26 @@ e1000_probe(struct pci_dev *pdev, int i, err, pci_using_dac; uint16_t eeprom_data; uint16_t eeprom_apme_mask = E1000_EEPROM_APME; - if((err = pci_enable_device(pdev))) + if ((err = pci_enable_device(pdev))) return err; - if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { + if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { pci_using_dac = 1; } else { - if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { + if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { E1000_ERR("No usable DMA configuration, aborting\n"); return err; } pci_using_dac = 0; } - if((err = pci_request_regions(pdev, e1000_driver_name))) + if ((err = pci_request_regions(pdev, e1000_driver_name))) return err; pci_set_master(pdev); netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if(!netdev) { + if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; } @@ -644,15 +704,15 @@ e1000_probe(struct pci_dev *pdev, mmio_len = pci_resource_len(pdev, BAR_0); adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if(!adapter->hw.hw_addr) { + if (!adapter->hw.hw_addr) { err = -EIO; goto err_ioremap; } - for(i = BAR_1; i <= BAR_5; i++) { - if(pci_resource_len(pdev, i) == 0) + for (i = BAR_1; i <= BAR_5; i++) { + if (pci_resource_len(pdev, i) == 0) continue; - if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { + if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { adapter->hw.io_base = pci_resource_start(pdev, i); break; } @@ -689,13 +749,13 @@ e1000_probe(struct pci_dev *pdev, /* setup the private structure */ - if((err = e1000_sw_init(adapter))) + if ((err = e1000_sw_init(adapter))) goto err_sw_init; - if((err = e1000_check_phy_reset_block(&adapter->hw))) + if ((err = e1000_check_phy_reset_block(&adapter->hw))) DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); - if(adapter->hw.mac_type >= e1000_82543) { + if (adapter->hw.mac_type >= e1000_82543) { netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX | @@ -704,16 +764,16 @@ e1000_probe(struct pci_dev *pdev, } #ifdef NETIF_F_TSO - if((adapter->hw.mac_type >= e1000_82544) && + if ((adapter->hw.mac_type >= e1000_82544) && (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; #ifdef NETIF_F_TSO_IPV6 - if(adapter->hw.mac_type > e1000_82547_rev_2) + if (adapter->hw.mac_type > e1000_82547_rev_2) netdev->features |= NETIF_F_TSO_IPV6; #endif #endif - if(pci_using_dac) + if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; /* hard_start_xmit is safe against parallel locking */ @@ -721,14 +781,14 @@ e1000_probe(struct pci_dev *pdev, adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); - /* before reading the EEPROM, reset the controller to + /* before reading the EEPROM, reset the controller to * put the device in a known good starting state */ - + e1000_reset_hw(&adapter->hw); /* make sure the EEPROM is good */ - if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { + if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) { DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; @@ -736,12 +796,12 @@ e1000_probe(struct pci_dev *pdev, /* copy the MAC address out of the EEPROM */ - if(e1000_read_mac_addr(&adapter->hw)) + if (e1000_read_mac_addr(&adapter->hw)) DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); - if(!is_valid_ether_addr(netdev->perm_addr)) { + if (!is_valid_ether_addr(netdev->perm_addr)) { DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; @@ -781,7 +841,7 @@ e1000_probe(struct pci_dev *pdev, * enable the ACPI Magic Packet filter */ - switch(adapter->hw.mac_type) { + switch (adapter->hw.mac_type) { case e1000_82542_rev2_0: case e1000_82542_rev2_1: case e1000_82543: @@ -794,7 +854,7 @@ e1000_probe(struct pci_dev *pdev, case e1000_82546: case e1000_82546_rev_3: case e1000_82571: - if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){ + if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){ e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); break; @@ -805,7 +865,7 @@ e1000_probe(struct pci_dev *pdev, EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); break; } - if(eeprom_data & eeprom_apme_mask) + if (eeprom_data & eeprom_apme_mask) adapter->wol |= E1000_WUFC_MAG; /* print bus type/speed/width info */ @@ -840,7 +900,7 @@ e1000_probe(struct pci_dev *pdev, e1000_get_hw_control(adapter); strcpy(netdev->name, "eth%d"); - if((err = register_netdev(netdev))) + if ((err = register_netdev(netdev))) goto err_register; DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); @@ -881,10 +941,10 @@ e1000_remove(struct pci_dev *pdev) flush_scheduled_work(); - if(adapter->hw.mac_type >= e1000_82540 && + if (adapter->hw.mac_type >= e1000_82540 && adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { + if (manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; E1000_WRITE_REG(&adapter->hw, MANC, manc); } @@ -900,7 +960,7 @@ e1000_remove(struct pci_dev *pdev) __dev_put(&adapter->polling_netdev[i]); #endif - if(!e1000_check_phy_reset_block(&adapter->hw)) + if (!e1000_check_phy_reset_block(&adapter->hw)) e1000_phy_hw_reset(&adapter->hw); kfree(adapter->tx_ring); @@ -959,19 +1019,19 @@ e1000_sw_init(struct e1000_adapter *adapter) /* identify the MAC */ - if(e1000_set_mac_type(hw)) { + if (e1000_set_mac_type(hw)) { DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); return -EIO; } /* initialize eeprom parameters */ - if(e1000_init_eeprom_params(hw)) { + if (e1000_init_eeprom_params(hw)) { E1000_ERR("EEPROM initialization failed\n"); return -EIO; } - switch(hw->mac_type) { + switch (hw->mac_type) { default: break; case e1000_82541: @@ -990,7 +1050,7 @@ e1000_sw_init(struct e1000_adapter *adapter) /* Copper options */ - if(hw->media_type == e1000_media_type_copper) { + if (hw->media_type == e1000_media_type_copper) { hw->mdix = AUTO_ALL_MODES; hw->disable_polarity_correction = FALSE; hw->master_slave = E1000_MASTER_SLAVE; @@ -1166,10 +1226,10 @@ e1000_open(struct net_device *netdev) if ((err = e1000_setup_all_rx_resources(adapter))) goto err_setup_rx; - if((err = e1000_up(adapter))) + if ((err = e1000_up(adapter))) goto err_up; adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if((adapter->hw.mng_cookie.status & + if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { e1000_update_mng_vlan(adapter); } @@ -1214,7 +1274,7 @@ e1000_close(struct net_device *netdev) e1000_free_all_tx_resources(adapter); e1000_free_all_rx_resources(adapter); - if((adapter->hw.mng_cookie.status & + if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); } @@ -1269,7 +1329,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter, size = sizeof(struct e1000_buffer) * txdr->count; txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus)); - if(!txdr->buffer_info) { + if (!txdr->buffer_info) { DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; @@ -1282,7 +1342,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter, E1000_ROUNDUP(txdr->size, 4096); txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); - if(!txdr->desc) { + if (!txdr->desc) { setup_tx_desc_die: vfree(txdr->buffer_info); DPRINTK(PROBE, ERR, @@ -1298,8 +1358,8 @@ setup_tx_desc_die: "at %p\n", txdr->size, txdr->desc); /* Try again, without freeing the previous */ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); - if(!txdr->desc) { /* Failed allocation, critical failure */ + if (!txdr->desc) { pci_free_consistent(pdev, txdr->size, olddesc, olddma); goto setup_tx_desc_die; } @@ -1499,7 +1559,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter, size = sizeof(struct e1000_ps_page) * rxdr->count; rxdr->ps_page = kmalloc(size, GFP_KERNEL); - if(!rxdr->ps_page) { + if (!rxdr->ps_page) { vfree(rxdr->buffer_info); DPRINTK(PROBE, ERR, "Unable to allocate memory for the receive descriptor ring\n"); @@ -1509,7 +1569,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter, size = sizeof(struct e1000_ps_page_dma) * rxdr->count; rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL); - if(!rxdr->ps_page_dma) { + if (!rxdr->ps_page_dma) { vfree(rxdr->buffer_info); kfree(rxdr->ps_page); DPRINTK(PROBE, ERR, @@ -1518,7 +1578,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter, } memset(rxdr->ps_page_dma, 0, size); - if(adapter->hw.mac_type <= e1000_82547_rev_2) + if (adapter->hw.mac_type <= e1000_82547_rev_2) desc_len = sizeof(struct e1000_rx_desc); else desc_len = sizeof(union e1000_rx_desc_packet_split); @@ -1621,7 +1681,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter) { uint32_t rctl, rfctl; uint32_t psrctl = 0; -#ifdef CONFIG_E1000_PACKET_SPLIT +#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT uint32_t pages = 0; #endif @@ -1647,32 +1707,17 @@ e1000_setup_rctl(struct e1000_adapter *adapter) rctl |= E1000_RCTL_LPE; /* Setup buffer sizes */ - if(adapter->hw.mac_type >= e1000_82571) { + if (adapter->hw.mac_type >= e1000_82571) { /* We can now specify buffers in 1K increments. * BSIZE and BSEX are ignored in this case. */ rctl |= adapter->rx_buffer_len << 0x11; } else { rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384; - break; - } + rctl &= ~E1000_RCTL_BSEX; + rctl |= E1000_RCTL_SZ_2048; } -#ifdef CONFIG_E1000_PACKET_SPLIT +#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT /* 82571 and greater support packet-split where the protocol * header is placed in skb->data and the packet data is * placed in pages hanging off of skb_shinfo(skb)->nr_frags. @@ -1696,7 +1741,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC; - + psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; @@ -1758,7 +1803,7 @@ e1000_configure_rx(struct e1000_adapter *adapter) if (hw->mac_type >= e1000_82540) { E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); - if(adapter->itr > 1) + if (adapter->itr > 1) E1000_WRITE_REG(hw, ITR, 1000000000 / (adapter->itr * 256)); } @@ -1847,13 +1892,13 @@ e1000_configure_rx(struct e1000_adapter *adapter) /* Enable 82543 Receive Checksum Offload for TCP and UDP */ if (hw->mac_type >= e1000_82543) { rxcsum = E1000_READ_REG(hw, RXCSUM); - if(adapter->rx_csum == TRUE) { + if (adapter->rx_csum == TRUE) { rxcsum |= E1000_RXCSUM_TUOFL; /* Enable 82571 IPv4 payload checksum for UDP fragments * Must be used in conjunction with packet-split. */ - if ((hw->mac_type >= e1000_82571) && - (adapter->rx_ps_pages)) { + if ((hw->mac_type >= e1000_82571) && + (adapter->rx_ps_pages)) { rxcsum |= E1000_RXCSUM_IPPCSE; } } else { @@ -1915,7 +1960,7 @@ static inline void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { - if(buffer_info->dma) { + if (buffer_info->dma) { pci_unmap_page(adapter->pdev, buffer_info->dma, buffer_info->length, @@ -1942,7 +1987,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter, /* Free all the Tx ring sk_buffs */ - for(i = 0; i < tx_ring->count; i++) { + for (i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); } @@ -2038,10 +2083,9 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter, unsigned int i, j; /* Free all the Rx ring sk_buffs */ - - for(i = 0; i < rx_ring->count; i++) { + for (i = 0; i < rx_ring->count; i++) { buffer_info = &rx_ring->buffer_info[i]; - if(buffer_info->skb) { + if (buffer_info->skb) { pci_unmap_single(pdev, buffer_info->dma, buffer_info->length, @@ -2122,7 +2166,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter) E1000_WRITE_FLUSH(&adapter->hw); mdelay(5); - if(netif_running(netdev)) + if (netif_running(netdev)) e1000_clean_all_rx_rings(adapter); } @@ -2138,13 +2182,13 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter) E1000_WRITE_FLUSH(&adapter->hw); mdelay(5); - if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) + if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) e1000_pci_set_mwi(&adapter->hw); - if(netif_running(netdev)) { - e1000_configure_rx(adapter); + if (netif_running(netdev)) { /* No need to loop, because 82542 supports only 1 queue */ struct e1000_rx_ring *ring = &adapter->rx_ring[0]; + e1000_configure_rx(adapter); adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); } } @@ -2163,12 +2207,12 @@ e1000_set_mac(struct net_device *netdev, void *p) struct e1000_adapter *adapter = netdev_priv(netdev); struct sockaddr *addr = p; - if(!is_valid_ether_addr(addr->sa_data)) + if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; /* 82542 2.0 needs to be in reset to write receive address registers */ - if(adapter->hw.mac_type == e1000_82542_rev2_0) + if (adapter->hw.mac_type == e1000_82542_rev2_0) e1000_enter_82542_rst(adapter); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); @@ -2182,17 +2226,17 @@ e1000_set_mac(struct net_device *netdev, void *p) /* activate the work around */ adapter->hw.laa_is_present = 1; - /* Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed (in e1000_watchdog), the actual LAA is in one + /* Hold a copy of the LAA in RAR[14] This is done so that + * between the time RAR[0] gets clobbered and the time it + * gets fixed (in e1000_watchdog), the actual LAA is in one * of the RARs and no incoming packets directed to this port - * are dropped. Eventaully the LAA will be in RAR[0] and + * are dropped. Eventaully the LAA will be in RAR[0] and * RAR[14] */ - e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, + e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, E1000_RAR_ENTRIES - 1); } - if(adapter->hw.mac_type == e1000_82542_rev2_0) + if (adapter->hw.mac_type == e1000_82542_rev2_0) e1000_leave_82542_rst(adapter); return 0; @@ -2226,9 +2270,9 @@ e1000_set_multi(struct net_device *netdev) rctl = E1000_READ_REG(hw, RCTL); - if(netdev->flags & IFF_PROMISC) { + if (netdev->flags & IFF_PROMISC) { rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - } else if(netdev->flags & IFF_ALLMULTI) { + } else if (netdev->flags & IFF_ALLMULTI) { rctl |= E1000_RCTL_MPE; rctl &= ~E1000_RCTL_UPE; } else { @@ -2239,7 +2283,7 @@ e1000_set_multi(struct net_device *netdev) /* 82542 2.0 needs to be in reset to write receive address registers */ - if(hw->mac_type == e1000_82542_rev2_0) + if (hw->mac_type == e1000_82542_rev2_0) e1000_enter_82542_rst(adapter); /* load the first 14 multicast address into the exact filters 1-14 @@ -2249,7 +2293,7 @@ e1000_set_multi(struct net_device *netdev) */ mc_ptr = netdev->mc_list; - for(i = 1; i < rar_entries; i++) { + for (i = 1; i < rar_entries; i++) { if (mc_ptr) { e1000_rar_set(hw, mc_ptr->dmi_addr, i); mc_ptr = mc_ptr->next; @@ -2261,17 +2305,17 @@ e1000_set_multi(struct net_device *netdev) /* clear the old settings from the multicast hash table */ - for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) + for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++) E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); /* load any remaining addresses into the hash table */ - for(; mc_ptr; mc_ptr = mc_ptr->next) { + for (; mc_ptr; mc_ptr = mc_ptr->next) { hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr); e1000_mta_set(hw, hash_value); } - if(hw->mac_type == e1000_82542_rev2_0) + if (hw->mac_type == e1000_82542_rev2_0) e1000_leave_82542_rst(adapter); } @@ -2297,8 +2341,8 @@ e1000_82547_tx_fifo_stall(unsigned long data) struct net_device *netdev = adapter->netdev; uint32_t tctl; - if(atomic_read(&adapter->tx_fifo_stall)) { - if((E1000_READ_REG(&adapter->hw, TDT) == + if (atomic_read(&adapter->tx_fifo_stall)) { + if ((E1000_READ_REG(&adapter->hw, TDT) == E1000_READ_REG(&adapter->hw, TDH)) && (E1000_READ_REG(&adapter->hw, TDFT) == E1000_READ_REG(&adapter->hw, TDFH)) && @@ -2350,18 +2394,18 @@ e1000_watchdog_task(struct e1000_adapter *adapter) e1000_check_for_link(&adapter->hw); if (adapter->hw.mac_type == e1000_82573) { e1000_enable_tx_pkt_filtering(&adapter->hw); - if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) + if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) e1000_update_mng_vlan(adapter); - } + } - if((adapter->hw.media_type == e1000_media_type_internal_serdes) && + if ((adapter->hw.media_type == e1000_media_type_internal_serdes) && !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) link = !adapter->hw.serdes_link_down; else link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; - if(link) { - if(!netif_carrier_ok(netdev)) { + if (link) { + if (!netif_carrier_ok(netdev)) { e1000_get_speed_and_duplex(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); @@ -2392,7 +2436,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter) adapter->smartspeed = 0; } } else { - if(netif_carrier_ok(netdev)) { + if (netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; DPRINTK(LINK, INFO, "NIC Link is Down\n"); @@ -2432,12 +2476,12 @@ e1000_watchdog_task(struct e1000_adapter *adapter) } /* Dynamic mode for Interrupt Throttle Rate (ITR) */ - if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) { + if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) { /* Symmetric Tx/Rx gets a reduced ITR=2000; Total * asymmetrical Tx or Rx gets ITR=8000; everyone * else is between 2000-8000. */ uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000; - uint32_t dif = (adapter->gotcl > adapter->gorcl ? + uint32_t dif = (adapter->gotcl > adapter->gorcl ? adapter->gotcl - adapter->gorcl : adapter->gorcl - adapter->gotcl) / 10000; uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; @@ -2450,7 +2494,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter) /* Force detection of hung controller every watchdog period */ adapter->detect_tx_hung = TRUE; - /* With 82571 controllers, LAA may be overwritten due to controller + /* With 82571 controllers, LAA may be overwritten due to controller * reset from the other port. Set the appropriate LAA in RAR[0] */ if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present) e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); @@ -2479,7 +2523,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, uint8_t ipcss, ipcso, tucss, tucso, hdr_len; int err; - if(skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->tso_size) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -2488,7 +2532,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); mss = skb_shinfo(skb)->tso_size; - if(skb->protocol == ntohs(ETH_P_IP)) { + if (skb->protocol == ntohs(ETH_P_IP)) { skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; skb->h.th->check = @@ -2500,7 +2544,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, cmd_length = E1000_TXD_CMD_IP; ipcse = skb->h.raw - skb->data - 1; #ifdef NETIF_F_TSO_IPV6 - } else if(skb->protocol == ntohs(ETH_P_IPV6)) { + } else if (skb->protocol == ntohs(ETH_P_IPV6)) { skb->nh.ipv6h->payload_len = 0; skb->h.th->check = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, @@ -2555,7 +2599,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, unsigned int i; uint8_t css; - if(likely(skb->ip_summed == CHECKSUM_HW)) { + if (likely(skb->ip_summed == CHECKSUM_HW)) { css = skb->h.raw - skb->data; i = tx_ring->next_to_use; @@ -2595,7 +2639,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, i = tx_ring->next_to_use; - while(len) { + while (len) { buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); #ifdef NETIF_F_TSO @@ -2611,7 +2655,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(unlikely(mss && !nr_frags && size == len && size > 8)) + if (unlikely(mss && !nr_frags && size == len && size > 8)) size -= 4; #endif /* work-around for errata 10 and it applies @@ -2619,13 +2663,13 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, * The fix is to make sure that the first descriptor of a * packet is smaller than 2048 - 16 - 16 (or 2016) bytes */ - if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && + if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && (size > 2015) && count == 0)) size = 2015; - + /* Workaround for potential 82544 hang in PCI-X. Avoid * terminating buffers within evenly-aligned dwords. */ - if(unlikely(adapter->pcix_82544 && + if (unlikely(adapter->pcix_82544 && !((unsigned long)(skb->data + offset + size - 1) & 4) && size > 4)) size -= 4; @@ -2641,29 +2685,29 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, len -= size; offset += size; count++; - if(unlikely(++i == tx_ring->count)) i = 0; + if (unlikely(++i == tx_ring->count)) i = 0; } - for(f = 0; f < nr_frags; f++) { + for (f = 0; f < nr_frags; f++) { struct skb_frag_struct *frag; frag = &skb_shinfo(skb)->frags[f]; len = frag->size; offset = frag->page_offset; - while(len) { + while (len) { buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) + if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) size -= 4; #endif /* Workaround for potential 82544 hang in PCI-X. * Avoid terminating buffers within evenly-aligned * dwords. */ - if(unlikely(adapter->pcix_82544 && + if (unlikely(adapter->pcix_82544 && !((unsigned long)(frag->page+offset+size-1) & 4) && size > 4)) size -= 4; @@ -2680,7 +2724,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, len -= size; offset += size; count++; - if(unlikely(++i == tx_ring->count)) i = 0; + if (unlikely(++i == tx_ring->count)) i = 0; } } @@ -2700,35 +2744,35 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; unsigned int i; - if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { + if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | E1000_TXD_CMD_TSE; txd_upper |= E1000_TXD_POPTS_TXSM << 8; - if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) + if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) txd_upper |= E1000_TXD_POPTS_IXSM << 8; } - if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { + if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; txd_upper |= E1000_TXD_POPTS_TXSM << 8; } - if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { + if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { txd_lower |= E1000_TXD_CMD_VLE; txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); } i = tx_ring->next_to_use; - while(count--) { + while (count--) { buffer_info = &tx_ring->buffer_info[i]; tx_desc = E1000_TX_DESC(*tx_ring, i); tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); tx_desc->lower.data = cpu_to_le32(txd_lower | buffer_info->length); tx_desc->upper.data = cpu_to_le32(txd_upper); - if(unlikely(++i == tx_ring->count)) i = 0; + if (unlikely(++i == tx_ring->count)) i = 0; } tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); @@ -2763,20 +2807,20 @@ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb) E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); - if(adapter->link_duplex != HALF_DUPLEX) + if (adapter->link_duplex != HALF_DUPLEX) goto no_fifo_stall_required; - if(atomic_read(&adapter->tx_fifo_stall)) + if (atomic_read(&adapter->tx_fifo_stall)) return 1; - if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { + if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { atomic_set(&adapter->tx_fifo_stall, 1); return 1; } no_fifo_stall_required: adapter->tx_fifo_head += skb_fifo_len; - if(adapter->tx_fifo_head >= adapter->tx_fifo_size) + if (adapter->tx_fifo_head >= adapter->tx_fifo_size) adapter->tx_fifo_head -= adapter->tx_fifo_size; return 0; } @@ -2787,27 +2831,27 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) { struct e1000_hw *hw = &adapter->hw; uint16_t length, offset; - if(vlan_tx_tag_present(skb)) { - if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && + if (vlan_tx_tag_present(skb)) { + if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && ( adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) return 0; } - if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { + if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { struct ethhdr *eth = (struct ethhdr *) skb->data; - if((htons(ETH_P_IP) == eth->h_proto)) { - const struct iphdr *ip = + if ((htons(ETH_P_IP) == eth->h_proto)) { + const struct iphdr *ip = (struct iphdr *)((uint8_t *)skb->data+14); - if(IPPROTO_UDP == ip->protocol) { - struct udphdr *udp = - (struct udphdr *)((uint8_t *)ip + + if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = + (struct udphdr *)((uint8_t *)ip + (ip->ihl << 2)); - if(ntohs(udp->dest) == 67) { + if (ntohs(udp->dest) == 67) { offset = (uint8_t *)udp + 8 - skb->data; length = skb->len - offset; return e1000_mng_write_dhcp_info(hw, - (uint8_t *)udp + 8, + (uint8_t *)udp + 8, length); } } @@ -2830,7 +2874,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int nr_frags = 0; unsigned int mss = 0; int count = 0; - int tso; + int tso; unsigned int f; len -= skb->data_len; @@ -2853,7 +2897,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) * 4 = ceil(buffer len/mss). To make sure we don't * overrun the FIFO, adjust the max buffer len if mss * drops. */ - if(mss) { + if (mss) { uint8_t hdr_len; max_per_txd = min(mss << 2, max_per_txd); max_txd_pwr = fls(max_per_txd) - 1; @@ -2876,12 +2920,12 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - if((mss) || (skb->ip_summed == CHECKSUM_HW)) /* reserve a descriptor for the offload context */ + if ((mss) || (skb->ip_summed == CHECKSUM_HW)) count++; count++; #else - if(skb->ip_summed == CHECKSUM_HW) + if (skb->ip_summed == CHECKSUM_HW) count++; #endif @@ -2894,24 +2938,24 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) count += TXD_USE_COUNT(len, max_txd_pwr); - if(adapter->pcix_82544) + if (adapter->pcix_82544) count++; - /* work-around for errata 10 and it applies to all controllers + /* work-around for errata 10 and it applies to all controllers * in PCI-X mode, so add one more descriptor to the count */ - if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && + if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && (len > 2015))) count++; nr_frags = skb_shinfo(skb)->nr_frags; - for(f = 0; f < nr_frags; f++) + for (f = 0; f < nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, max_txd_pwr); - if(adapter->pcix_82544) + if (adapter->pcix_82544) count += nr_frags; - if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) ) + if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) ) e1000_transfer_dhcp_info(adapter, skb); local_irq_save(flags); @@ -2929,8 +2973,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - if(unlikely(adapter->hw.mac_type == e1000_82547)) { - if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) { + if (unlikely(adapter->hw.mac_type == e1000_82547)) { + if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { netif_stop_queue(netdev); mod_timer(&adapter->tx_fifo_stall_timer, jiffies); spin_unlock_irqrestore(&tx_ring->tx_lock, flags); @@ -2938,13 +2982,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { + if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } first = tx_ring->next_to_use; - + tso = e1000_tso(adapter, tx_ring, skb); if (tso < 0) { dev_kfree_skb_any(skb); @@ -3033,9 +3077,9 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); + if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || + (max_frame > MAX_JUMBO_FRAME_SIZE)) { + DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); return -EINVAL; } @@ -3083,7 +3127,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; - if(netif_running(netdev)) { + if (netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); } @@ -3170,7 +3214,7 @@ e1000_update_stats(struct e1000_adapter *adapter) hw->collision_delta = E1000_READ_REG(hw, COLC); adapter->stats.colc += hw->collision_delta; - if(hw->mac_type >= e1000_82543) { + if (hw->mac_type >= e1000_82543) { adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); @@ -3178,7 +3222,7 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); } - if(hw->mac_type > e1000_82547_rev_2) { + if (hw->mac_type > e1000_82547_rev_2) { adapter->stats.iac += E1000_READ_REG(hw, IAC); adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); @@ -3222,14 +3266,14 @@ e1000_update_stats(struct e1000_adapter *adapter) /* Phy Stats */ - if(hw->media_type == e1000_media_type_copper) { - if((adapter->link_speed == SPEED_1000) && + if (hw->media_type == e1000_media_type_copper) { + if ((adapter->link_speed == SPEED_1000) && (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; adapter->phy_stats.idle_errors += phy_tmp; } - if((hw->mac_type <= e1000_82546) && + if ((hw->mac_type <= e1000_82546) && (hw->phy_type == e1000_phy_m88) && !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) adapter->phy_stats.receive_errors += phy_tmp; @@ -3294,7 +3338,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) return IRQ_NONE; /* Not our interrupt */ } - if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { + if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; mod_timer(&adapter->watchdog_timer, jiffies); } @@ -3326,26 +3370,26 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) #else /* if !CONFIG_E1000_NAPI */ /* Writing IMC and IMS is needed for 82547. - Due to Hub Link bus being occupied, an interrupt - de-assertion message is not able to be sent. - When an interrupt assertion message is generated later, - two messages are re-ordered and sent out. - That causes APIC to think 82547 is in de-assertion - state, while 82547 is in assertion state, resulting - in dead lock. Writing IMC forces 82547 into - de-assertion state. - */ - if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){ + * Due to Hub Link bus being occupied, an interrupt + * de-assertion message is not able to be sent. + * When an interrupt assertion message is generated later, + * two messages are re-ordered and sent out. + * That causes APIC to think 82547 is in de-assertion + * state, while 82547 is in assertion state, resulting + * in dead lock. Writing IMC forces 82547 into + * de-assertion state. + */ + if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) { atomic_inc(&adapter->irq_sem); E1000_WRITE_REG(hw, IMC, ~0); } - for(i = 0; i < E1000_MAX_INTR; i++) - if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & + for (i = 0; i < E1000_MAX_INTR; i++) + if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; - if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) + if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) e1000_irq_enable(adapter); #endif /* CONFIG_E1000_NAPI */ @@ -3397,9 +3441,9 @@ e1000_clean(struct net_device *poll_dev, int *budget) *budget -= work_done; poll_dev->quota -= work_done; - + /* If no Tx and not enough Rx work done, exit the polling mode */ - if((!tx_cleaned && (work_done == 0)) || + if ((!tx_cleaned && (work_done == 0)) || !netif_running(adapter->netdev)) { quit_polling: netif_rx_complete(poll_dev); @@ -3431,7 +3475,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, eop_desc = E1000_TX_DESC(*tx_ring, eop); while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - for(cleaned = FALSE; !cleaned; ) { + for (cleaned = FALSE; !cleaned; ) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -3442,7 +3486,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, e1000_unmap_and_free_tx_resource(adapter, buffer_info); memset(tx_desc, 0, sizeof(struct e1000_tx_desc)); - if(unlikely(++i == tx_ring->count)) i = 0; + if (unlikely(++i == tx_ring->count)) i = 0; } #ifdef CONFIG_E1000_MQ @@ -3457,7 +3501,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, spin_lock(&tx_ring->tx_lock); - if(unlikely(cleaned && netif_queue_stopped(netdev) && + if (unlikely(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))) netif_wake_queue(netdev); @@ -3519,21 +3563,21 @@ e1000_rx_checksum(struct e1000_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; /* 82543 or newer only */ - if(unlikely(adapter->hw.mac_type < e1000_82543)) return; + if (unlikely(adapter->hw.mac_type < e1000_82543)) return; /* Ignore Checksum bit is set */ - if(unlikely(status & E1000_RXD_STAT_IXSM)) return; + if (unlikely(status & E1000_RXD_STAT_IXSM)) return; /* TCP/UDP checksum error bit is set */ - if(unlikely(errors & E1000_RXD_ERR_TCPE)) { + if (unlikely(errors & E1000_RXD_ERR_TCPE)) { /* let the stack verify checksum errors */ adapter->hw_csum_err++; return; } /* TCP/UDP Checksum has not been calculated */ - if(adapter->hw.mac_type <= e1000_82547_rev_2) { - if(!(status & E1000_RXD_STAT_TCPCS)) + if (adapter->hw.mac_type <= e1000_82547_rev_2) { + if (!(status & E1000_RXD_STAT_TCPCS)) return; } else { - if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) + if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) return; } /* It must be a TCP or UDP packet with a valid checksum */ @@ -3569,9 +3613,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; + struct e1000_rx_desc *rx_desc, *next_rxd; + struct e1000_buffer *buffer_info, *next_buffer; unsigned long flags; uint32_t length; uint8_t last_byte; @@ -3581,16 +3624,25 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); + buffer_info = &rx_ring->buffer_info[i]; - while(rx_desc->status & E1000_RXD_STAT_DD) { - buffer_info = &rx_ring->buffer_info[i]; + while (rx_desc->status & E1000_RXD_STAT_DD) { + struct sk_buff *skb, *next_skb; u8 status; #ifdef CONFIG_E1000_NAPI - if(*work_done >= work_to_do) + if (*work_done >= work_to_do) break; (*work_done)++; #endif status = rx_desc->status; + skb = buffer_info->skb; + buffer_info->skb = NULL; + + if (++i == rx_ring->count) i = 0; + next_rxd = E1000_RX_DESC(*rx_ring, i); + next_buffer = &rx_ring->buffer_info[i]; + next_skb = next_buffer->skb; + cleaned = TRUE; cleaned_count++; pci_unmap_single(pdev, @@ -3598,20 +3650,50 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; length = le16_to_cpu(rx_desc->length); - if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { - /* All receives must fit into a single buffer */ - E1000_DBG("%s: Receive packet consumed multiple" - " buffers\n", netdev->name); - dev_kfree_skb_irq(skb); + skb_put(skb, length); + + if (!(status & E1000_RXD_STAT_EOP)) { + if (!rx_ring->rx_skb_top) { + rx_ring->rx_skb_top = skb; + rx_ring->rx_skb_top->len = length; + rx_ring->rx_skb_prev = skb; + } else { + if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) { + rx_ring->rx_skb_prev->next = skb; + skb->prev = rx_ring->rx_skb_prev; + } else { + skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb; + } + rx_ring->rx_skb_prev = skb; + rx_ring->rx_skb_top->data_len += length; + } goto next_desc; + } else { + if (rx_ring->rx_skb_top) { + if (skb_shinfo(rx_ring->rx_skb_top) + ->frag_list) { + rx_ring->rx_skb_prev->next = skb; + skb->prev = rx_ring->rx_skb_prev; + } else + skb_shinfo(rx_ring->rx_skb_top) + ->frag_list = skb; + + rx_ring->rx_skb_top->data_len += length; + rx_ring->rx_skb_top->len += + rx_ring->rx_skb_top->data_len; + + skb = rx_ring->rx_skb_top; + multi_descriptor = TRUE; + rx_ring->rx_skb_top = NULL; + rx_ring->rx_skb_prev = NULL; + } } - if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { + if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { last_byte = *(skb->data + length - 1); - if(TBI_ACCEPT(&adapter->hw, rx_desc->status, + if (TBI_ACCEPT(&adapter->hw, status, rx_desc->errors, length, last_byte)) { spin_lock_irqsave(&adapter->stats_lock, flags); e1000_tbi_adjust_stats(&adapter->hw, @@ -3656,9 +3738,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, (uint32_t)(status) | ((uint32_t)(rx_desc->errors) << 24), rx_desc->csum, skb); + skb->protocol = eth_type_trans(skb, netdev); #ifdef CONFIG_E1000_NAPI - if(unlikely(adapter->vlgrp && + if (unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, le16_to_cpu(rx_desc->special) & @@ -3667,8 +3750,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, netif_receive_skb(skb); } #else /* CONFIG_E1000_NAPI */ - if(unlikely(adapter->vlgrp && - (rx_desc->status & E1000_RXD_STAT_VP))) { + if (unlikely(adapter->vlgrp && + (status & E1000_RXD_STAT_VP))) { vlan_hwaccel_rx(skb, adapter->vlgrp, le16_to_cpu(rx_desc->special) & E1000_RXD_SPC_VLAN_MASK); @@ -3691,6 +3774,8 @@ next_desc: cleaned_count = 0; } + rx_desc = next_rxd; + buffer_info = next_buffer; } rx_ring->next_to_clean = i; @@ -3716,13 +3801,13 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring) #endif { - union e1000_rx_desc_packet_split *rx_desc; + union e1000_rx_desc_packet_split *rx_desc, *next_rxd; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; + struct e1000_buffer *buffer_info, *next_buffer; struct e1000_ps_page *ps_page; struct e1000_ps_page_dma *ps_page_dma; - struct sk_buff *skb; + struct sk_buff *skb, *next_skb; unsigned int i, j; uint32_t length, staterr; int cleaned_count = 0; @@ -3731,39 +3816,44 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + buffer_info = &rx_ring->buffer_info[i]; - while(staterr & E1000_RXD_STAT_DD) { - buffer_info = &rx_ring->buffer_info[i]; + while (staterr & E1000_RXD_STAT_DD) { ps_page = &rx_ring->ps_page[i]; ps_page_dma = &rx_ring->ps_page_dma[i]; #ifdef CONFIG_E1000_NAPI - if(unlikely(*work_done >= work_to_do)) + if (unlikely(*work_done >= work_to_do)) break; (*work_done)++; #endif + skb = buffer_info->skb; + + if (++i == rx_ring->count) i = 0; + next_rxd = E1000_RX_DESC_PS(*rx_ring, i); + next_buffer = &rx_ring->buffer_info[i]; + next_skb = next_buffer->skb; + cleaned = TRUE; cleaned_count++; pci_unmap_single(pdev, buffer_info->dma, buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; - - if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { + if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) { E1000_DBG("%s: Packet Split buffers didn't pick up" " the full packet\n", netdev->name); dev_kfree_skb_irq(skb); goto next_desc; } - if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { + if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { dev_kfree_skb_irq(skb); goto next_desc; } length = le16_to_cpu(rx_desc->wb.middle.length0); - if(unlikely(!length)) { + if (unlikely(!length)) { E1000_DBG("%s: Last part of the packet spanning" " multiple descriptors\n", netdev->name); dev_kfree_skb_irq(skb); @@ -3773,8 +3863,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, /* Good Receive */ skb_put(skb, length); - for(j = 0; j < adapter->rx_ps_pages; j++) { - if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) + for (j = 0; j < adapter->rx_ps_pages; j++) { + if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) break; pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], @@ -3794,15 +3884,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); skb->protocol = eth_type_trans(skb, netdev); - if(likely(rx_desc->wb.upper.header_status & - E1000_RXDPS_HDRSTAT_HDRSP)) { + if (likely(rx_desc->wb.upper.header_status & + E1000_RXDPS_HDRSTAT_HDRSP)) adapter->rx_hdr_split++; -#ifdef HAVE_RX_ZERO_COPY - skb_shinfo(skb)->zero_copy = TRUE; -#endif - } #ifdef CONFIG_E1000_NAPI - if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { + if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, le16_to_cpu(rx_desc->wb.middle.vlan) & E1000_RXD_SPC_VLAN_MASK); @@ -3810,7 +3896,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, netif_receive_skb(skb); } #else /* CONFIG_E1000_NAPI */ - if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { + if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_rx(skb, adapter->vlgrp, le16_to_cpu(rx_desc->wb.middle.vlan) & E1000_RXD_SPC_VLAN_MASK); @@ -3834,6 +3920,9 @@ next_desc: cleaned_count = 0; } + rx_desc = next_rxd; + buffer_info = next_buffer; + staterr = le32_to_cpu(rx_desc->wb.middle.status_error); } rx_ring->next_to_clean = i; @@ -3875,7 +3964,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, } - if(unlikely(!skb)) { + if (unlikely(!skb)) { /* Better luck next round */ adapter->alloc_rx_buff_failed++; break; @@ -3940,20 +4029,23 @@ map_skb: rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->rdt); - } - - if(unlikely(++i == rx_ring->count)) i = 0; + if (unlikely(++i == rx_ring->count)) + i = 0; buffer_info = &rx_ring->buffer_info[i]; } - rx_ring->next_to_use = i; + if (likely(rx_ring->next_to_use != i)) { + rx_ring->next_to_use = i; + if (unlikely(i-- == 0)) + i = (rx_ring->count - 1); + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); + writel(i, adapter->hw.hw_addr + rx_ring->rdt); + } } /** @@ -3983,13 +4075,15 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, while (cleaned_count--) { rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - for(j = 0; j < PS_PAGE_BUFFERS; j++) { + for (j = 0; j < PS_PAGE_BUFFERS; j++) { if (j < adapter->rx_ps_pages) { if (likely(!ps_page->ps_page[j])) { ps_page->ps_page[j] = alloc_page(GFP_ATOMIC); - if (unlikely(!ps_page->ps_page[j])) + if (unlikely(!ps_page->ps_page[j])) { + adapter->alloc_rx_buff_failed++; goto no_buffers; + } ps_page_dma->ps_page_dma[j] = pci_map_page(pdev, ps_page->ps_page[j], @@ -3997,7 +4091,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, PCI_DMA_FROMDEVICE); } /* Refresh the desc even if buffer_addrs didn't - * change because each write-back erases + * change because each write-back erases * this info. */ rx_desc->read.buffer_addr[j+1] = @@ -4008,8 +4102,10 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); - if(unlikely(!skb)) + if (unlikely(!skb)) { + adapter->alloc_rx_buff_failed++; break; + } /* Make buffer alignment 2 beyond a 16 byte boundary * this will result in a 16 byte aligned IP header after @@ -4027,27 +4123,28 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); - if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - /* Hardware increments by 16 bytes, but packet split - * descriptors are 32 bytes...so we increment tail - * twice as much. - */ - writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt); - } - - if(unlikely(++i == rx_ring->count)) i = 0; + if (unlikely(++i == rx_ring->count)) i = 0; buffer_info = &rx_ring->buffer_info[i]; ps_page = &rx_ring->ps_page[i]; ps_page_dma = &rx_ring->ps_page_dma[i]; } no_buffers: - rx_ring->next_to_use = i; + if (likely(rx_ring->next_to_use != i)) { + rx_ring->next_to_use = i; + if (unlikely(i-- == 0)) i = (rx_ring->count - 1); + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); + /* Hardware increments by 16 bytes, but packet split + * descriptors are 32 bytes...so we increment tail + * twice as much. + */ + writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt); + } } /** @@ -4061,24 +4158,24 @@ e1000_smartspeed(struct e1000_adapter *adapter) uint16_t phy_status; uint16_t phy_ctrl; - if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg || + if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg || !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) return; - if(adapter->smartspeed == 0) { + if (adapter->smartspeed == 0) { /* If Master/Slave config fault is asserted twice, * we assume back-to-back */ e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); - if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; + if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); - if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; + if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); - if(phy_ctrl & CR_1000T_MS_ENABLE) { + if (phy_ctrl & CR_1000T_MS_ENABLE) { phy_ctrl &= ~CR_1000T_MS_ENABLE; e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); adapter->smartspeed++; - if(!e1000_phy_setup_autoneg(&adapter->hw) && + if (!e1000_phy_setup_autoneg(&adapter->hw) && !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { phy_ctrl |= (MII_CR_AUTO_NEG_EN | @@ -4088,12 +4185,12 @@ e1000_smartspeed(struct e1000_adapter *adapter) } } return; - } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { + } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { /* If still no link, perhaps using 2/3 pair cable */ e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); phy_ctrl |= CR_1000T_MS_ENABLE; e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); - if(!e1000_phy_setup_autoneg(&adapter->hw) && + if (!e1000_phy_setup_autoneg(&adapter->hw) && !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); @@ -4101,7 +4198,7 @@ e1000_smartspeed(struct e1000_adapter *adapter) } } /* Restart process after E1000_SMARTSPEED_MAX iterations */ - if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) + if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX) adapter->smartspeed = 0; } @@ -4142,7 +4239,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) uint16_t spddplx; unsigned long flags; - if(adapter->hw.media_type != e1000_media_type_copper) + if (adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; switch (cmd) { @@ -4150,10 +4247,10 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) data->phy_id = adapter->hw.phy_addr; break; case SIOCGMIIREG: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; spin_lock_irqsave(&adapter->stats_lock, flags); - if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, &data->val_out)) { spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; @@ -4161,23 +4258,23 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) spin_unlock_irqrestore(&adapter->stats_lock, flags); break; case SIOCSMIIREG: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(data->reg_num & ~(0x1F)) + if (data->reg_num & ~(0x1F)) return -EFAULT; mii_reg = data->val_in; spin_lock_irqsave(&adapter->stats_lock, flags); - if(e1000_write_phy_reg(&adapter->hw, data->reg_num, + if (e1000_write_phy_reg(&adapter->hw, data->reg_num, mii_reg)) { spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; } - if(adapter->hw.phy_type == e1000_phy_m88) { + if (adapter->hw.phy_type == e1000_phy_m88) { switch (data->reg_num) { case PHY_CTRL: - if(mii_reg & MII_CR_POWER_DOWN) + if (mii_reg & MII_CR_POWER_DOWN) break; - if(mii_reg & MII_CR_AUTO_NEG_EN) { + if (mii_reg & MII_CR_AUTO_NEG_EN) { adapter->hw.autoneg = 1; adapter->hw.autoneg_advertised = 0x2F; } else { @@ -4192,14 +4289,14 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) HALF_DUPLEX; retval = e1000_set_spd_dplx(adapter, spddplx); - if(retval) { + if (retval) { spin_unlock_irqrestore( - &adapter->stats_lock, + &adapter->stats_lock, flags); return retval; } } - if(netif_running(adapter->netdev)) { + if (netif_running(adapter->netdev)) { e1000_down(adapter); e1000_up(adapter); } else @@ -4207,7 +4304,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; case M88E1000_PHY_SPEC_CTRL: case M88E1000_EXT_PHY_SPEC_CTRL: - if(e1000_phy_reset(&adapter->hw)) { + if (e1000_phy_reset(&adapter->hw)) { spin_unlock_irqrestore( &adapter->stats_lock, flags); return -EIO; @@ -4217,9 +4314,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } else { switch (data->reg_num) { case PHY_CTRL: - if(mii_reg & MII_CR_POWER_DOWN) + if (mii_reg & MII_CR_POWER_DOWN) break; - if(netif_running(adapter->netdev)) { + if (netif_running(adapter->netdev)) { e1000_down(adapter); e1000_up(adapter); } else @@ -4241,7 +4338,7 @@ e1000_pci_set_mwi(struct e1000_hw *hw) struct e1000_adapter *adapter = hw->back; int ret_val = pci_set_mwi(adapter->pdev); - if(ret_val) + if (ret_val) DPRINTK(PROBE, ERR, "Error in setting MWI\n"); } @@ -4290,7 +4387,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) e1000_irq_disable(adapter); adapter->vlgrp = grp; - if(grp) { + if (grp) { /* enable VLAN tag insert/strip */ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl |= E1000_CTRL_VME; @@ -4312,7 +4409,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl &= ~E1000_RCTL_VFE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { + if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; } @@ -4326,9 +4423,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) { struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t vfta, index; - if((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && - (vid == adapter->mng_vlan_id)) + + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) return; /* add VID to filter table */ index = (vid >> 5) & 0x7F; @@ -4345,13 +4443,13 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) e1000_irq_disable(adapter); - if(adapter->vlgrp) + if (adapter->vlgrp) adapter->vlgrp->vlan_devices[vid] = NULL; e1000_irq_enable(adapter); - if((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + if ((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && (vid == adapter->mng_vlan_id)) { /* release control to f/w */ e1000_release_hw_control(adapter); @@ -4370,10 +4468,10 @@ e1000_restore_vlan(struct e1000_adapter *adapter) { e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp); - if(adapter->vlgrp) { + if (adapter->vlgrp) { uint16_t vid; - for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if(!adapter->vlgrp->vlan_devices[vid]) + for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + if (!adapter->vlgrp->vlan_devices[vid]) continue; e1000_vlan_rx_add_vid(adapter->netdev, vid); } @@ -4386,13 +4484,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) adapter->hw.autoneg = 0; /* Fiber NICs only allow 1000 gbps Full duplex */ - if((adapter->hw.media_type == e1000_media_type_fiber) && + if ((adapter->hw.media_type == e1000_media_type_fiber) && spddplx != (SPEED_1000 + DUPLEX_FULL)) { DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } - switch(spddplx) { + switch (spddplx) { case SPEED_10 + DUPLEX_HALF: adapter->hw.forced_speed_duplex = e1000_10_half; break; @@ -4418,6 +4516,54 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) } #ifdef CONFIG_PM +/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config + * space versus the 64 bytes that pci_[save|restore]_state handle + */ +#define PCIE_CONFIG_SPACE_LEN 256 +#define PCI_CONFIG_SPACE_LEN 64 +static int +e1000_pci_save_state(struct e1000_adapter *adapter) +{ + struct pci_dev *dev = adapter->pdev; + int size; + int i; + if (adapter->hw.mac_type >= e1000_82571) + size = PCIE_CONFIG_SPACE_LEN; + else + size = PCI_CONFIG_SPACE_LEN; + + WARN_ON(adapter->config_space != NULL); + + adapter->config_space = kmalloc(size, GFP_KERNEL); + if (!adapter->config_space) { + DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size); + return -ENOMEM; + } + for (i = 0; i < (size / 4); i++) + pci_read_config_dword(dev, i * 4, &adapter->config_space[i]); + return 0; +} + +static void +e1000_pci_restore_state(struct e1000_adapter *adapter) +{ + struct pci_dev *dev = adapter->pdev; + int size; + int i; + if (adapter->config_space == NULL) + return; + if (adapter->hw.mac_type >= e1000_82571) + size = PCIE_CONFIG_SPACE_LEN; + else + size = PCI_CONFIG_SPACE_LEN; + for (i = 0; i < (size / 4); i++) + pci_write_config_dword(dev, i * 4, adapter->config_space[i]); + kfree(adapter->config_space); + adapter->config_space = NULL; + return; +} +#endif /* CONFIG_PM */ + static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -4429,25 +4575,33 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(netdev); - if(netif_running(netdev)) + if (netif_running(netdev)) e1000_down(adapter); +#ifdef CONFIG_PM + /* implement our own version of pci_save_state(pdev) because pci + * express adapters have larger 256 byte config spaces */ + retval = e1000_pci_save_state(adapter); + if (retval) + return retval; +#endif + status = E1000_READ_REG(&adapter->hw, STATUS); - if(status & E1000_STATUS_LU) + if (status & E1000_STATUS_LU) wufc &= ~E1000_WUFC_LNKC; - if(wufc) { + if (wufc) { e1000_setup_rctl(adapter); e1000_set_multi(netdev); /* turn on all-multi mode if wake on multicast is enabled */ - if(adapter->wol & E1000_WUFC_MC) { + if (adapter->wol & E1000_WUFC_MC) { rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl |= E1000_RCTL_MPE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } - if(adapter->hw.mac_type >= e1000_82540) { + if (adapter->hw.mac_type >= e1000_82540) { ctrl = E1000_READ_REG(&adapter->hw, CTRL); /* advertise wake from D3Cold */ #define E1000_CTRL_ADVD3WUC 0x00100000 @@ -4458,7 +4612,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } - if(adapter->hw.media_type == e1000_media_type_fiber || + if (adapter->hw.media_type == e1000_media_type_fiber || adapter->hw.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); @@ -4488,12 +4642,10 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); } - pci_save_state(pdev); - - if(adapter->hw.mac_type >= e1000_82540 && + if (adapter->hw.mac_type >= e1000_82540 && adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); - if(manc & E1000_MANC_SMBUS_EN) { + if (manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; E1000_WRITE_REG(&adapter->hw, MANC, manc); retval = pci_enable_wake(pdev, PCI_D3hot, 1); @@ -4518,6 +4670,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +#ifdef CONFIG_PM static int e1000_resume(struct pci_dev *pdev) { @@ -4529,6 +4682,7 @@ e1000_resume(struct pci_dev *pdev) retval = pci_set_power_state(pdev, PCI_D0); if (retval) DPRINTK(PROBE, ERR, "Error in setting power state\n"); + e1000_pci_restore_state(adapter); ret_val = pci_enable_device(pdev); pci_set_master(pdev); @@ -4542,12 +4696,12 @@ e1000_resume(struct pci_dev *pdev) e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); - if(netif_running(netdev)) + if (netif_running(netdev)) e1000_up(adapter); netif_device_attach(netdev); - if(adapter->hw.mac_type >= e1000_82540 && + if (adapter->hw.mac_type >= e1000_82540 && adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index aac64de61437..9790db974dc1 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -47,7 +47,7 @@ BUG(); \ } else { \ msleep(x); \ - } } while(0) + } } while (0) /* Some workarounds require millisecond delays and are run during interrupt * context. Most notably, when establishing link, the phy may need tweaking diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 0a7918c62557..3768d83cd577 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -227,7 +227,7 @@ static int __devinit e1000_validate_option(int *value, struct e1000_option *opt, struct e1000_adapter *adapter) { - if(*value == OPTION_UNSET) { + if (*value == OPTION_UNSET) { *value = opt->def; return 0; } @@ -244,7 +244,7 @@ e1000_validate_option(int *value, struct e1000_option *opt, } break; case range_option: - if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { + if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { DPRINTK(PROBE, INFO, "%s set to %i\n", opt->name, *value); return 0; @@ -254,10 +254,10 @@ e1000_validate_option(int *value, struct e1000_option *opt, int i; struct e1000_opt_list *ent; - for(i = 0; i < opt->arg.l.nr; i++) { + for (i = 0; i < opt->arg.l.nr; i++) { ent = &opt->arg.l.p[i]; - if(*value == ent->i) { - if(ent->str[0] != '\0') + if (*value == ent->i) { + if (ent->str[0] != '\0') DPRINTK(PROBE, INFO, "%s\n", ent->str); return 0; } @@ -291,7 +291,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) { int bd = adapter->bd_number; - if(bd >= E1000_MAX_NIC) { + if (bd >= E1000_MAX_NIC) { DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%i\n", bd); DPRINTK(PROBE, NOTICE, "Using defaults for all values\n"); @@ -315,7 +315,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_TxDescriptors > bd) { tx_ring->count = TxDescriptors[bd]; e1000_validate_option(&tx_ring->count, &opt, adapter); - E1000_ROUNDUP(tx_ring->count, + E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); } else { tx_ring->count = opt.def; @@ -341,7 +341,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_RxDescriptors > bd) { rx_ring->count = RxDescriptors[bd]; e1000_validate_option(&rx_ring->count, &opt, adapter); - E1000_ROUNDUP(rx_ring->count, + E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); } else { rx_ring->count = opt.def; @@ -403,7 +403,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_TxIntDelay > bd) { adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, + e1000_validate_option(&adapter->tx_int_delay, &opt, adapter); } else { adapter->tx_int_delay = opt.def; @@ -421,7 +421,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_TxAbsIntDelay > bd) { adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, + e1000_validate_option(&adapter->tx_abs_int_delay, &opt, adapter); } else { adapter->tx_abs_int_delay = opt.def; @@ -439,7 +439,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_RxIntDelay > bd) { adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, + e1000_validate_option(&adapter->rx_int_delay, &opt, adapter); } else { adapter->rx_int_delay = opt.def; @@ -457,7 +457,7 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_RxAbsIntDelay > bd) { adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, + e1000_validate_option(&adapter->rx_abs_int_delay, &opt, adapter); } else { adapter->rx_abs_int_delay = opt.def; @@ -475,17 +475,17 @@ e1000_check_options(struct e1000_adapter *adapter) if (num_InterruptThrottleRate > bd) { adapter->itr = InterruptThrottleRate[bd]; - switch(adapter->itr) { + switch (adapter->itr) { case 0: - DPRINTK(PROBE, INFO, "%s turned off\n", + DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); break; case 1: - DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", + DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name); break; default: - e1000_validate_option(&adapter->itr, &opt, + e1000_validate_option(&adapter->itr, &opt, adapter); break; } @@ -494,7 +494,7 @@ e1000_check_options(struct e1000_adapter *adapter) } } - switch(adapter->hw.media_type) { + switch (adapter->hw.media_type) { case e1000_media_type_fiber: case e1000_media_type_internal_serdes: e1000_check_fiber_options(adapter); @@ -518,17 +518,17 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) { int bd = adapter->bd_number; - if(num_Speed > bd) { + if (num_Speed > bd) { DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, " "parameter ignored\n"); } - if(num_Duplex > bd) { + if (num_Duplex > bd) { DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, " "parameter ignored\n"); } - if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) { + if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) { DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is " "not valid for fiber adapters, " "parameter ignored\n"); @@ -598,7 +598,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter) } } - if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) { + if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) { DPRINTK(PROBE, INFO, "AutoNeg specified along with Speed or Duplex, " "parameter ignored\n"); @@ -659,7 +659,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter) switch (speed + dplx) { case 0: adapter->hw.autoneg = adapter->fc_autoneg = 1; - if((num_Speed > bd) && (speed != 0 || dplx != 0)) + if ((num_Speed > bd) && (speed != 0 || dplx != 0)) DPRINTK(PROBE, INFO, "Speed and duplex autonegotiation enabled\n"); break; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0c18dbd67d3b..0e8e3fcde9ff 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -199,8 +199,7 @@ static int gfar_probe(struct platform_device *pdev) /* get a pointer to the register memory */ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = (struct gfar *) - ioremap(r->start, sizeof (struct gfar)); + priv->regs = ioremap(r->start, sizeof (struct gfar)); if (NULL == priv->regs) { err = -ENOMEM; @@ -369,7 +368,7 @@ static int gfar_probe(struct platform_device *pdev) return 0; register_fail: - iounmap((void *) priv->regs); + iounmap(priv->regs); regs_fail: free_netdev(dev); return err; @@ -382,7 +381,7 @@ static int gfar_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - iounmap((void *) priv->regs); + iounmap(priv->regs); free_netdev(dev); return 0; @@ -454,8 +453,7 @@ static void init_registers(struct net_device *dev) /* Zero out the rmon mib registers if it has them */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - memset((void *) &(priv->regs->rmon), 0, - sizeof (struct rmon_mib)); + memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib)); /* Mask off the CAM interrupts */ gfar_write(&priv->regs->rmon.cam1, 0xffffffff); @@ -477,7 +475,7 @@ static void init_registers(struct net_device *dev) void gfar_halt(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; u32 tempval; /* Mask all interrupts */ @@ -507,7 +505,7 @@ void gfar_halt(struct net_device *dev) void stop_gfar(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; unsigned long flags; phy_stop(priv->phydev); @@ -590,7 +588,7 @@ static void free_skb_resources(struct gfar_private *priv) void gfar_start(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; u32 tempval; /* Enable Rx and Tx in MACCFG1 */ @@ -624,7 +622,7 @@ int startup_gfar(struct net_device *dev) unsigned long vaddr; int i; struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; int err = 0; u32 rctrl = 0; u32 attrs = 0; @@ -1622,7 +1620,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void adjust_link(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; unsigned long flags; struct phy_device *phydev = priv->phydev; int new_state = 0; @@ -1703,7 +1701,7 @@ static void gfar_set_multi(struct net_device *dev) { struct dev_mc_list *mc_ptr; struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; + struct gfar __iomem *regs = priv->regs; u32 tempval; if(dev->flags & IFF_PROMISC) { @@ -1842,7 +1840,7 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr) int idx; char tmpbuf[MAC_ADDR_LEN]; u32 tempval; - u32 *macptr = &priv->regs->macstnaddr1; + u32 __iomem *macptr = &priv->regs->macstnaddr1; macptr += num*2; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cb9d66ac3ab9..d37d5401be6e 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -682,8 +682,8 @@ struct gfar_private { struct rxbd8 *cur_rx; /* Next free rx ring entry */ struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ - struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ - u32 *hash_regs[16]; + struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */ + u32 __iomem *hash_regs[16]; int hash_width; struct net_device_stats stats; /* linux network statistics */ struct gfar_extra_stats extra_stats; @@ -718,14 +718,14 @@ struct gfar_private { uint32_t msg_enable; }; -static inline u32 gfar_read(volatile unsigned *addr) +static inline u32 gfar_read(volatile unsigned __iomem *addr) { u32 val; val = in_be32(addr); return val; } -static inline void gfar_write(volatile unsigned *addr, u32 val) +static inline void gfar_write(volatile unsigned __iomem *addr, u32 val) { out_be32(addr, val); } diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 765e810620fe..5de7b2e259dc 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -144,11 +144,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 *extra = (u64 *) & priv->extra_stats; if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { - u32 *rmon = (u32 *) & priv->regs->rmon; + u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; struct gfar_stats *stats = (struct gfar_stats *) buf; for (i = 0; i < GFAR_RMON_LEN; i++) - stats->rmon[i] = (u64) (rmon[i]); + stats->rmon[i] = (u64) gfar_read(&rmon[i]); for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) stats->extra[i] = extra[i]; @@ -221,11 +221,11 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi { int i; struct gfar_private *priv = netdev_priv(dev); - u32 *theregs = (u32 *) priv->regs; + u32 __iomem *theregs = (u32 __iomem *) priv->regs; u32 *buf = (u32 *) regbuf; for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) - buf[i] = theregs[i]; + buf[i] = gfar_read(&theregs[i]); } /* Convert microseconds to ethernet clock ticks, which changes diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 74e52fcbf806..c6b725529af5 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -50,7 +50,7 @@ * All PHY configuration is done through the TSEC1 MIIM regs */ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { - struct gfar_mii *regs = bus->priv; + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; /* Set the PHY address and the register address we want to write */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); @@ -70,7 +70,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) * configuration has to be done through the TSEC1 MIIM regs */ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - struct gfar_mii *regs = bus->priv; + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; u16 value; /* Set the PHY address and the register address we want to read */ @@ -94,7 +94,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) /* Reset the MIIM registers, and wait for the bus to free */ int gfar_mdio_reset(struct mii_bus *bus) { - struct gfar_mii *regs = bus->priv; + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; unsigned int timeout = PHY_INIT_TIMEOUT; spin_lock_bh(&bus->mdio_lock); @@ -126,7 +126,7 @@ int gfar_mdio_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gianfar_mdio_data *pdata; - struct gfar_mii *regs; + struct gfar_mii __iomem *regs; struct mii_bus *new_bus; struct resource *r; int err = 0; @@ -155,15 +155,14 @@ int gfar_mdio_probe(struct device *dev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); /* Set the PHY base address */ - regs = (struct gfar_mii *) ioremap(r->start, - sizeof (struct gfar_mii)); + regs = ioremap(r->start, sizeof (struct gfar_mii)); if (NULL == regs) { err = -ENOMEM; goto reg_map_fail; } - new_bus->priv = regs; + new_bus->priv = (void __force *)regs; new_bus->irq = pdata->irq; @@ -181,7 +180,7 @@ int gfar_mdio_probe(struct device *dev) return 0; bus_register_fail: - iounmap((void *) regs); + iounmap(regs); reg_map_fail: kfree(new_bus); @@ -197,7 +196,7 @@ int gfar_mdio_remove(struct device *dev) dev_set_drvdata(dev, NULL); - iounmap((void *) (&bus->priv)); + iounmap((void __iomem *)bus->priv); bus->priv = NULL; kfree(bus); diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 3b1bef1ee215..77411a00d1ee 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -86,7 +86,6 @@ #include <linux/bitops.h> #include <linux/jiffies.h> -#include <asm/bug.h> #include <asm/system.h> #include <asm/uaccess.h> diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 6139f06d7d2b..94d5ea1ce8bd 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -56,8 +56,6 @@ PORT SIZE ACTION MEANING All other communication is through memory! */ -#define SLOW_DOWN_IO udelay(5) - #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 40ae36b20c9d..c0998ef938e0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -32,6 +32,8 @@ */ #include <linux/init.h> #include <linux/dma-mapping.h> +#include <linux/in.h> +#include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/etherdevice.h> @@ -444,6 +446,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) netif_rx(skb); #endif } + dev->last_rx = jiffies; } return received_packets; @@ -461,7 +464,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) */ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, - struct pt_regs *regs) + struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; struct mv643xx_private *mp = netdev_priv(dev); @@ -1047,16 +1050,15 @@ static int mv643xx_poll(struct net_device *dev, int *budget) static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) { - unsigned int frag; - skb_frag_t *fragp; - - for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { - fragp = &skb_shinfo(skb)->frags[frag]; - if (fragp->size <= 8 && fragp->page_offset & 0x7) - return 1; + unsigned int frag; + skb_frag_t *fragp; - } - return 0; + for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { + fragp = &skb_shinfo(skb)->frags[frag]; + if (fragp->size <= 8 && fragp->page_offset & 0x7) + return 1; + } + return 0; } @@ -2137,26 +2139,26 @@ static void eth_port_set_multicast_list(struct net_device *dev) */ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) { for (table_index = 0; table_index <= 0xFC; table_index += 4) { - /* Set all entries in DA filter special multicast - * table (Ex_dFSMT) - * Set for ETH_Q0 for now - * Bits - * 0 Accept=1, Drop=0 - * 3-1 Queue ETH_Q0=0 - * 7-4 Reserved = 0; - */ - mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); - - /* Set all entries in DA filter other multicast - * table (Ex_dFOMT) - * Set for ETH_Q0 for now - * Bits - * 0 Accept=1, Drop=0 - * 3-1 Queue ETH_Q0=0 - * 7-4 Reserved = 0; - */ - mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); - } + /* Set all entries in DA filter special multicast + * table (Ex_dFSMT) + * Set for ETH_Q0 for now + * Bits + * 0 Accept=1, Drop=0 + * 3-1 Queue ETH_Q0=0 + * 7-4 Reserved = 0; + */ + mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); + + /* Set all entries in DA filter other multicast + * table (Ex_dFOMT) + * Set for ETH_Q0 for now + * Bits + * 0 Accept=1, Drop=0 + * 3-1 Queue ETH_Q0=0 + * 7-4 Reserved = 0; + */ + mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); + } return; } @@ -2617,7 +2619,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, struct eth_tx_desc *current_descriptor; struct eth_tx_desc *first_descriptor; u32 command; - unsigned long flags; /* Do not process Tx ring in case of Tx ring resource error */ if (mp->tx_resource_err) @@ -2634,8 +2635,6 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, return ETH_ERROR; } - spin_lock_irqsave(&mp->lock, flags); - mp->tx_ring_skbs++; BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); @@ -2685,15 +2684,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, mp->tx_resource_err = 1; mp->tx_curr_desc_q = tx_first_desc; - spin_unlock_irqrestore(&mp->lock, flags); - return ETH_QUEUE_LAST_RESOURCE; } mp->tx_curr_desc_q = tx_next_desc; - spin_unlock_irqrestore(&mp->lock, flags); - return ETH_OK; } #else @@ -2704,14 +2699,11 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, int tx_desc_used; struct eth_tx_desc *current_descriptor; unsigned int command_status; - unsigned long flags; /* Do not process Tx ring in case of Tx ring resource error */ if (mp->tx_resource_err) return ETH_QUEUE_FULL; - spin_lock_irqsave(&mp->lock, flags); - mp->tx_ring_skbs++; BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); @@ -2742,12 +2734,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, /* Check for ring index overlap in the Tx desc ring */ if (tx_desc_curr == tx_desc_used) { mp->tx_resource_err = 1; - - spin_unlock_irqrestore(&mp->lock, flags); return ETH_QUEUE_LAST_RESOURCE; } - spin_unlock_irqrestore(&mp->lock, flags); return ETH_OK; } #endif @@ -2898,8 +2887,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp, p_pkt_info->return_info = mp->rx_skb[rx_curr_desc]; p_pkt_info->l4i_chk = p_rx_desc->buf_size; - /* Clean the return info field to indicate that the packet has been */ - /* moved to the upper layers */ + /* + * Clean the return info field to indicate that the + * packet has been moved to the upper layers + */ mp->rx_skb[rx_curr_desc] = NULL; /* Update current index in data structure */ @@ -2980,7 +2971,7 @@ struct mv643xx_stats { }; #define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \ - offsetof(struct mv643xx_private, m) + offsetof(struct mv643xx_private, m) static const struct mv643xx_stats mv643xx_gstrings_stats[] = { { "rx_packets", MV643XX_STAT(stats.rx_packets) }, @@ -3131,9 +3122,8 @@ mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return 0; } -static void -mv643xx_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) +static void mv643xx_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) { strncpy(drvinfo->driver, mv643xx_driver_name, 32); strncpy(drvinfo->version, mv643xx_driver_version, 32); @@ -3142,39 +3132,37 @@ mv643xx_get_drvinfo(struct net_device *netdev, drvinfo->n_stats = MV643XX_STATS_LEN; } -static int -mv643xx_get_stats_count(struct net_device *netdev) +static int mv643xx_get_stats_count(struct net_device *netdev) { return MV643XX_STATS_LEN; } -static void -mv643xx_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) +static void mv643xx_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) { struct mv643xx_private *mp = netdev->priv; int i; eth_update_mib_counters(mp); - for(i = 0; i < MV643XX_STATS_LEN; i++) { + for (i = 0; i < MV643XX_STATS_LEN; i++) { char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset; - data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == + data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; } } -static void -mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) +static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, + uint8_t *data) { int i; switch(stringset) { case ETH_SS_STATS: for (i=0; i < MV643XX_STATS_LEN; i++) { - memcpy(data + i * ETH_GSTRING_LEN, - mv643xx_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); + memcpy(data + i * ETH_GSTRING_LEN, + mv643xx_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); } break; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 1c6d328165bb..0245e40b51a1 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1610,6 +1610,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) } else if (!pskb_may_pull(skb, skb->len)) goto err; + else + skb->ip_summed = CHECKSUM_NONE; len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); if (len <= 0) { @@ -1690,6 +1692,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) kfree_skb(skb); } else { skb_pull(skb, 2); /* chop off protocol */ + skb_postpull_rcsum(skb, skb->data - 2, 2); skb->dev = ppp->dev; skb->protocol = htons(npindex_to_ethertype[npi]); skb->mac.raw = skb->data; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 2e1bed153c39..6e1018448eea 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) int i; RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); - udelay(1000); - for (i = 2000; i > 0; i--) { + for (i = 20; i > 0; i--) { /* Check if the RTL8169 has completed writing to the specified MII register */ if (!(RTL_R32(PHYAR) & 0x80000000)) break; - udelay(100); + udelay(25); } } @@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr) int i, value = -1; RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); - udelay(1000); - for (i = 2000; i > 0; i--) { + for (i = 20; i > 0; i--) { /* Check if the RTL8169 has completed retrieving data from the specified MII register */ if (RTL_R32(PHYAR) & 0x80000000) { value = (int) (RTL_R32(PHYAR) & 0xFFFF); break; } - udelay(100); + udelay(25); } return value; } @@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, if (duplex == DUPLEX_HALF) auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); + + if (duplex == DUPLEX_FULL) + auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half); } tp->phy_auto_nego_reg = auto_nego; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 89c46787676c..49b597cbc19a 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3586,7 +3586,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Buffer_Pointer = (u64) pci_map_page (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); - txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size); + txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); if (skb_shinfo(skb)->ufo_size) txdp->Control_1 |= TXD_UFO_EN; } diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h index 4233ea55670f..50323941e3c0 100644 --- a/drivers/net/sis900.h +++ b/drivers/net/sis900.h @@ -33,7 +33,6 @@ enum sis900_registers { rxcfg=0x34, //Receive Configuration Register flctrl=0x38, //Flow Control Register rxlen=0x3c, //Receive Packet Length Register - cfgpmcsr=0x44, //Configuration Power Management Control/Status Register rfcr=0x48, //Receive Filter Control Register rfdr=0x4C, //Receive Filter Data Register pmctrl=0xB0, //Power Management Control Register diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f8b973a04b65..cae2edf23004 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -23,12 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * TOTEST - * - speed setting - * - suspend/resume - */ - #include <linux/config.h> #include <linux/crc32.h> #include <linux/kernel.h> @@ -57,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "0.13" +#define DRV_VERSION "0.15" #define PFX DRV_NAME " " /* @@ -102,6 +96,10 @@ static int copybreak __read_mostly = 256; module_param(copybreak, int, 0); MODULE_PARM_DESC(copybreak, "Receive copy threshold"); +static int disable_msi = 0; +module_param(disable_msi, int, 0); +MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); + static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, @@ -198,7 +196,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); - vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) && + vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && (power_control & PCI_PM_CAP_PME_D3cold); pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); @@ -1834,6 +1832,8 @@ static int sky2_poll(struct net_device *dev0, int *budget) u16 hwidx; u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + hwidx = sky2_read16(hw, STAT_PUT_IDX); BUG_ON(hwidx >= STATUS_RING_SIZE); rmb(); @@ -1913,12 +1913,10 @@ static int sky2_poll(struct net_device *dev0, int *budget) } exit_loop: - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - sky2_tx_check(hw, 0, tx_done[0]); sky2_tx_check(hw, 1, tx_done[1]); - if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) { + if (likely(work_done < to_do)) { /* need to restart TX timer */ if (is_ec_a1(hw)) { sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); @@ -2141,14 +2139,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) static int sky2_reset(struct sky2_hw *hw) { - u32 ctst; u16 status; u8 t8, pmd_type; - int i; - - ctst = sky2_read32(hw, B0_CTST); + int i, err; sky2_write8(hw, B0_CTST, CS_RST_CLR); + hw->chip_id = sky2_read8(hw, B2_CHIP_ID); if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", @@ -2156,12 +2152,6 @@ static int sky2_reset(struct sky2_hw *hw) return -EOPNOTSUPP; } - /* ring for status responses */ - hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, - &hw->st_dma); - if (!hw->st_le) - return -ENOMEM; - /* disable ASF */ if (hw->chip_id <= CHIP_ID_YUKON_EC) { sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); @@ -2173,19 +2163,24 @@ static int sky2_reset(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_RST_CLR); /* clear PCI errors, if any */ - pci_read_config_word(hw->pdev, PCI_STATUS, &status); + err = pci_read_config_word(hw->pdev, PCI_STATUS, &status); + if (err) + goto pci_err; + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(hw->pdev, PCI_STATUS, - status | PCI_STATUS_ERROR_BITS); + err = pci_write_config_word(hw->pdev, PCI_STATUS, + status | PCI_STATUS_ERROR_BITS); + if (err) + goto pci_err; sky2_write8(hw, B0_CTST, CS_MRST_CLR); /* clear any PEX errors */ - if (is_pciex(hw)) { - u16 lstat; - pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, - 0xffffffffUL); - pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat); + if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) { + err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, + 0xffffffffUL); + if (err) + goto pci_err; } pmd_type = sky2_read8(hw, B2_PMD_TYP); @@ -2297,6 +2292,14 @@ static int sky2_reset(struct sky2_hw *hw) sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); return 0; + +pci_err: + /* This is to catch a BIOS bug workaround where + * mmconfig table doesn't have other buses. + */ + printk(KERN_ERR PFX "%s: can't access PCI config space\n", + pci_name(hw->pdev)); + return err; } static u32 sky2_supported_modes(const struct sky2_hw *hw) @@ -2551,19 +2554,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) static int sky2_set_mac_address(struct net_device *dev, void *p) { struct sky2_port *sky2 = netdev_priv(dev); - struct sockaddr *addr = p; + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + const struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8, + memcpy_toio(hw->regs + B2_MAC_1 + port * 8, dev->dev_addr, ETH_ALEN); - memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8, + memcpy_toio(hw->regs + B2_MAC_2 + port * 8, dev->dev_addr, ETH_ALEN); - if (netif_running(dev)) - sky2_phy_reinit(sky2); + /* virtual address for data */ + gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + + /* physical address: used for pause frames */ + gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); return 0; } @@ -2843,7 +2851,7 @@ static int sky2_set_coalesce(struct net_device *dev, if (ecmd->rx_coalesce_usecs_irq == 0) sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); else { - sky2_write32(hw, STAT_TX_TIMER_INI, + sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); } @@ -3055,6 +3063,61 @@ static void __devinit sky2_show_addr(struct net_device *dev) dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); } +/* Handle software interrupt used during MSI test */ +static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct sky2_hw *hw = dev_id; + u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); + + if (status == 0) + return IRQ_NONE; + + if (status & Y2_IS_IRQ_SW) { + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + hw->msi = 1; + } + sky2_write32(hw, B0_Y2_SP_ICR, 2); + + sky2_read32(hw, B0_IMSK); + return IRQ_HANDLED; +} + +/* Test interrupt path by forcing a a software IRQ */ +static int __devinit sky2_test_msi(struct sky2_hw *hw) +{ + struct pci_dev *pdev = hw->pdev; + int i, err; + + sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); + + err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); + if (err) { + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", + pci_name(pdev), pdev->irq); + return err; + } + + sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); + wmb(); + + for (i = 0; i < 10; i++) { + barrier(); + if (hw->msi) + goto found; + mdelay(1); + } + + err = -EOPNOTSUPP; + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + found: + sky2_write32(hw, B0_IMSK, 0); + + free_irq(pdev->irq, hw); + + return err; +} + static int __devinit sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3135,6 +3198,12 @@ static int __devinit sky2_probe(struct pci_dev *pdev, } hw->pm_cap = pm_cap; + /* ring for status responses */ + hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, + &hw->st_dma); + if (!hw->st_le) + goto err_out_iounmap; + err = sky2_reset(hw); if (err) goto err_out_iounmap; @@ -3169,7 +3238,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev, } } - err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); + if (!disable_msi && pci_enable_msi(pdev) == 0) { + err = sky2_test_msi(hw); + if (err == -EOPNOTSUPP) { + /* MSI test failed, go back to INTx mode */ + printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " + "switching to INTx mode. Please report this failure to " + "the PCI maintainer and include system chipset information.\n", + pci_name(pdev)); + pci_disable_msi(pdev); + } + else if (err) + goto err_out_unregister; + } + + err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, + DRV_NAME, hw); if (err) { printk(KERN_ERR PFX "%s: cannot assign irq %d\n", pci_name(pdev), pdev->irq); @@ -3184,6 +3268,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, return 0; err_out_unregister: + if (hw->msi) + pci_disable_msi(pdev); if (dev1) { unregister_netdev(dev1); free_netdev(dev1); @@ -3226,6 +3312,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); + if (hw->msi) + pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); pci_disable_device(pdev); @@ -3263,25 +3351,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) static int sky2_resume(struct pci_dev *pdev) { struct sky2_hw *hw = pci_get_drvdata(pdev); - int i; + int i, err; pci_restore_state(pdev); pci_enable_wake(pdev, PCI_D0, 0); - sky2_set_power_state(hw, PCI_D0); + err = sky2_set_power_state(hw, PCI_D0); + if (err) + goto out; - sky2_reset(hw); + err = sky2_reset(hw); + if (err) + goto out; for (i = 0; i < 2; i++) { struct net_device *dev = hw->dev[i]; - if (dev) { - if (netif_running(dev)) { - netif_device_attach(dev); - if (sky2_up(dev)) - dev_close(dev); + if (dev && netif_running(dev)) { + netif_device_attach(dev); + err = sky2_up(dev); + if (err) { + printk(KERN_ERR PFX "%s: could not up: %d\n", + dev->name, err); + dev_close(dev); + break; } } } - return 0; +out: + return err; } #endif diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 95518921001c..fd12c289a238 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1841,6 +1841,7 @@ struct sky2_hw { struct net_device *dev[2]; int pm_cap; + int msi; u8 chip_id; u8 chip_rev; u8 copper; @@ -1867,14 +1868,6 @@ static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg) return readb(hw->regs + reg); } -/* This should probably go away, bus based tweeks suck */ -static inline int is_pciex(const struct sky2_hw *hw) -{ - u32 status; - pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status); - return (status & PCI_OS_PCI_X) == 0; -} - static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val) { writel(val, hw->regs + reg); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f2d1dafde087..e7dc653d5bd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.48" -#define DRV_MODULE_RELDATE "Jan 16, 2006" +#define DRV_MODULE_VERSION "3.49" +#define DRV_MODULE_RELDATE "Feb 2, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3482,6 +3482,17 @@ static void tg3_reset_task(void *_data) struct tg3 *tp = _data; unsigned int restart_timer; + tg3_full_lock(tp, 0); + tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; + + if (!netif_running(tp->dev)) { + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; + tg3_full_unlock(tp); + return; + } + + tg3_full_unlock(tp); + tg3_netif_stop(tp); tg3_full_lock(tp, 1); @@ -3494,10 +3505,12 @@ static void tg3_reset_task(void *_data) tg3_netif_start(tp); - tg3_full_unlock(tp); - if (restart_timer) mod_timer(&tp->timer, jiffies + 1); + + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; + + tg3_full_unlock(tp); } static void tg3_tx_timeout(struct net_device *dev) @@ -6786,6 +6799,13 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); + /* Calling flush_scheduled_work() may deadlock because + * linkwatch_event() may be on the workqueue and it will try to get + * the rtnl_lock which we are holding. + */ + while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) + msleep(1); + netif_stop_queue(dev); del_timer_sync(&tp->timer); @@ -10880,6 +10900,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) if (dev) { struct tg3 *tp = netdev_priv(dev); + flush_scheduled_work(); unregister_netdev(dev); if (tp->regs) { iounmap(tp->regs); @@ -10901,6 +10922,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) if (!netif_running(dev)) return 0; + flush_scheduled_work(); tg3_netif_stop(tp); del_timer_sync(&tp->timer); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index e8243305f0e8..7f4b7f6ac40d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2162,6 +2162,7 @@ struct tg3 { #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 +#define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_SPLIT_MODE 0x40000000 diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 983981666800..238e9c72cb3a 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -214,7 +214,7 @@ static u32 uli526x_cr6_user_set; /* For module input parameter */ static int debug; static u32 cr6set; -static unsigned char mode = 8; +static int mode = 8; /* function declaration ------------------------------------- */ static int uli526x_open(struct net_device *); diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 2f61a47b4716..1ff5de076d21 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -1943,7 +1943,7 @@ static int dscc4_init_ring(struct net_device *dev) (++i%TX_RING_SIZE)*sizeof(*tx_fd)); } while (i < TX_RING_SIZE); - if (dscc4_init_dummy_skb(dpriv) < 0) + if (!dscc4_init_dummy_skb(dpriv)) goto err_free_dma_tx; memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE); diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index 8dea07b47999..eba8e5cfacc2 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -29,7 +29,7 @@ #include <linux/netdevice.h> #include <linux/hdlc.h> #include <linux/pci.h> -#include <asm/delay.h> +#include <linux/delay.h> #include <asm/io.h> #include "hd64572.h" diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 9c1e10602f2b..9d3b51c3ef54 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -27,8 +27,8 @@ #include <linux/hdlc.h> #include <linux/pci.h> #include <linux/dma-mapping.h> +#include <linux/delay.h> #include <asm/io.h> -#include <asm/delay.h> #include "wanxl.h" diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 233a4f608084..ef85d76575a2 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -148,7 +148,7 @@ config IPW2100 In order to use this driver, you will need a firmware image for it. You can obtain the firmware from <http://ipw2100.sf.net/>. Once you have the firmware image, you - will need to place it in /etc/firmware. + will need to place it in /lib/firmware. You will also very likely need the Wireless Tools in order to configure your card: diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig index c8f6286dd35f..308f773ad566 100644 --- a/drivers/net/wireless/hostap/Kconfig +++ b/drivers/net/wireless/hostap/Kconfig @@ -75,7 +75,7 @@ config HOSTAP_PCI config HOSTAP_CS tristate "Host AP driver for Prism2/2.5/3 PC Cards" - depends on PCMCIA!=n && HOSTAP + depends on PCMCIA && HOSTAP ---help--- Host AP driver's version for Prism2/2.5/3 PC Cards. diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 8bf02763b5c7..6290c9f7e939 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -2201,6 +2201,17 @@ static int ipw2100_alloc_skb(struct ipw2100_priv *priv, #define SEARCH_SNAPSHOT 1 #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) +static void ipw2100_snapshot_free(struct ipw2100_priv *priv) +{ + int i; + if (!priv->snapshot[0]) + return; + for (i = 0; i < 0x30; i++) + kfree(priv->snapshot[i]); + priv->snapshot[0] = NULL; +} + +#ifdef CONFIG_IPW2100_DEBUG_C3 static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) { int i; @@ -2221,16 +2232,6 @@ static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) return 1; } -static void ipw2100_snapshot_free(struct ipw2100_priv *priv) -{ - int i; - if (!priv->snapshot[0]) - return; - for (i = 0; i < 0x30; i++) - kfree(priv->snapshot[i]); - priv->snapshot[0] = NULL; -} - static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, size_t len, int mode) { @@ -2269,6 +2270,7 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, return ret; } +#endif /* * @@ -7112,11 +7114,17 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, { struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0, value; + + if (ipw_radio_kill_sw(priv, wrqu->txpower.disabled)) + return -EINPROGRESS; if (priv->ieee->iw_mode != IW_MODE_ADHOC) + return 0; + + if ((wrqu->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) return -EINVAL; - if (wrqu->txpower.disabled == 1 || wrqu->txpower.fixed == 0) + if (wrqu->txpower.fixed == 0) value = IPW_TX_POWER_DEFAULT; else { if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM || @@ -7151,24 +7159,19 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); - if (priv->ieee->iw_mode != IW_MODE_ADHOC) { - wrqu->power.disabled = 1; - return 0; - } + wrqu->txpower.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; if (priv->tx_power == IPW_TX_POWER_DEFAULT) { - wrqu->power.fixed = 0; - wrqu->power.value = IPW_TX_POWER_MAX_DBM; - wrqu->power.disabled = 1; + wrqu->txpower.fixed = 0; + wrqu->txpower.value = IPW_TX_POWER_MAX_DBM; } else { - wrqu->power.disabled = 0; - wrqu->power.fixed = 1; - wrqu->power.value = priv->tx_power; + wrqu->txpower.fixed = 1; + wrqu->txpower.value = priv->tx_power; } - wrqu->power.flags = IW_TXPOW_DBM; + wrqu->txpower.flags = IW_TXPOW_DBM; - IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->power.value); + IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value); return 0; } diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 4c28e332ecc3..14beab4bc91c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2456,7 +2456,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) copy. Otherwise let the firmware know to perform the operation on it's own */ - if ((priv->eeprom + EEPROM_VERSION) != 0) { + if (priv->eeprom[EEPROM_VERSION] != 0) { IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); /* write the eeprom data to sram */ @@ -8012,6 +8012,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) else IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); + priv->config &= ~CFG_STATIC_ESSID; + priv->essid_len = 0; + memset(priv->essid, 0, IW_ESSID_MAX_SIZE); + if (disable) { priv->status |= STATUS_RF_KILL_SW; IPW_DEBUG_INFO("Radio disabled.\n"); @@ -11035,7 +11039,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; priv->wireless_data.spy_data = &priv->ieee->spy_data; - priv->wireless_data.ieee80211 = priv->ieee; net_dev->wireless_data = &priv->wireless_data; net_dev->wireless_handlers = &ipw_wx_handler_def; net_dev->ethtool_ops = &ipw_ethtool_ops; @@ -11121,8 +11124,8 @@ static void ipw_pci_remove(struct pci_dev *pdev) /* Free MAC hash list for ADHOC */ for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) { list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { - kfree(list_entry(p, struct ipw_ibss_seq, list)); list_del(p); + kfree(list_entry(p, struct ipw_ibss_seq, list)); } } diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index b664708481cc..ec6f2a48895b 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -261,13 +261,13 @@ orinoco_cs_config(dev_link_t *link) /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); + DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); if (!ignore_cis_vcc) goto next_entry; } } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); + DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); if(!ignore_cis_vcc) goto next_entry; } @@ -590,6 +590,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index c5cd61c7f927..e5bb9f5ae429 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, if (essid->length) { dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ /* if it is to big, trunk it */ - dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length); + dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); } else { dwrq->flags = 0; dwrq->length = 0; diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 9e0229f7e25f..f46e8438e0d2 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1423,7 +1423,7 @@ static void __init ccio_init_resources(struct ioc *ioc) struct resource *res = ioc->mmio_region; char *name = kmalloc(14, GFP_KERNEL); - sprintf(name, "GSC Bus [%d/]", ioc->hw_path); + snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path); ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low); ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv); @@ -1557,12 +1557,11 @@ static int ccio_probe(struct parisc_device *dev) int i; struct ioc *ioc, **ioc_p = &ioc_list; - ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL); + ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL); if (ioc == NULL) { printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); return 1; } - memset(ioc, 0, sizeof(struct ioc)); ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; @@ -1578,7 +1577,7 @@ static int ccio_probe(struct parisc_device *dev) ccio_ioc_init(ioc); ccio_init_resources(ioc); hppa_dma_ops = &ccio_ops; - dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL); + dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL); /* if this fails, no I/O cards will work, so may as well bug */ BUG_ON(dev->dev.platform_data == NULL); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 216d1d859326..3d1a7f98c676 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -989,14 +989,12 @@ static int __init dino_probe(struct parisc_device *dev) */ } - dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL); + dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL); if (!dino_dev) { printk("dino_init_chip - couldn't alloc dino_device\n"); return 1; } - memset(dino_dev, 0, sizeof(struct dino_device)); - dino_dev->hba.dev = dev; dino_dev->hba.base_addr = ioremap(hpa, 4096); dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 5edf93f80757..07dc2b6d4e93 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -60,12 +60,11 @@ static int hppb_probe(struct parisc_device *dev) } if(card->hpa) { - card->next = kmalloc(sizeof(struct hppb_card), GFP_KERNEL); + card->next = kzalloc(sizeof(struct hppb_card), GFP_KERNEL); if(!card->next) { printk(KERN_ERR "HP-PB: Unable to allocate memory.\n"); return 1; } - memset(card->next, '\0', sizeof(struct hppb_card)); card = card->next; } printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 19657efa8dc3..8d7a36392eb8 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -873,28 +873,24 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL); + isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); if (!isi) { BUG(); return NULL; } - memset(isi, 0, sizeof(struct iosapic_info)); - isi->addr = ioremap(hpa, 4096); isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; vip = isi->isi_vector = (struct vector_info *) - kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL); + kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL); if (vip == NULL) { kfree(isi); return NULL; } - memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors); - for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { vip->irqline = (unsigned char) cnt; vip->iosapic = isi; diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index 2b3ba1dcf332..cb3d28176129 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -166,11 +166,12 @@ static void lasi_power_off(void) int __init lasi_init_chip(struct parisc_device *dev) { + extern void (*chassis_power_off)(void); struct gsc_asic *lasi; struct gsc_irq gsc_irq; int ret; - lasi = kmalloc(sizeof(*lasi), GFP_KERNEL); + lasi = kzalloc(sizeof(*lasi), GFP_KERNEL); if (!lasi) return -ENOMEM; @@ -222,7 +223,7 @@ lasi_init_chip(struct parisc_device *dev) * ensure that only the first LASI (the one controlling the power off) * should set the HPA here */ lasi_power_off_hpa = lasi->hpa; - pm_power_off = lasi_power_off; + chassis_power_off = lasi_power_off; return ret; } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index cbae8c8963fa..e8a2a4a852f5 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1565,7 +1565,7 @@ lba_driver_probe(struct parisc_device *dev) } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) { func_class &= 0xff; version = kmalloc(6, GFP_KERNEL); - sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf)); + snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf)); /* We could use one printk for both Elroy and Mercury, * but for the mask for func_class. */ @@ -1586,14 +1586,12 @@ lba_driver_probe(struct parisc_device *dev) ** have an IRT entry will get NULL back from iosapic code. */ - lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL); + lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL); if (!lba_dev) { printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n"); return(1); } - memset(lba_dev, 0, sizeof(struct lba_device)); - /* ---------- First : initialize data we already have --------- */ diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 42a3c54e8e6c..a28e17898fbd 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -1,7 +1,7 @@ /* * Interfaces to retrieve and set PDC Stable options (firmware) * - * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.org> * * 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 @@ -26,11 +26,19 @@ * * Since locations between 96 and 192 are the various paths, most (if not * all) PA-RISC machines should have them. Anyway, for safety reasons, the - * following code can deal with only 96 bytes of Stable Storage, and all + * following code can deal with just 96 bytes of Stable Storage, and all * sizes between 96 and 192 bytes (provided they are multiple of struct * device_path size, eg: 128, 160 and 192) to provide full information. * The code makes no use of data above 192 bytes. One last word: there's one * path we can always count on: the primary path. + * + * The current policy wrt file permissions is: + * - write: root only + * - read: (reading triggers PDC calls) ? root only : everyone + * The rationale is that PDC calls could hog (DoS) the machine. + * + * TODO: + * - timer/fastsize write calls */ #undef PDCS_DEBUG @@ -50,13 +58,15 @@ #include <linux/kobject.h> #include <linux/device.h> #include <linux/errno.h> +#include <linux/spinlock.h> #include <asm/pdc.h> #include <asm/page.h> #include <asm/uaccess.h> #include <asm/hardware.h> -#define PDCS_VERSION "0.10" +#define PDCS_VERSION "0.22" +#define PDCS_PREFIX "PDC Stable Storage" #define PDCS_ADDR_PPRI 0x00 #define PDCS_ADDR_OSID 0x40 @@ -70,10 +80,12 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data"); MODULE_LICENSE("GPL"); MODULE_VERSION(PDCS_VERSION); +/* holds Stable Storage size. Initialized once and for all, no lock needed */ static unsigned long pdcs_size __read_mostly; /* This struct defines what we need to deal with a parisc pdc path entry */ struct pdcspath_entry { + rwlock_t rw_lock; /* to protect path entry access */ short ready; /* entry record is valid if != 0 */ unsigned long addr; /* entry address in stable storage */ char *name; /* entry name */ @@ -121,6 +133,8 @@ struct pdcspath_attribute paths_attr_##_name = { \ * content of the stable storage WRT various paths in these structs. We read * these structs when reading the files, and we will write to these structs when * writing to the files, and only then write them back to the Stable Storage. + * + * This function expects to be called with @entry->rw_lock write-hold. */ static int pdcspath_fetch(struct pdcspath_entry *entry) @@ -160,14 +174,15 @@ pdcspath_fetch(struct pdcspath_entry *entry) * pointer, from which it'll find out the corresponding hardware path. * For now we do not handle the case where there's an error in writing to the * Stable Storage area, so you'd better not mess up the data :P + * + * This function expects to be called with @entry->rw_lock write-hold. */ -static int +static void pdcspath_store(struct pdcspath_entry *entry) { struct device_path *devpath; - if (!entry) - return -EINVAL; + BUG_ON(!entry); devpath = &entry->devpath; @@ -176,10 +191,8 @@ pdcspath_store(struct pdcspath_entry *entry) First case, we don't have a preset hwpath... */ if (!entry->ready) { /* ...but we have a device, map it */ - if (entry->dev) - device_to_hwpath(entry->dev, (struct hardware_path *)devpath); - else - return -EINVAL; + BUG_ON(!entry->dev); + device_to_hwpath(entry->dev, (struct hardware_path *)devpath); } /* else, we expect the provided hwpath to be valid. */ @@ -191,15 +204,13 @@ pdcspath_store(struct pdcspath_entry *entry) printk(KERN_ERR "%s: an error occured when writing to PDC.\n" "It is likely that the Stable Storage data has been corrupted.\n" "Please check it carefully upon next reboot.\n", __func__); - return -EIO; + WARN_ON(1); } /* kobject is already registered */ entry->ready = 2; DPRINTK("%s: device: 0x%p\n", __func__, entry->dev); - - return 0; } /** @@ -214,14 +225,17 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) { char *out = buf; struct device_path *devpath; - unsigned short i; + short i; if (!entry || !buf) return -EINVAL; + read_lock(&entry->rw_lock); devpath = &entry->devpath; + i = entry->ready; + read_unlock(&entry->rw_lock); - if (!entry->ready) + if (!i) /* entry is not ready */ return -ENODATA; for (i = 0; i < 6; i++) { @@ -242,7 +256,7 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) * * We will call this function to change the current hardware path. * Hardware paths are to be given '/'-delimited, without brackets. - * We take care to make sure that the provided path actually maps to an existing + * We make sure that the provided path actually maps to an existing * device, BUT nothing would prevent some foolish user to set the path to some * PCI bridge or even a CPU... * A better work around would be to make sure we are at the end of a device tree @@ -298,17 +312,19 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun } /* So far so good, let's get in deep */ + write_lock(&entry->rw_lock); entry->ready = 0; entry->dev = dev; /* Now, dive in. Write back to the hardware */ - WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */ + pdcspath_store(entry); /* Update the symlink to the real device */ sysfs_remove_link(&entry->kobj, "device"); sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + write_unlock(&entry->rw_lock); - printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n", + printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n", entry->name, buf); return count; @@ -326,14 +342,17 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf) { char *out = buf; struct device_path *devpath; - unsigned short i; + short i; if (!entry || !buf) return -EINVAL; + read_lock(&entry->rw_lock); devpath = &entry->devpath; + i = entry->ready; + read_unlock(&entry->rw_lock); - if (!entry->ready) + if (!i) /* entry is not ready */ return -ENODATA; for (i = 0; devpath->layers[i] && (likely(i < 6)); i++) @@ -388,15 +407,17 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count } /* So far so good, let's get in deep */ + write_lock(&entry->rw_lock); /* First, overwrite the current layers with the new ones, not touching the hardware path. */ memcpy(&entry->devpath.layers, &layers, sizeof(layers)); /* Now, dive in. Write back to the hardware */ - WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */ + pdcspath_store(entry); + write_unlock(&entry->rw_lock); - printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n", + printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n", entry->name, buf); return count; @@ -415,9 +436,6 @@ pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr); ssize_t ret = 0; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (pdcs_attr->show) ret = pdcs_attr->show(entry, buf); @@ -454,8 +472,8 @@ static struct sysfs_ops pdcspath_attr_ops = { }; /* These are the two attributes of any PDC path. */ -static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write); -static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write); +static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write); +static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write); static struct attribute *paths_subsys_attrs[] = { &paths_attr_hwpath.attr, @@ -484,36 +502,119 @@ static struct pdcspath_entry *pdcspath_entries[] = { NULL, }; + +/* For more insight of what's going on here, refer to PDC Procedures doc, + * Section PDC_STABLE */ + /** - * pdcs_info_read - Pretty printing of the remaining useful data. + * pdcs_size_read - Stable Storage size output. * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. - * - * We will call this function to format the output of the 'info' attribute file. - * Please refer to PDC Procedures documentation, section PDC_STABLE to get a - * better insight of what we're doing here. */ static ssize_t -pdcs_info_read(struct subsystem *entry, char *buf) +pdcs_size_read(struct subsystem *entry, char *buf) { char *out = buf; - __u32 result; - struct device_path devpath; - char *tmpstr = NULL; if (!entry || !buf) return -EINVAL; /* show the size of the stable storage */ - out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size); + out += sprintf(out, "%ld\n", pdcs_size); - /* deal with flags */ - if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK) - return -EIO; + return out - buf; +} + +/** + * pdcs_auto_read - Stable Storage autoboot/search flag output. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag + */ +static ssize_t +pdcs_auto_read(struct subsystem *entry, char *buf, int knob) +{ + char *out = buf; + struct pdcspath_entry *pathentry; - out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off"); - out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off"); - out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0); + if (!entry || !buf) + return -EINVAL; + + /* Current flags are stored in primary boot path entry */ + pathentry = &pdcspath_entry_primary; + + read_lock(&pathentry->rw_lock); + out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ? + "On" : "Off"); + read_unlock(&pathentry->rw_lock); + + return out - buf; +} + +/** + * pdcs_autoboot_read - Stable Storage autoboot flag output. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + */ +static inline ssize_t +pdcs_autoboot_read(struct subsystem *entry, char *buf) +{ + return pdcs_auto_read(entry, buf, PF_AUTOBOOT); +} + +/** + * pdcs_autosearch_read - Stable Storage autoboot flag output. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + */ +static inline ssize_t +pdcs_autosearch_read(struct subsystem *entry, char *buf) +{ + return pdcs_auto_read(entry, buf, PF_AUTOSEARCH); +} + +/** + * pdcs_timer_read - Stable Storage timer count output (in seconds). + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + * + * The value of the timer field correponds to a number of seconds in powers of 2. + */ +static ssize_t +pdcs_timer_read(struct subsystem *entry, char *buf) +{ + char *out = buf; + struct pdcspath_entry *pathentry; + + if (!entry || !buf) + return -EINVAL; + + /* Current flags are stored in primary boot path entry */ + pathentry = &pdcspath_entry_primary; + + /* print the timer value in seconds */ + read_lock(&pathentry->rw_lock); + out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ? + (1 << (pathentry->devpath.flags & PF_TIMER)) : 0); + read_unlock(&pathentry->rw_lock); + + return out - buf; +} + +/** + * pdcs_osid_read - Stable Storage OS ID register output. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + */ +static ssize_t +pdcs_osid_read(struct subsystem *entry, char *buf) +{ + char *out = buf; + __u32 result; + char *tmpstr = NULL; + + if (!entry || !buf) + return -EINVAL; /* get OSID */ if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK) @@ -529,13 +630,31 @@ pdcs_info_read(struct subsystem *entry, char *buf) case 0x0005: tmpstr = "Novell Netware dependent data"; break; default: tmpstr = "Unknown"; break; } - out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16)); + out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16)); + + return out - buf; +} + +/** + * pdcs_fastsize_read - Stable Storage FastSize register output. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The output buffer to write to. + * + * This register holds the amount of system RAM to be tested during boot sequence. + */ +static ssize_t +pdcs_fastsize_read(struct subsystem *entry, char *buf) +{ + char *out = buf; + __u32 result; + + if (!entry || !buf) + return -EINVAL; /* get fast-size */ if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK) return -EIO; - out += sprintf(out, "Memory tested: "); if ((result & 0x0F) < 0x0E) out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256); else @@ -546,22 +665,18 @@ pdcs_info_read(struct subsystem *entry, char *buf) } /** - * pdcs_info_write - This function handles boot flag modifying. + * pdcs_auto_write - This function handles autoboot/search flag modifying. * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. + * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag * - * We will call this function to change the current boot flags. + * We will call this function to change the current autoboot flag. * We expect a precise syntax: - * \"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch - * - * As of now there is no incentive on my side to provide more "knobs" to that - * interface, since modifying the rest of the data is pretty meaningless when - * the machine is running and for the expected use of that facility, such as - * PALO setting up the boot disk when installing a Linux distribution... + * \"n\" (n == 0 or 1) to toggle AutoBoot Off or On */ static ssize_t -pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) +pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob) { struct pdcspath_entry *pathentry; unsigned char flags; @@ -582,7 +697,9 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) pathentry = &pdcspath_entry_primary; /* Be nice to the existing flag record */ + read_lock(&pathentry->rw_lock); flags = pathentry->devpath.flags; + read_unlock(&pathentry->rw_lock); DPRINTK("%s: flags before: 0x%X\n", __func__, flags); @@ -595,50 +712,85 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) if ((c != 0) && (c != 1)) goto parse_error; if (c == 0) - flags &= ~PF_AUTOBOOT; + flags &= ~knob; else - flags |= PF_AUTOBOOT; - - if (*temp++ != ' ') - goto parse_error; - - c = *temp++ - '0'; - if ((c != 0) && (c != 1)) - goto parse_error; - if (c == 0) - flags &= ~PF_AUTOSEARCH; - else - flags |= PF_AUTOSEARCH; + flags |= knob; DPRINTK("%s: flags after: 0x%X\n", __func__, flags); /* So far so good, let's get in deep */ + write_lock(&pathentry->rw_lock); /* Change the path entry flags first */ pathentry->devpath.flags = flags; /* Now, dive in. Write back to the hardware */ - WARN_ON(pdcspath_store(pathentry)); /* this warn should *NEVER* happen */ + pdcspath_store(pathentry); + write_unlock(&pathentry->rw_lock); - printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf); + printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" to \"%s\"\n", + (knob & PF_AUTOBOOT) ? "autoboot" : "autosearch", + (flags & knob) ? "On" : "Off"); return count; parse_error: - printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__); + printk(KERN_WARNING "%s: Parse error: expect \"n\" (n == 0 or 1)\n", __func__); return -EINVAL; } -/* The last attribute (the 'root' one actually) with all remaining data. */ -static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write); +/** + * pdcs_autoboot_write - This function handles autoboot flag modifying. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The input buffer to read from. + * @count: The number of bytes to be read. + * + * We will call this function to change the current boot flags. + * We expect a precise syntax: + * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On + */ +static inline ssize_t +pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count) +{ + return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT); +} + +/** + * pdcs_autosearch_write - This function handles autosearch flag modifying. + * @entry: An allocated and populated subsytem struct. We don't use it tho. + * @buf: The input buffer to read from. + * @count: The number of bytes to be read. + * + * We will call this function to change the current boot flags. + * We expect a precise syntax: + * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On + */ +static inline ssize_t +pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count) +{ + return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH); +} + +/* The remaining attributes. */ +static PDCS_ATTR(size, 0444, pdcs_size_read, NULL); +static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write); +static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write); +static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL); +static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL); +static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL); static struct subsys_attribute *pdcs_subsys_attrs[] = { - &pdcs_attr_info, - NULL, /* maybe more in the future? */ + &pdcs_attr_size, + &pdcs_attr_autoboot, + &pdcs_attr_autosearch, + &pdcs_attr_timer, + &pdcs_attr_osid, + &pdcs_attr_fastsize, + NULL, }; static decl_subsys(paths, &ktype_pdcspath, NULL); -static decl_subsys(pdc, NULL, NULL); +static decl_subsys(stable, NULL, NULL); /** * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage. @@ -656,8 +808,16 @@ pdcs_register_pathentries(void) struct pdcspath_entry *entry; int err; + /* Initialize the entries rw_lock before anything else */ + for (i = 0; (entry = pdcspath_entries[i]); i++) + rwlock_init(&entry->rw_lock); + for (i = 0; (entry = pdcspath_entries[i]); i++) { - if (pdcspath_fetch(entry) < 0) + write_lock(&entry->rw_lock); + err = pdcspath_fetch(entry); + write_unlock(&entry->rw_lock); + + if (err < 0) continue; if ((err = kobject_set_name(&entry->kobj, "%s", entry->name))) @@ -667,13 +827,14 @@ pdcs_register_pathentries(void) return err; /* kobject is now registered */ + write_lock(&entry->rw_lock); entry->ready = 2; - if (!entry->dev) - continue; - /* Add a nice symlink to the real device */ - sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + if (entry->dev) + sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + + write_unlock(&entry->rw_lock); } return 0; @@ -688,14 +849,17 @@ pdcs_unregister_pathentries(void) unsigned short i; struct pdcspath_entry *entry; - for (i = 0; (entry = pdcspath_entries[i]); i++) + for (i = 0; (entry = pdcspath_entries[i]); i++) { + read_lock(&entry->rw_lock); if (entry->ready >= 2) - kobject_unregister(&entry->kobj); + kobject_unregister(&entry->kobj); + read_unlock(&entry->rw_lock); + } } /* - * For now we register the pdc subsystem with the firmware subsystem - * and the paths subsystem with the pdc subsystem + * For now we register the stable subsystem with the firmware subsystem + * and the paths subsystem with the stable subsystem */ static int __init pdc_stable_init(void) @@ -707,19 +871,23 @@ pdc_stable_init(void) if (pdc_stable_get_size(&pdcs_size) != PDC_OK) return -ENODEV; - printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION); + /* make sure we have enough data */ + if (pdcs_size < 96) + return -ENODATA; + + printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION); - /* For now we'll register the pdc subsys within this driver */ - if ((rc = firmware_register(&pdc_subsys))) + /* For now we'll register the stable subsys within this driver */ + if ((rc = firmware_register(&stable_subsys))) goto fail_firmreg; - /* Don't forget the info entry */ + /* Don't forget the root entries */ for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++) if (attr->show) - error = subsys_create_file(&pdc_subsys, attr); + error = subsys_create_file(&stable_subsys, attr); - /* register the paths subsys as a subsystem of pdc subsys */ - kset_set_kset_s(&paths_subsys, pdc_subsys); + /* register the paths subsys as a subsystem of stable subsys */ + kset_set_kset_s(&paths_subsys, stable_subsys); if ((rc= subsystem_register(&paths_subsys))) goto fail_subsysreg; @@ -734,10 +902,10 @@ fail_pdcsreg: subsystem_unregister(&paths_subsys); fail_subsysreg: - firmware_unregister(&pdc_subsys); + firmware_unregister(&stable_subsys); fail_firmreg: - printk(KERN_INFO "PDC Stable Storage bailing out\n"); + printk(KERN_INFO PDCS_PREFIX " bailing out\n"); return rc; } @@ -747,7 +915,7 @@ pdc_stable_exit(void) pdcs_unregister_pathentries(); subsystem_unregister(&paths_subsys); - firmware_unregister(&pdc_subsys); + firmware_unregister(&stable_subsys); } diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index c85653f315aa..52f265e97729 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -2064,14 +2064,13 @@ sba_driver_callback(struct parisc_device *dev) printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME, version, dev->hpa.start); - sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); + sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL); if (!sba_dev) { printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n"); return -ENOMEM; } parisc_set_drvdata(dev, sba_dev); - memset(sba_dev, 0, sizeof(struct sba_device)); for(i=0; i<MAX_IOC; i++) spin_lock_init(&(sba_dev->ioc[i].res_lock)); diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index d14888e149bb..ba971fecd0d8 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -89,6 +89,9 @@ static struct superio_device sio_dev; #define DBG_INIT(x...) #endif +#define SUPERIO "SuperIO" +#define PFX SUPERIO ": " + static irqreturn_t superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) { @@ -117,7 +120,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) local_irq = results & 0x0f; if (local_irq == 2 || local_irq > 7) { - printk(KERN_ERR "SuperIO: slave interrupted!\n"); + printk(KERN_ERR PFX "slave interrupted!\n"); return IRQ_HANDLED; } @@ -128,7 +131,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) outb(OCW3_ISR,IC_PIC1+0); results = inb(IC_PIC1+0); if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ - printk(KERN_WARNING "SuperIO: spurious interrupt!\n"); + printk(KERN_WARNING PFX "spurious interrupt!\n"); return IRQ_HANDLED; } } @@ -163,27 +166,27 @@ superio_init(struct pci_dev *pcidev) /* ...then properly fixup the USB to point at suckyio PIC */ sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); - printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", + printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n", pci_name(pdev), pdev->irq); pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); sio->sp1_base &= ~1; - printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base); + printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base); pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); sio->sp2_base &= ~1; - printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base); + printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base); pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); sio->pp_base &= ~1; - printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base); + printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base); pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); sio->fdc_base &= ~1; - printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base); + printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base); pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); sio->acpi_base &= ~1; - printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base); + printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base); request_region (IC_PIC1, 0x1f, "pic1"); request_region (IC_PIC2, 0x1f, "pic2"); @@ -263,14 +266,14 @@ superio_init(struct pci_dev *pcidev) /* Setup USB power regulation */ outb(1, sio->acpi_base + USB_REG_CR); if (inb(sio->acpi_base + USB_REG_CR) & 1) - printk(KERN_INFO "SuperIO: USB regulator enabled\n"); + printk(KERN_INFO PFX "USB regulator enabled\n"); else - printk(KERN_ERR "USB regulator not initialized!\n"); + printk(KERN_ERR PFX "USB regulator not initialized!\n"); if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT, - "SuperIO", (void *)sio)) { + SUPERIO, (void *)sio)) { - printk(KERN_ERR "SuperIO: could not get irq\n"); + printk(KERN_ERR PFX "could not get irq\n"); BUG(); return; } @@ -284,7 +287,7 @@ static void superio_disable_irq(unsigned int irq) u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { - printk(KERN_ERR "SuperIO: Illegal irq number.\n"); + printk(KERN_ERR PFX "Illegal irq number.\n"); BUG(); return; } @@ -301,7 +304,7 @@ static void superio_enable_irq(unsigned int irq) u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { - printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq); + printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq); BUG(); return; } @@ -319,7 +322,7 @@ static unsigned int superio_startup_irq(unsigned int irq) } static struct hw_interrupt_type superio_interrupt_type = { - .typename = "SuperIO", + .typename = SUPERIO, .startup = superio_startup_irq, .shutdown = superio_disable_irq, .enable = superio_enable_irq, @@ -413,7 +416,7 @@ static void __devinit superio_serial_init(void) retval = early_serial_setup(&serial[0]); if (retval < 0) { - printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n"); + printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); return; } @@ -423,7 +426,7 @@ static void __devinit superio_serial_init(void) retval = early_serial_setup(&serial[1]); if (retval < 0) - printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n"); + printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); #endif /* CONFIG_SERIAL_8250 */ } @@ -437,7 +440,7 @@ static void __devinit superio_parport_init(void) PARPORT_DMA_NONE /* dma */, NULL /*struct pci_dev* */) ) - printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n"); + printk(KERN_WARNING PFX "Probing parallel port failed.\n"); #endif /* CONFIG_PARPORT_PC */ } @@ -499,7 +502,7 @@ static struct pci_device_id superio_tbl[] = { }; static struct pci_driver superio_driver = { - .name = "SuperIO", + .name = SUPERIO, .id_table = superio_tbl, .probe = superio_probe, }; diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 17dce2adf7fe..813c2c24ab1e 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -76,7 +76,7 @@ wax_init_chip(struct parisc_device *dev) struct gsc_irq gsc_irq; int ret; - wax = kmalloc(sizeof(*wax), GFP_KERNEL); + wax = kzalloc(sizeof(*wax), GFP_KERNEL); if (!wax) return -ENOMEM; diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index f605dea57224..f63c387976cf 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -90,6 +90,15 @@ config PARPORT_ARC depends on ARM && PARPORT select PARPORT_NOT_PC +config PARPORT_IP32 + tristate "SGI IP32 builtin port (EXPERIMENTAL)" + depends on SGI_IP32 && PARPORT && EXPERIMENTAL + select PARPORT_NOT_PC + help + Say Y here if you need support for the parallel port on + SGI O2 machines. This code is also available as a module (say M), + called parport_ip32. If in doubt, saying N is the safe plan. + config PARPORT_AMIGA tristate "Amiga builtin port" depends on AMIGA && PARPORT diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile index 5372212bb9d9..a19de35f8de2 100644 --- a/drivers/parport/Makefile +++ b/drivers/parport/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o +obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 5b887ba5aaf9..690b239ad3a7 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -61,10 +61,10 @@ static void timeout_waiting_on_port (unsigned long cookie) * set to zero, it returns immediately. * * If an interrupt occurs before the timeout period elapses, this - * function returns one immediately. If it times out, it returns - * a value greater than zero. An error code less than zero - * indicates an error (most likely a pending signal), and the - * calling code should finish what it's doing as soon as it can. + * function returns zero immediately. If it times out, it returns + * one. An error code less than zero indicates an error (most + * likely a pending signal), and the calling code should finish + * what it's doing as soon as it can. */ int parport_wait_event (struct parport *port, signed long timeout) @@ -110,7 +110,7 @@ int parport_wait_event (struct parport *port, signed long timeout) * * If the status lines take on the desired values before the * timeout period elapses, parport_poll_peripheral() returns zero - * immediately. A zero return value greater than zero indicates + * immediately. A return value greater than zero indicates * a timeout. An error code (less than zero) indicates an error, * most likely a signal that arrived, and the caller should * finish what it is doing as soon as possible. diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index fde29a75f888..1de52d9febf9 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -249,7 +249,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base, struct parport tmp; struct parport *p = &tmp; - priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); + priv = kzalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); if (!priv) { printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); return NULL; diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c new file mode 100644 index 000000000000..46e06e596d73 --- /dev/null +++ b/drivers/parport/parport_ip32.c @@ -0,0 +1,2253 @@ +/* Low-level parallel port routines for built-in port on SGI IP32 + * + * Author: Arnaud Giersch <arnaud.giersch@free.fr> + * + * Based on parport_pc.c by + * Phil Blundell, Tim Waugh, Jose Renau, David Campbell, + * Andrea Arcangeli, et al. + * + * Thanks to Ilya A. Volynets-Evenbakh for his help. + * + * Copyright (C) 2005, 2006 Arnaud Giersch. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Current status: + * + * Basic SPP and PS2 modes are supported. + * Support for parallel port IRQ is present. + * Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are + * supported. + * SPP/ECP FIFO can be driven in PIO or DMA mode. PIO mode can work with + * or without interrupt support. + * + * Hardware ECP mode is not fully implemented (ecp_read_data and + * ecp_write_addr are actually missing). + * + * To do: + * + * Fully implement ECP mode. + * EPP and ECP mode need to be tested. I currently do not own any + * peripheral supporting these extended mode, and cannot test them. + * If DMA mode works well, decide if support for PIO FIFO modes should be + * dropped. + * Use the io{read,write} family functions when they become available in + * the linux-mips.org tree. Note: the MIPS specific functions readsb() + * and writesb() are to be translated by ioread8_rep() and iowrite8_rep() + * respectively. + */ + +/* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an + * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1]. + * This chip supports SPP, bidirectional, EPP and ECP modes. It has a 16 byte + * FIFO buffer and supports DMA transfers. + * + * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html + * + * Theoretically, we could simply use the parport_pc module. It is however + * not so simple. The parport_pc code assumes that the parallel port + * registers are port-mapped. On the O2, they are memory-mapped. + * Furthermore, each register is replicated on 256 consecutive addresses (as + * it is for the built-in serial ports on the same chip). + */ + +/*--- Some configuration defines ---------------------------------------*/ + +/* DEBUG_PARPORT_IP32 + * 0 disable debug + * 1 standard level: pr_debug1 is enabled + * 2 parport_ip32_dump_state is enabled + * >=3 verbose level: pr_debug is enabled + */ +#if !defined(DEBUG_PARPORT_IP32) +# define DEBUG_PARPORT_IP32 0 /* 0 (disabled) for production */ +#endif + +/*----------------------------------------------------------------------*/ + +/* Setup DEBUG macros. This is done before any includes, just in case we + * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3. + */ +#if DEBUG_PARPORT_IP32 == 1 +# warning DEBUG_PARPORT_IP32 == 1 +#elif DEBUG_PARPORT_IP32 == 2 +# warning DEBUG_PARPORT_IP32 == 2 +#elif DEBUG_PARPORT_IP32 >= 3 +# warning DEBUG_PARPORT_IP32 >= 3 +# if !defined(DEBUG) +# define DEBUG /* enable pr_debug() in kernel.h */ +# endif +#endif + +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/parport.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/stddef.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/ip32/ip32_ints.h> +#include <asm/ip32/mace.h> + +/*--- Global variables -------------------------------------------------*/ + +/* Verbose probing on by default for debugging. */ +#if DEBUG_PARPORT_IP32 >= 1 +# define DEFAULT_VERBOSE_PROBING 1 +#else +# define DEFAULT_VERBOSE_PROBING 0 +#endif + +/* Default prefix for printk */ +#define PPIP32 "parport_ip32: " + +/* + * These are the module parameters: + * @features: bit mask of features to enable/disable + * (all enabled by default) + * @verbose_probing: log chit-chat during initialization + */ +#define PARPORT_IP32_ENABLE_IRQ (1U << 0) +#define PARPORT_IP32_ENABLE_DMA (1U << 1) +#define PARPORT_IP32_ENABLE_SPP (1U << 2) +#define PARPORT_IP32_ENABLE_EPP (1U << 3) +#define PARPORT_IP32_ENABLE_ECP (1U << 4) +static unsigned int features = ~0U; +static int verbose_probing = DEFAULT_VERBOSE_PROBING; + +/* We do not support more than one port. */ +static struct parport *this_port = NULL; + +/* Timing constants for FIFO modes. */ +#define FIFO_NFAULT_TIMEOUT 100 /* milliseconds */ +#define FIFO_POLLING_INTERVAL 50 /* microseconds */ + +/*--- I/O register definitions -----------------------------------------*/ + +/** + * struct parport_ip32_regs - virtual addresses of parallel port registers + * @data: Data Register + * @dsr: Device Status Register + * @dcr: Device Control Register + * @eppAddr: EPP Address Register + * @eppData0: EPP Data Register 0 + * @eppData1: EPP Data Register 1 + * @eppData2: EPP Data Register 2 + * @eppData3: EPP Data Register 3 + * @ecpAFifo: ECP Address FIFO + * @fifo: General FIFO register. The same address is used for: + * - cFifo, the Parallel Port DATA FIFO + * - ecpDFifo, the ECP Data FIFO + * - tFifo, the ECP Test FIFO + * @cnfgA: Configuration Register A + * @cnfgB: Configuration Register B + * @ecr: Extended Control Register + */ +struct parport_ip32_regs { + void __iomem *data; + void __iomem *dsr; + void __iomem *dcr; + void __iomem *eppAddr; + void __iomem *eppData0; + void __iomem *eppData1; + void __iomem *eppData2; + void __iomem *eppData3; + void __iomem *ecpAFifo; + void __iomem *fifo; + void __iomem *cnfgA; + void __iomem *cnfgB; + void __iomem *ecr; +}; + +/* Device Status Register */ +#define DSR_nBUSY (1U << 7) /* PARPORT_STATUS_BUSY */ +#define DSR_nACK (1U << 6) /* PARPORT_STATUS_ACK */ +#define DSR_PERROR (1U << 5) /* PARPORT_STATUS_PAPEROUT */ +#define DSR_SELECT (1U << 4) /* PARPORT_STATUS_SELECT */ +#define DSR_nFAULT (1U << 3) /* PARPORT_STATUS_ERROR */ +#define DSR_nPRINT (1U << 2) /* specific to TL16PIR552 */ +/* #define DSR_reserved (1U << 1) */ +#define DSR_TIMEOUT (1U << 0) /* EPP timeout */ + +/* Device Control Register */ +/* #define DCR_reserved (1U << 7) | (1U << 6) */ +#define DCR_DIR (1U << 5) /* direction */ +#define DCR_IRQ (1U << 4) /* interrupt on nAck */ +#define DCR_SELECT (1U << 3) /* PARPORT_CONTROL_SELECT */ +#define DCR_nINIT (1U << 2) /* PARPORT_CONTROL_INIT */ +#define DCR_AUTOFD (1U << 1) /* PARPORT_CONTROL_AUTOFD */ +#define DCR_STROBE (1U << 0) /* PARPORT_CONTROL_STROBE */ + +/* ECP Configuration Register A */ +#define CNFGA_IRQ (1U << 7) +#define CNFGA_ID_MASK ((1U << 6) | (1U << 5) | (1U << 4)) +#define CNFGA_ID_SHIFT 4 +#define CNFGA_ID_16 (00U << CNFGA_ID_SHIFT) +#define CNFGA_ID_8 (01U << CNFGA_ID_SHIFT) +#define CNFGA_ID_32 (02U << CNFGA_ID_SHIFT) +/* #define CNFGA_reserved (1U << 3) */ +#define CNFGA_nBYTEINTRANS (1U << 2) +#define CNFGA_PWORDLEFT ((1U << 1) | (1U << 0)) + +/* ECP Configuration Register B */ +#define CNFGB_COMPRESS (1U << 7) +#define CNFGB_INTRVAL (1U << 6) +#define CNFGB_IRQ_MASK ((1U << 5) | (1U << 4) | (1U << 3)) +#define CNFGB_IRQ_SHIFT 3 +#define CNFGB_DMA_MASK ((1U << 2) | (1U << 1) | (1U << 0)) +#define CNFGB_DMA_SHIFT 0 + +/* Extended Control Register */ +#define ECR_MODE_MASK ((1U << 7) | (1U << 6) | (1U << 5)) +#define ECR_MODE_SHIFT 5 +#define ECR_MODE_SPP (00U << ECR_MODE_SHIFT) +#define ECR_MODE_PS2 (01U << ECR_MODE_SHIFT) +#define ECR_MODE_PPF (02U << ECR_MODE_SHIFT) +#define ECR_MODE_ECP (03U << ECR_MODE_SHIFT) +#define ECR_MODE_EPP (04U << ECR_MODE_SHIFT) +/* #define ECR_MODE_reserved (05U << ECR_MODE_SHIFT) */ +#define ECR_MODE_TST (06U << ECR_MODE_SHIFT) +#define ECR_MODE_CFG (07U << ECR_MODE_SHIFT) +#define ECR_nERRINTR (1U << 4) +#define ECR_DMAEN (1U << 3) +#define ECR_SERVINTR (1U << 2) +#define ECR_F_FULL (1U << 1) +#define ECR_F_EMPTY (1U << 0) + +/*--- Private data -----------------------------------------------------*/ + +/** + * enum parport_ip32_irq_mode - operation mode of interrupt handler + * @PARPORT_IP32_IRQ_FWD: forward interrupt to the upper parport layer + * @PARPORT_IP32_IRQ_HERE: interrupt is handled locally + */ +enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE }; + +/** + * struct parport_ip32_private - private stuff for &struct parport + * @regs: register addresses + * @dcr_cache: cached contents of DCR + * @dcr_writable: bit mask of writable DCR bits + * @pword: number of bytes per PWord + * @fifo_depth: number of PWords that FIFO will hold + * @readIntrThreshold: minimum number of PWords we can read + * if we get an interrupt + * @writeIntrThreshold: minimum number of PWords we can write + * if we get an interrupt + * @irq_mode: operation mode of interrupt handler for this port + * @irq_complete: mutex used to wait for an interrupt to occur + */ +struct parport_ip32_private { + struct parport_ip32_regs regs; + unsigned int dcr_cache; + unsigned int dcr_writable; + unsigned int pword; + unsigned int fifo_depth; + unsigned int readIntrThreshold; + unsigned int writeIntrThreshold; + enum parport_ip32_irq_mode irq_mode; + struct completion irq_complete; +}; + +/*--- Debug code -------------------------------------------------------*/ + +/* + * pr_debug1 - print debug messages + * + * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1 + */ +#if DEBUG_PARPORT_IP32 >= 1 +# define pr_debug1(...) printk(KERN_DEBUG __VA_ARGS__) +#else /* DEBUG_PARPORT_IP32 < 1 */ +# define pr_debug1(...) do { } while (0) +#endif + +/* + * pr_trace, pr_trace1 - trace function calls + * @p: pointer to &struct parport + * @fmt: printk format string + * @...: parameters for format string + * + * Macros used to trace function calls. The given string is formatted after + * function name. pr_trace() uses pr_debug(), and pr_trace1() uses + * pr_debug1(). __pr_trace() is the low-level macro and is not to be used + * directly. + */ +#define __pr_trace(pr, p, fmt, ...) \ + pr("%s: %s" fmt "\n", \ + ({ const struct parport *__p = (p); \ + __p ? __p->name : "parport_ip32"; }), \ + __func__ , ##__VA_ARGS__) +#define pr_trace(p, fmt, ...) __pr_trace(pr_debug, p, fmt , ##__VA_ARGS__) +#define pr_trace1(p, fmt, ...) __pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__) + +/* + * __pr_probe, pr_probe - print message if @verbose_probing is true + * @p: pointer to &struct parport + * @fmt: printk format string + * @...: parameters for format string + * + * For new lines, use pr_probe(). Use __pr_probe() for continued lines. + */ +#define __pr_probe(...) \ + do { if (verbose_probing) printk(__VA_ARGS__); } while (0) +#define pr_probe(p, fmt, ...) \ + __pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__) + +/* + * parport_ip32_dump_state - print register status of parport + * @p: pointer to &struct parport + * @str: string to add in message + * @show_ecp_config: shall we dump ECP configuration registers too? + * + * This function is only here for debugging purpose, and should be used with + * care. Reading the parallel port registers may have undesired side effects. + * Especially if @show_ecp_config is true, the parallel port is resetted. + * This function is only defined if %DEBUG_PARPORT_IP32 >= 2. + */ +#if DEBUG_PARPORT_IP32 >= 2 +static void parport_ip32_dump_state(struct parport *p, char *str, + unsigned int show_ecp_config) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + unsigned int i; + + printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str); + { + static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF", + "ECP", "EPP", "???", + "TST", "CFG"}; + unsigned int ecr = readb(priv->regs.ecr); + printk(KERN_DEBUG PPIP32 " ecr=0x%02x", ecr); + printk(" %s", + ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]); + if (ecr & ECR_nERRINTR) + printk(",nErrIntrEn"); + if (ecr & ECR_DMAEN) + printk(",dmaEn"); + if (ecr & ECR_SERVINTR) + printk(",serviceIntr"); + if (ecr & ECR_F_FULL) + printk(",f_full"); + if (ecr & ECR_F_EMPTY) + printk(",f_empty"); + printk("\n"); + } + if (show_ecp_config) { + unsigned int oecr, cnfgA, cnfgB; + oecr = readb(priv->regs.ecr); + writeb(ECR_MODE_PS2, priv->regs.ecr); + writeb(ECR_MODE_CFG, priv->regs.ecr); + cnfgA = readb(priv->regs.cnfgA); + cnfgB = readb(priv->regs.cnfgB); + writeb(ECR_MODE_PS2, priv->regs.ecr); + writeb(oecr, priv->regs.ecr); + printk(KERN_DEBUG PPIP32 " cnfgA=0x%02x", cnfgA); + printk(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses"); + switch (cnfgA & CNFGA_ID_MASK) { + case CNFGA_ID_8: + printk(",8 bits"); + break; + case CNFGA_ID_16: + printk(",16 bits"); + break; + case CNFGA_ID_32: + printk(",32 bits"); + break; + default: + printk(",unknown ID"); + break; + } + if (!(cnfgA & CNFGA_nBYTEINTRANS)) + printk(",ByteInTrans"); + if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8) + printk(",%d byte%s left", cnfgA & CNFGA_PWORDLEFT, + ((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : ""); + printk("\n"); + printk(KERN_DEBUG PPIP32 " cnfgB=0x%02x", cnfgB); + printk(" irq=%u,dma=%u", + (cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT, + (cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT); + printk(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL)); + if (cnfgB & CNFGB_COMPRESS) + printk(",compress"); + printk("\n"); + } + for (i = 0; i < 2; i++) { + unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr); + printk(KERN_DEBUG PPIP32 " dcr(%s)=0x%02x", + i ? "soft" : "hard", dcr); + printk(" %s", (dcr & DCR_DIR) ? "rev" : "fwd"); + if (dcr & DCR_IRQ) + printk(",ackIntEn"); + if (!(dcr & DCR_SELECT)) + printk(",nSelectIn"); + if (dcr & DCR_nINIT) + printk(",nInit"); + if (!(dcr & DCR_AUTOFD)) + printk(",nAutoFD"); + if (!(dcr & DCR_STROBE)) + printk(",nStrobe"); + printk("\n"); + } +#define sep (f++ ? ',' : ' ') + { + unsigned int f = 0; + unsigned int dsr = readb(priv->regs.dsr); + printk(KERN_DEBUG PPIP32 " dsr=0x%02x", dsr); + if (!(dsr & DSR_nBUSY)) + printk("%cBusy", sep); + if (dsr & DSR_nACK) + printk("%cnAck", sep); + if (dsr & DSR_PERROR) + printk("%cPError", sep); + if (dsr & DSR_SELECT) + printk("%cSelect", sep); + if (dsr & DSR_nFAULT) + printk("%cnFault", sep); + if (!(dsr & DSR_nPRINT)) + printk("%c(Print)", sep); + if (dsr & DSR_TIMEOUT) + printk("%cTimeout", sep); + printk("\n"); + } +#undef sep +} +#else /* DEBUG_PARPORT_IP32 < 2 */ +#define parport_ip32_dump_state(...) do { } while (0) +#endif + +/* + * CHECK_EXTRA_BITS - track and log extra bits + * @p: pointer to &struct parport + * @b: byte to inspect + * @m: bit mask of authorized bits + * + * This is used to track and log extra bits that should not be there in + * parport_ip32_write_control() and parport_ip32_frob_control(). It is only + * defined if %DEBUG_PARPORT_IP32 >= 1. + */ +#if DEBUG_PARPORT_IP32 >= 1 +#define CHECK_EXTRA_BITS(p, b, m) \ + do { \ + unsigned int __b = (b), __m = (m); \ + if (__b & ~__m) \ + pr_debug1(PPIP32 "%s: extra bits in %s(%s): " \ + "0x%02x/0x%02x\n", \ + (p)->name, __func__, #b, __b, __m); \ + } while (0) +#else /* DEBUG_PARPORT_IP32 < 1 */ +#define CHECK_EXTRA_BITS(...) do { } while (0) +#endif + +/*--- IP32 parallel port DMA operations --------------------------------*/ + +/** + * struct parport_ip32_dma_data - private data needed for DMA operation + * @dir: DMA direction (from or to device) + * @buf: buffer physical address + * @len: buffer length + * @next: address of next bytes to DMA transfer + * @left: number of bytes remaining + * @ctx: next context to write (0: context_a; 1: context_b) + * @irq_on: are the DMA IRQs currently enabled? + * @lock: spinlock to protect access to the structure + */ +struct parport_ip32_dma_data { + enum dma_data_direction dir; + dma_addr_t buf; + dma_addr_t next; + size_t len; + size_t left; + unsigned int ctx; + unsigned int irq_on; + spinlock_t lock; +}; +static struct parport_ip32_dma_data parport_ip32_dma; + +/** + * parport_ip32_dma_setup_context - setup next DMA context + * @limit: maximum data size for the context + * + * The alignment constraints must be verified in caller function, and the + * parameter @limit must be set accordingly. + */ +static void parport_ip32_dma_setup_context(unsigned int limit) +{ + unsigned long flags; + + spin_lock_irqsave(&parport_ip32_dma.lock, flags); + if (parport_ip32_dma.left > 0) { + /* Note: ctxreg is "volatile" here only because + * mace->perif.ctrl.parport.context_a and context_b are + * "volatile". */ + volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ? + &mace->perif.ctrl.parport.context_a : + &mace->perif.ctrl.parport.context_b; + u64 count; + u64 ctxval; + if (parport_ip32_dma.left <= limit) { + count = parport_ip32_dma.left; + ctxval = MACEPAR_CONTEXT_LASTFLAG; + } else { + count = limit; + ctxval = 0; + } + + pr_trace(NULL, + "(%u): 0x%04x:0x%04x, %u -> %u%s", + limit, + (unsigned int)parport_ip32_dma.buf, + (unsigned int)parport_ip32_dma.next, + (unsigned int)count, + parport_ip32_dma.ctx, ctxval ? "*" : ""); + + ctxval |= parport_ip32_dma.next & + MACEPAR_CONTEXT_BASEADDR_MASK; + ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) & + MACEPAR_CONTEXT_DATALEN_MASK; + writeq(ctxval, ctxreg); + parport_ip32_dma.next += count; + parport_ip32_dma.left -= count; + parport_ip32_dma.ctx ^= 1U; + } + /* If there is nothing more to send, disable IRQs to avoid to + * face an IRQ storm which can lock the machine. Disable them + * only once. */ + if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) { + pr_debug(PPIP32 "IRQ off (ctx)\n"); + disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); + disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); + parport_ip32_dma.irq_on = 0; + } + spin_unlock_irqrestore(&parport_ip32_dma.lock, flags); +} + +/** + * parport_ip32_dma_interrupt - DMA interrupt handler + * @irq: interrupt number + * @dev_id: unused + * @regs: pointer to &struct pt_regs + */ +static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + if (parport_ip32_dma.left) + pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx); + parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); + return IRQ_HANDLED; +} + +#if DEBUG_PARPORT_IP32 +static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + pr_trace1(NULL, "(%d)", irq); + return IRQ_HANDLED; +} +#endif + +/** + * parport_ip32_dma_start - begins a DMA transfer + * @dir: DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE + * @addr: pointer to data buffer + * @count: buffer size + * + * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be + * correctly balanced. + */ +static int parport_ip32_dma_start(enum dma_data_direction dir, + void *addr, size_t count) +{ + unsigned int limit; + u64 ctrl; + + pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count); + + /* FIXME - add support for DMA_FROM_DEVICE. In this case, buffer must + * be 64 bytes aligned. */ + BUG_ON(dir != DMA_TO_DEVICE); + + /* Reset DMA controller */ + ctrl = MACEPAR_CTLSTAT_RESET; + writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); + + /* DMA IRQs should normally be enabled */ + if (!parport_ip32_dma.irq_on) { + WARN_ON(1); + enable_irq(MACEISA_PAR_CTXA_IRQ); + enable_irq(MACEISA_PAR_CTXB_IRQ); + parport_ip32_dma.irq_on = 1; + } + + /* Prepare DMA pointers */ + parport_ip32_dma.dir = dir; + parport_ip32_dma.buf = dma_map_single(NULL, addr, count, dir); + parport_ip32_dma.len = count; + parport_ip32_dma.next = parport_ip32_dma.buf; + parport_ip32_dma.left = parport_ip32_dma.len; + parport_ip32_dma.ctx = 0; + + /* Setup DMA direction and first two contexts */ + ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION; + writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); + /* Single transfer should not cross a 4K page boundary */ + limit = MACEPAR_CONTEXT_DATA_BOUND - + (parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1)); + parport_ip32_dma_setup_context(limit); + parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); + + /* Real start of DMA transfer */ + ctrl |= MACEPAR_CTLSTAT_ENABLE; + writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); + + return 0; +} + +/** + * parport_ip32_dma_stop - ends a running DMA transfer + * + * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be + * correctly balanced. + */ +static void parport_ip32_dma_stop(void) +{ + u64 ctx_a; + u64 ctx_b; + u64 ctrl; + u64 diag; + size_t res[2]; /* {[0] = res_a, [1] = res_b} */ + + pr_trace(NULL, "()"); + + /* Disable IRQs */ + spin_lock_irq(&parport_ip32_dma.lock); + if (parport_ip32_dma.irq_on) { + pr_debug(PPIP32 "IRQ off (stop)\n"); + disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); + disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); + parport_ip32_dma.irq_on = 0; + } + spin_unlock_irq(&parport_ip32_dma.lock); + /* Force IRQ synchronization, even if the IRQs were disabled + * elsewhere. */ + synchronize_irq(MACEISA_PAR_CTXA_IRQ); + synchronize_irq(MACEISA_PAR_CTXB_IRQ); + + /* Stop DMA transfer */ + ctrl = readq(&mace->perif.ctrl.parport.cntlstat); + ctrl &= ~MACEPAR_CTLSTAT_ENABLE; + writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); + + /* Adjust residue (parport_ip32_dma.left) */ + ctx_a = readq(&mace->perif.ctrl.parport.context_a); + ctx_b = readq(&mace->perif.ctrl.parport.context_b); + ctrl = readq(&mace->perif.ctrl.parport.cntlstat); + diag = readq(&mace->perif.ctrl.parport.diagnostic); + res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ? + 1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >> + MACEPAR_CONTEXT_DATALEN_SHIFT) : + 0; + res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ? + 1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >> + MACEPAR_CONTEXT_DATALEN_SHIFT) : + 0; + if (diag & MACEPAR_DIAG_DMACTIVE) + res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] = + 1 + ((diag & MACEPAR_DIAG_CTRMASK) >> + MACEPAR_DIAG_CTRSHIFT); + parport_ip32_dma.left += res[0] + res[1]; + + /* Reset DMA controller, and re-enable IRQs */ + ctrl = MACEPAR_CTLSTAT_RESET; + writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); + pr_debug(PPIP32 "IRQ on (stop)\n"); + enable_irq(MACEISA_PAR_CTXA_IRQ); + enable_irq(MACEISA_PAR_CTXB_IRQ); + parport_ip32_dma.irq_on = 1; + + dma_unmap_single(NULL, parport_ip32_dma.buf, parport_ip32_dma.len, + parport_ip32_dma.dir); +} + +/** + * parport_ip32_dma_get_residue - get residue from last DMA transfer + * + * Returns the number of bytes remaining from last DMA transfer. + */ +static inline size_t parport_ip32_dma_get_residue(void) +{ + return parport_ip32_dma.left; +} + +/** + * parport_ip32_dma_register - initialize DMA engine + * + * Returns zero for success. + */ +static int parport_ip32_dma_register(void) +{ + int err; + + spin_lock_init(&parport_ip32_dma.lock); + parport_ip32_dma.irq_on = 1; + + /* Reset DMA controller */ + writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat); + + /* Request IRQs */ + err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt, + 0, "parport_ip32", NULL); + if (err) + goto fail_a; + err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt, + 0, "parport_ip32", NULL); + if (err) + goto fail_b; +#if DEBUG_PARPORT_IP32 + /* FIXME - what is this IRQ for? */ + err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt, + 0, "parport_ip32", NULL); + if (err) + goto fail_merr; +#endif + return 0; + +#if DEBUG_PARPORT_IP32 +fail_merr: + free_irq(MACEISA_PAR_CTXB_IRQ, NULL); +#endif +fail_b: + free_irq(MACEISA_PAR_CTXA_IRQ, NULL); +fail_a: + return err; +} + +/** + * parport_ip32_dma_unregister - release and free resources for DMA engine + */ +static void parport_ip32_dma_unregister(void) +{ +#if DEBUG_PARPORT_IP32 + free_irq(MACEISA_PAR_MERR_IRQ, NULL); +#endif + free_irq(MACEISA_PAR_CTXB_IRQ, NULL); + free_irq(MACEISA_PAR_CTXA_IRQ, NULL); +} + +/*--- Interrupt handlers and associates --------------------------------*/ + +/** + * parport_ip32_wakeup - wakes up code waiting for an interrupt + * @p: pointer to &struct parport + */ +static inline void parport_ip32_wakeup(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + complete(&priv->irq_complete); +} + +/** + * parport_ip32_interrupt - interrupt handler + * @irq: interrupt number + * @dev_id: pointer to &struct parport + * @regs: pointer to &struct pt_regs + * + * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is + * %PARPORT_IP32_IRQ_FWD. + */ +static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct parport * const p = dev_id; + struct parport_ip32_private * const priv = p->physport->private_data; + enum parport_ip32_irq_mode irq_mode = priv->irq_mode; + switch (irq_mode) { + case PARPORT_IP32_IRQ_FWD: + parport_generic_irq(irq, p, regs); + break; + case PARPORT_IP32_IRQ_HERE: + parport_ip32_wakeup(p); + break; + } + return IRQ_HANDLED; +} + +/*--- Some utility function to manipulate ECR register -----------------*/ + +/** + * parport_ip32_read_econtrol - read contents of the ECR register + * @p: pointer to &struct parport + */ +static inline unsigned int parport_ip32_read_econtrol(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return readb(priv->regs.ecr); +} + +/** + * parport_ip32_write_econtrol - write new contents to the ECR register + * @p: pointer to &struct parport + * @c: new value to write + */ +static inline void parport_ip32_write_econtrol(struct parport *p, + unsigned int c) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + writeb(c, priv->regs.ecr); +} + +/** + * parport_ip32_frob_econtrol - change bits from the ECR register + * @p: pointer to &struct parport + * @mask: bit mask of bits to change + * @val: new value for changed bits + * + * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits + * in @val, and write the result to the ECR. + */ +static inline void parport_ip32_frob_econtrol(struct parport *p, + unsigned int mask, + unsigned int val) +{ + unsigned int c; + c = (parport_ip32_read_econtrol(p) & ~mask) ^ val; + parport_ip32_write_econtrol(p, c); +} + +/** + * parport_ip32_set_mode - change mode of ECP port + * @p: pointer to &struct parport + * @mode: new mode to write in ECR + * + * ECR is reset in a sane state (interrupts and DMA disabled), and placed in + * mode @mode. Go through PS2 mode if needed. + */ +static void parport_ip32_set_mode(struct parport *p, unsigned int mode) +{ + unsigned int omode; + + mode &= ECR_MODE_MASK; + omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK; + + if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2 + || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) { + /* We have to go through PS2 mode */ + unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; + parport_ip32_write_econtrol(p, ecr); + } + parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR); +} + +/*--- Basic functions needed for parport -------------------------------*/ + +/** + * parport_ip32_read_data - return current contents of the DATA register + * @p: pointer to &struct parport + */ +static inline unsigned char parport_ip32_read_data(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return readb(priv->regs.data); +} + +/** + * parport_ip32_write_data - set new contents for the DATA register + * @p: pointer to &struct parport + * @d: new value to write + */ +static inline void parport_ip32_write_data(struct parport *p, unsigned char d) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + writeb(d, priv->regs.data); +} + +/** + * parport_ip32_read_status - return current contents of the DSR register + * @p: pointer to &struct parport + */ +static inline unsigned char parport_ip32_read_status(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return readb(priv->regs.dsr); +} + +/** + * __parport_ip32_read_control - return cached contents of the DCR register + * @p: pointer to &struct parport + */ +static inline unsigned int __parport_ip32_read_control(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return priv->dcr_cache; /* use soft copy */ +} + +/** + * __parport_ip32_write_control - set new contents for the DCR register + * @p: pointer to &struct parport + * @c: new value to write + */ +static inline void __parport_ip32_write_control(struct parport *p, + unsigned int c) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + CHECK_EXTRA_BITS(p, c, priv->dcr_writable); + c &= priv->dcr_writable; /* only writable bits */ + writeb(c, priv->regs.dcr); + priv->dcr_cache = c; /* update soft copy */ +} + +/** + * __parport_ip32_frob_control - change bits from the DCR register + * @p: pointer to &struct parport + * @mask: bit mask of bits to change + * @val: new value for changed bits + * + * This is equivalent to read from the DCR, mask out the bits in @mask, + * exclusive-or with the bits in @val, and write the result to the DCR. + * Actually, the cached contents of the DCR is used. + */ +static inline void __parport_ip32_frob_control(struct parport *p, + unsigned int mask, + unsigned int val) +{ + unsigned int c; + c = (__parport_ip32_read_control(p) & ~mask) ^ val; + __parport_ip32_write_control(p, c); +} + +/** + * parport_ip32_read_control - return cached contents of the DCR register + * @p: pointer to &struct parport + * + * The return value is masked so as to only return the value of %DCR_STROBE, + * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. + */ +static inline unsigned char parport_ip32_read_control(struct parport *p) +{ + const unsigned int rm = + DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; + return __parport_ip32_read_control(p) & rm; +} + +/** + * parport_ip32_write_control - set new contents for the DCR register + * @p: pointer to &struct parport + * @c: new value to write + * + * The value is masked so as to only change the value of %DCR_STROBE, + * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. + */ +static inline void parport_ip32_write_control(struct parport *p, + unsigned char c) +{ + const unsigned int wm = + DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; + CHECK_EXTRA_BITS(p, c, wm); + __parport_ip32_frob_control(p, wm, c & wm); +} + +/** + * parport_ip32_frob_control - change bits from the DCR register + * @p: pointer to &struct parport + * @mask: bit mask of bits to change + * @val: new value for changed bits + * + * This differs from __parport_ip32_frob_control() in that it only allows to + * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. + */ +static inline unsigned char parport_ip32_frob_control(struct parport *p, + unsigned char mask, + unsigned char val) +{ + const unsigned int wm = + DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; + CHECK_EXTRA_BITS(p, mask, wm); + CHECK_EXTRA_BITS(p, val, wm); + __parport_ip32_frob_control(p, mask & wm, val & wm); + return parport_ip32_read_control(p); +} + +/** + * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK + * @p: pointer to &struct parport + */ +static inline void parport_ip32_disable_irq(struct parport *p) +{ + __parport_ip32_frob_control(p, DCR_IRQ, 0); +} + +/** + * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK + * @p: pointer to &struct parport + */ +static inline void parport_ip32_enable_irq(struct parport *p) +{ + __parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ); +} + +/** + * parport_ip32_data_forward - enable host-to-peripheral communications + * @p: pointer to &struct parport + * + * Enable the data line drivers, for 8-bit host-to-peripheral communications. + */ +static inline void parport_ip32_data_forward(struct parport *p) +{ + __parport_ip32_frob_control(p, DCR_DIR, 0); +} + +/** + * parport_ip32_data_reverse - enable peripheral-to-host communications + * @p: pointer to &struct parport + * + * Place the data bus in a high impedance state, if @p->modes has the + * PARPORT_MODE_TRISTATE bit set. + */ +static inline void parport_ip32_data_reverse(struct parport *p) +{ + __parport_ip32_frob_control(p, DCR_DIR, DCR_DIR); +} + +/** + * parport_ip32_init_state - for core parport code + * @dev: pointer to &struct pardevice + * @s: pointer to &struct parport_state to initialize + */ +static void parport_ip32_init_state(struct pardevice *dev, + struct parport_state *s) +{ + s->u.ip32.dcr = DCR_SELECT | DCR_nINIT; + s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; +} + +/** + * parport_ip32_save_state - for core parport code + * @p: pointer to &struct parport + * @s: pointer to &struct parport_state to save state to + */ +static void parport_ip32_save_state(struct parport *p, + struct parport_state *s) +{ + s->u.ip32.dcr = __parport_ip32_read_control(p); + s->u.ip32.ecr = parport_ip32_read_econtrol(p); +} + +/** + * parport_ip32_restore_state - for core parport code + * @p: pointer to &struct parport + * @s: pointer to &struct parport_state to restore state from + */ +static void parport_ip32_restore_state(struct parport *p, + struct parport_state *s) +{ + parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK); + parport_ip32_write_econtrol(p, s->u.ip32.ecr); + __parport_ip32_write_control(p, s->u.ip32.dcr); +} + +/*--- EPP mode functions -----------------------------------------------*/ + +/** + * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode + * @p: pointer to &struct parport + * + * Returns 1 if the Timeout bit is clear, and 0 otherwise. + */ +static unsigned int parport_ip32_clear_epp_timeout(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + unsigned int cleared; + + if (!(parport_ip32_read_status(p) & DSR_TIMEOUT)) + cleared = 1; + else { + unsigned int r; + /* To clear timeout some chips require double read */ + parport_ip32_read_status(p); + r = parport_ip32_read_status(p); + /* Some reset by writing 1 */ + writeb(r | DSR_TIMEOUT, priv->regs.dsr); + /* Others by writing 0 */ + writeb(r & ~DSR_TIMEOUT, priv->regs.dsr); + + r = parport_ip32_read_status(p); + cleared = !(r & DSR_TIMEOUT); + } + + pr_trace(p, "(): %s", cleared ? "cleared" : "failed"); + return cleared; +} + +/** + * parport_ip32_epp_read - generic EPP read function + * @eppreg: I/O register to read from + * @p: pointer to &struct parport + * @buf: buffer to store read data + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_read(void __iomem *eppreg, + struct parport *p, void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + size_t got; + parport_ip32_set_mode(p, ECR_MODE_EPP); + parport_ip32_data_reverse(p); + parport_ip32_write_control(p, DCR_nINIT); + if ((flags & PARPORT_EPP_FAST) && (len > 1)) { + readsb(eppreg, buf, len); + if (readb(priv->regs.dsr) & DSR_TIMEOUT) { + parport_ip32_clear_epp_timeout(p); + return -EIO; + } + got = len; + } else { + u8 *bufp = buf; + for (got = 0; got < len; got++) { + *bufp++ = readb(eppreg); + if (readb(priv->regs.dsr) & DSR_TIMEOUT) { + parport_ip32_clear_epp_timeout(p); + break; + } + } + } + parport_ip32_data_forward(p); + parport_ip32_set_mode(p, ECR_MODE_PS2); + return got; +} + +/** + * parport_ip32_epp_write - generic EPP write function + * @eppreg: I/O register to write to + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_write(void __iomem *eppreg, + struct parport *p, const void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + size_t written; + parport_ip32_set_mode(p, ECR_MODE_EPP); + parport_ip32_data_forward(p); + parport_ip32_write_control(p, DCR_nINIT); + if ((flags & PARPORT_EPP_FAST) && (len > 1)) { + writesb(eppreg, buf, len); + if (readb(priv->regs.dsr) & DSR_TIMEOUT) { + parport_ip32_clear_epp_timeout(p); + return -EIO; + } + written = len; + } else { + const u8 *bufp = buf; + for (written = 0; written < len; written++) { + writeb(*bufp++, eppreg); + if (readb(priv->regs.dsr) & DSR_TIMEOUT) { + parport_ip32_clear_epp_timeout(p); + break; + } + } + } + parport_ip32_set_mode(p, ECR_MODE_PS2); + return written; +} + +/** + * parport_ip32_epp_read_data - read a block of data in EPP mode + * @p: pointer to &struct parport + * @buf: buffer to store read data + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_read_data(struct parport *p, void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags); +} + +/** + * parport_ip32_epp_write_data - write a block of data in EPP mode + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags); +} + +/** + * parport_ip32_epp_read_addr - read a block of addresses in EPP mode + * @p: pointer to &struct parport + * @buf: buffer to store read data + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags); +} + +/** + * parport_ip32_epp_write_addr - write a block of addresses in EPP mode + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * @flags: may be PARPORT_EPP_FAST + */ +static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf, + size_t len, int flags) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags); +} + +/*--- ECP mode functions (FIFO) ----------------------------------------*/ + +/** + * parport_ip32_fifo_wait_break - check if the waiting function should return + * @p: pointer to &struct parport + * @expire: timeout expiring date, in jiffies + * + * parport_ip32_fifo_wait_break() checks if the waiting function should return + * immediately or not. The break conditions are: + * - expired timeout; + * - a pending signal; + * - nFault asserted low. + * This function also calls cond_resched(). + */ +static unsigned int parport_ip32_fifo_wait_break(struct parport *p, + unsigned long expire) +{ + cond_resched(); + if (time_after(jiffies, expire)) { + pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name); + return 1; + } + if (signal_pending(current)) { + pr_debug1(PPIP32 "%s: Signal pending\n", p->name); + return 1; + } + if (!(parport_ip32_read_status(p) & DSR_nFAULT)) { + pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name); + return 1; + } + return 0; +} + +/** + * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling) + * @p: pointer to &struct parport + * + * Returns the number of bytes that can safely be written in the FIFO. A + * return value of zero means that the calling function should terminate as + * fast as possible. + */ +static unsigned int parport_ip32_fwp_wait_polling(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport * const physport = p->physport; + unsigned long expire; + unsigned int count; + unsigned int ecr; + + expire = jiffies + physport->cad->timeout; + count = 0; + while (1) { + if (parport_ip32_fifo_wait_break(p, expire)) + break; + + /* Check FIFO state. We do nothing when the FIFO is nor full, + * nor empty. It appears that the FIFO full bit is not always + * reliable, the FIFO state is sometimes wrongly reported, and + * the chip gets confused if we give it another byte. */ + ecr = parport_ip32_read_econtrol(p); + if (ecr & ECR_F_EMPTY) { + /* FIFO is empty, fill it up */ + count = priv->fifo_depth; + break; + } + + /* Wait a moment... */ + udelay(FIFO_POLLING_INTERVAL); + } /* while (1) */ + + return count; +} + +/** + * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven) + * @p: pointer to &struct parport + * + * Returns the number of bytes that can safely be written in the FIFO. A + * return value of zero means that the calling function should terminate as + * fast as possible. + */ +static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p) +{ + static unsigned int lost_interrupt = 0; + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport * const physport = p->physport; + unsigned long nfault_timeout; + unsigned long expire; + unsigned int count; + unsigned int ecr; + + nfault_timeout = min((unsigned long)physport->cad->timeout, + msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); + expire = jiffies + physport->cad->timeout; + count = 0; + while (1) { + if (parport_ip32_fifo_wait_break(p, expire)) + break; + + /* Initialize mutex used to take interrupts into account */ + INIT_COMPLETION(priv->irq_complete); + + /* Enable serviceIntr */ + parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); + + /* Enabling serviceIntr while the FIFO is empty does not + * always generate an interrupt, so check for emptiness + * now. */ + ecr = parport_ip32_read_econtrol(p); + if (!(ecr & ECR_F_EMPTY)) { + /* FIFO is not empty: wait for an interrupt or a + * timeout to occur */ + wait_for_completion_interruptible_timeout( + &priv->irq_complete, nfault_timeout); + ecr = parport_ip32_read_econtrol(p); + if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR) + && !lost_interrupt) { + printk(KERN_WARNING PPIP32 + "%s: lost interrupt in %s\n", + p->name, __func__); + lost_interrupt = 1; + } + } + + /* Disable serviceIntr */ + parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR); + + /* Check FIFO state */ + if (ecr & ECR_F_EMPTY) { + /* FIFO is empty, fill it up */ + count = priv->fifo_depth; + break; + } else if (ecr & ECR_SERVINTR) { + /* FIFO is not empty, but we know that can safely push + * writeIntrThreshold bytes into it */ + count = priv->writeIntrThreshold; + break; + } + /* FIFO is not empty, and we did not get any interrupt. + * Either it's time to check for nFault, or a signal is + * pending. This is verified in + * parport_ip32_fifo_wait_break(), so we continue the loop. */ + } /* while (1) */ + + return count; +} + +/** + * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode) + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * + * Uses PIO to write the contents of the buffer @buf into the parallel port + * FIFO. Returns the number of bytes that were actually written. It can work + * with or without the help of interrupts. The parallel port must be + * correctly initialized before calling parport_ip32_fifo_write_block_pio(). + */ +static size_t parport_ip32_fifo_write_block_pio(struct parport *p, + const void *buf, size_t len) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + const u8 *bufp = buf; + size_t left = len; + + priv->irq_mode = PARPORT_IP32_IRQ_HERE; + + while (left > 0) { + unsigned int count; + + count = (p->irq == PARPORT_IRQ_NONE) ? + parport_ip32_fwp_wait_polling(p) : + parport_ip32_fwp_wait_interrupt(p); + if (count == 0) + break; /* Transmission should be stopped */ + if (count > left) + count = left; + if (count == 1) { + writeb(*bufp, priv->regs.fifo); + bufp++, left--; + } else { + writesb(priv->regs.fifo, bufp, count); + bufp += count, left -= count; + } + } + + priv->irq_mode = PARPORT_IP32_IRQ_FWD; + + return len - left; +} + +/** + * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode) + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * + * Uses DMA to write the contents of the buffer @buf into the parallel port + * FIFO. Returns the number of bytes that were actually written. The + * parallel port must be correctly initialized before calling + * parport_ip32_fifo_write_block_dma(). + */ +static size_t parport_ip32_fifo_write_block_dma(struct parport *p, + const void *buf, size_t len) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport * const physport = p->physport; + unsigned long nfault_timeout; + unsigned long expire; + size_t written; + unsigned int ecr; + + priv->irq_mode = PARPORT_IP32_IRQ_HERE; + + parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len); + INIT_COMPLETION(priv->irq_complete); + parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN); + + nfault_timeout = min((unsigned long)physport->cad->timeout, + msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); + expire = jiffies + physport->cad->timeout; + while (1) { + if (parport_ip32_fifo_wait_break(p, expire)) + break; + wait_for_completion_interruptible_timeout(&priv->irq_complete, + nfault_timeout); + ecr = parport_ip32_read_econtrol(p); + if (ecr & ECR_SERVINTR) + break; /* DMA transfer just finished */ + } + parport_ip32_dma_stop(); + written = len - parport_ip32_dma_get_residue(); + + priv->irq_mode = PARPORT_IP32_IRQ_FWD; + + return written; +} + +/** + * parport_ip32_fifo_write_block - write a block of data + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * + * Uses PIO or DMA to write the contents of the buffer @buf into the parallel + * p FIFO. Returns the number of bytes that were actually written. + */ +static size_t parport_ip32_fifo_write_block(struct parport *p, + const void *buf, size_t len) +{ + size_t written = 0; + if (len) + /* FIXME - Maybe some threshold value should be set for @len + * under which we revert to PIO mode? */ + written = (p->modes & PARPORT_MODE_DMA) ? + parport_ip32_fifo_write_block_dma(p, buf, len) : + parport_ip32_fifo_write_block_pio(p, buf, len); + return written; +} + +/** + * parport_ip32_drain_fifo - wait for FIFO to empty + * @p: pointer to &struct parport + * @timeout: timeout, in jiffies + * + * This function waits for FIFO to empty. It returns 1 when FIFO is empty, or + * 0 if the timeout @timeout is reached before, or if a signal is pending. + */ +static unsigned int parport_ip32_drain_fifo(struct parport *p, + unsigned long timeout) +{ + unsigned long expire = jiffies + timeout; + unsigned int polling_interval; + unsigned int counter; + + /* Busy wait for approx. 200us */ + for (counter = 0; counter < 40; counter++) { + if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) + break; + if (time_after(jiffies, expire)) + break; + if (signal_pending(current)) + break; + udelay(5); + } + /* Poll slowly. Polling interval starts with 1 millisecond, and is + * increased exponentially until 128. */ + polling_interval = 1; /* msecs */ + while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) { + if (time_after_eq(jiffies, expire)) + break; + msleep_interruptible(polling_interval); + if (signal_pending(current)) + break; + if (polling_interval < 128) + polling_interval *= 2; + } + + return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY); +} + +/** + * parport_ip32_get_fifo_residue - reset FIFO + * @p: pointer to &struct parport + * @mode: current operation mode (ECR_MODE_PPF or ECR_MODE_ECP) + * + * This function resets FIFO, and returns the number of bytes remaining in it. + */ +static unsigned int parport_ip32_get_fifo_residue(struct parport *p, + unsigned int mode) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + unsigned int residue; + unsigned int cnfga; + + /* FIXME - We are missing one byte if the printer is off-line. I + * don't know how to detect this. It looks that the full bit is not + * always reliable. For the moment, the problem is avoided in most + * cases by testing for BUSY in parport_ip32_compat_write_data(). + */ + if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) + residue = 0; + else { + pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name); + + /* Stop all transfers. + * + * Microsoft's document instructs to drive DCR_STROBE to 0, + * but it doesn't work (at least in Compatibility mode, not + * tested in ECP mode). Switching directly to Test mode (as + * in parport_pc) is not an option: it does confuse the port, + * ECP service interrupts are no more working after that. A + * hard reset is then needed to revert to a sane state. + * + * Let's hope that the FIFO is really stuck and that the + * peripheral doesn't wake up now. + */ + parport_ip32_frob_control(p, DCR_STROBE, 0); + + /* Fill up FIFO */ + for (residue = priv->fifo_depth; residue > 0; residue--) { + if (parport_ip32_read_econtrol(p) & ECR_F_FULL) + break; + writeb(0x00, priv->regs.fifo); + } + } + if (residue) + pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n", + p->name, residue, + (residue == 1) ? " was" : "s were"); + + /* Now reset the FIFO */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + + /* Host recovery for ECP mode */ + if (mode == ECR_MODE_ECP) { + parport_ip32_data_reverse(p); + parport_ip32_frob_control(p, DCR_nINIT, 0); + if (parport_wait_peripheral(p, DSR_PERROR, 0)) + pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n", + p->name, __func__); + parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE); + parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT); + if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) + pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n", + p->name, __func__); + } + + /* Adjust residue if needed */ + parport_ip32_set_mode(p, ECR_MODE_CFG); + cnfga = readb(priv->regs.cnfgA); + if (!(cnfga & CNFGA_nBYTEINTRANS)) { + pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n", + p->name, cnfga); + pr_debug1(PPIP32 "%s: Accounting for extra byte\n", + p->name); + residue++; + } + + /* Don't care about partial PWords since we do not support + * PWord != 1 byte. */ + + /* Back to forward PS2 mode. */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + parport_ip32_data_forward(p); + + return residue; +} + +/** + * parport_ip32_compat_write_data - write a block of data in SPP mode + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * @flags: ignored + */ +static size_t parport_ip32_compat_write_data(struct parport *p, + const void *buf, size_t len, + int flags) +{ + static unsigned int ready_before = 1; + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport * const physport = p->physport; + size_t written = 0; + + /* Special case: a timeout of zero means we cannot call schedule(). + * Also if O_NONBLOCK is set then use the default implementation. */ + if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) + return parport_ieee1284_write_compat(p, buf, len, flags); + + /* Reset FIFO, go in forward mode, and disable ackIntEn */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); + parport_ip32_data_forward(p); + parport_ip32_disable_irq(p); + parport_ip32_set_mode(p, ECR_MODE_PPF); + physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; + + /* Wait for peripheral to become ready */ + if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, + DSR_nBUSY | DSR_nFAULT)) { + /* Avoid to flood the logs */ + if (ready_before) + printk(KERN_INFO PPIP32 "%s: not ready in %s\n", + p->name, __func__); + ready_before = 0; + goto stop; + } + ready_before = 1; + + written = parport_ip32_fifo_write_block(p, buf, len); + + /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ + parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); + + /* Check for a potential residue */ + written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF); + + /* Then, wait for BUSY to get low. */ + if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) + printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", + p->name, __func__); + +stop: + /* Reset FIFO */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; + + return written; +} + +/* + * FIXME - Insert here parport_ip32_ecp_read_data(). + */ + +/** + * parport_ip32_ecp_write_data - write a block of data in ECP mode + * @p: pointer to &struct parport + * @buf: buffer of data to write + * @len: length of buffer @buf + * @flags: ignored + */ +static size_t parport_ip32_ecp_write_data(struct parport *p, + const void *buf, size_t len, + int flags) +{ + static unsigned int ready_before = 1; + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport * const physport = p->physport; + size_t written = 0; + + /* Special case: a timeout of zero means we cannot call schedule(). + * Also if O_NONBLOCK is set then use the default implementation. */ + if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) + return parport_ieee1284_ecp_write_data(p, buf, len, flags); + + /* Negotiate to forward mode if necessary. */ + if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { + /* Event 47: Set nInit high. */ + parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD, + DCR_nINIT | DCR_AUTOFD); + + /* Event 49: PError goes high. */ + if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) { + printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s", + p->name, __func__); + physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN; + return 0; + } + } + + /* Reset FIFO, go in forward mode, and disable ackIntEn */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); + parport_ip32_data_forward(p); + parport_ip32_disable_irq(p); + parport_ip32_set_mode(p, ECR_MODE_ECP); + physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; + + /* Wait for peripheral to become ready */ + if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, + DSR_nBUSY | DSR_nFAULT)) { + /* Avoid to flood the logs */ + if (ready_before) + printk(KERN_INFO PPIP32 "%s: not ready in %s\n", + p->name, __func__); + ready_before = 0; + goto stop; + } + ready_before = 1; + + written = parport_ip32_fifo_write_block(p, buf, len); + + /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ + parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); + + /* Check for a potential residue */ + written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP); + + /* Then, wait for BUSY to get low. */ + if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) + printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", + p->name, __func__); + +stop: + /* Reset FIFO */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; + + return written; +} + +/* + * FIXME - Insert here parport_ip32_ecp_write_addr(). + */ + +/*--- Default parport operations ---------------------------------------*/ + +static __initdata struct parport_operations parport_ip32_ops = { + .write_data = parport_ip32_write_data, + .read_data = parport_ip32_read_data, + + .write_control = parport_ip32_write_control, + .read_control = parport_ip32_read_control, + .frob_control = parport_ip32_frob_control, + + .read_status = parport_ip32_read_status, + + .enable_irq = parport_ip32_enable_irq, + .disable_irq = parport_ip32_disable_irq, + + .data_forward = parport_ip32_data_forward, + .data_reverse = parport_ip32_data_reverse, + + .init_state = parport_ip32_init_state, + .save_state = parport_ip32_save_state, + .restore_state = parport_ip32_restore_state, + + .epp_write_data = parport_ieee1284_epp_write_data, + .epp_read_data = parport_ieee1284_epp_read_data, + .epp_write_addr = parport_ieee1284_epp_write_addr, + .epp_read_addr = parport_ieee1284_epp_read_addr, + + .ecp_write_data = parport_ieee1284_ecp_write_data, + .ecp_read_data = parport_ieee1284_ecp_read_data, + .ecp_write_addr = parport_ieee1284_ecp_write_addr, + + .compat_write_data = parport_ieee1284_write_compat, + .nibble_read_data = parport_ieee1284_read_nibble, + .byte_read_data = parport_ieee1284_read_byte, + + .owner = THIS_MODULE, +}; + +/*--- Device detection -------------------------------------------------*/ + +/** + * parport_ip32_ecp_supported - check for an ECP port + * @p: pointer to the &parport structure + * + * Returns 1 if an ECP port is found, and 0 otherwise. This function actually + * checks if an Extended Control Register seems to be present. On successful + * return, the port is placed in SPP mode. + */ +static __init unsigned int parport_ip32_ecp_supported(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + unsigned int ecr; + + ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; + writeb(ecr, priv->regs.ecr); + if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY)) + goto fail; + + pr_probe(p, "Found working ECR register\n"); + parport_ip32_set_mode(p, ECR_MODE_SPP); + parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); + return 1; + +fail: + pr_probe(p, "ECR register not found\n"); + return 0; +} + +/** + * parport_ip32_fifo_supported - check for FIFO parameters + * @p: pointer to the &parport structure + * + * Check for FIFO parameters of an Extended Capabilities Port. Returns 1 on + * success, and 0 otherwise. Adjust FIFO parameters in the parport structure. + * On return, the port is placed in SPP mode. + */ +static __init unsigned int parport_ip32_fifo_supported(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + unsigned int configa, configb; + unsigned int pword; + unsigned int i; + + /* Configuration mode */ + parport_ip32_set_mode(p, ECR_MODE_CFG); + configa = readb(priv->regs.cnfgA); + configb = readb(priv->regs.cnfgB); + + /* Find out PWord size */ + switch (configa & CNFGA_ID_MASK) { + case CNFGA_ID_8: + pword = 1; + break; + case CNFGA_ID_16: + pword = 2; + break; + case CNFGA_ID_32: + pword = 4; + break; + default: + pr_probe(p, "Unknown implementation ID: 0x%0x\n", + (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT); + goto fail; + break; + } + if (pword != 1) { + pr_probe(p, "Unsupported PWord size: %u\n", pword); + goto fail; + } + priv->pword = pword; + pr_probe(p, "PWord is %u bits\n", 8 * priv->pword); + + /* Check for compression support */ + writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB); + if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS) + pr_probe(p, "Hardware compression detected (unsupported)\n"); + writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB); + + /* Reset FIFO and go in test mode (no interrupt, no DMA) */ + parport_ip32_set_mode(p, ECR_MODE_TST); + + /* FIFO must be empty now */ + if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { + pr_probe(p, "FIFO not reset\n"); + goto fail; + } + + /* Find out FIFO depth. */ + priv->fifo_depth = 0; + for (i = 0; i < 1024; i++) { + if (readb(priv->regs.ecr) & ECR_F_FULL) { + /* FIFO full */ + priv->fifo_depth = i; + break; + } + writeb((u8)i, priv->regs.fifo); + } + if (i >= 1024) { + pr_probe(p, "Can't fill FIFO\n"); + goto fail; + } + if (!priv->fifo_depth) { + pr_probe(p, "Can't get FIFO depth\n"); + goto fail; + } + pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth); + + /* Enable interrupts */ + parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); + + /* Find out writeIntrThreshold: number of PWords we know we can write + * if we get an interrupt. */ + priv->writeIntrThreshold = 0; + for (i = 0; i < priv->fifo_depth; i++) { + if (readb(priv->regs.fifo) != (u8)i) { + pr_probe(p, "Invalid data in FIFO\n"); + goto fail; + } + if (!priv->writeIntrThreshold + && readb(priv->regs.ecr) & ECR_SERVINTR) + /* writeIntrThreshold reached */ + priv->writeIntrThreshold = i + 1; + if (i + 1 < priv->fifo_depth + && readb(priv->regs.ecr) & ECR_F_EMPTY) { + /* FIFO empty before the last byte? */ + pr_probe(p, "Data lost in FIFO\n"); + goto fail; + } + } + if (!priv->writeIntrThreshold) { + pr_probe(p, "Can't get writeIntrThreshold\n"); + goto fail; + } + pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold); + + /* FIFO must be empty now */ + if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { + pr_probe(p, "Can't empty FIFO\n"); + goto fail; + } + + /* Reset FIFO */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + /* Set reverse direction (must be in PS2 mode) */ + parport_ip32_data_reverse(p); + /* Test FIFO, no interrupt, no DMA */ + parport_ip32_set_mode(p, ECR_MODE_TST); + /* Enable interrupts */ + parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); + + /* Find out readIntrThreshold: number of PWords we can read if we get + * an interrupt. */ + priv->readIntrThreshold = 0; + for (i = 0; i < priv->fifo_depth; i++) { + writeb(0xaa, priv->regs.fifo); + if (readb(priv->regs.ecr) & ECR_SERVINTR) { + /* readIntrThreshold reached */ + priv->readIntrThreshold = i + 1; + break; + } + } + if (!priv->readIntrThreshold) { + pr_probe(p, "Can't get readIntrThreshold\n"); + goto fail; + } + pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold); + + /* Reset ECR */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + parport_ip32_data_forward(p); + parport_ip32_set_mode(p, ECR_MODE_SPP); + return 1; + +fail: + priv->fifo_depth = 0; + parport_ip32_set_mode(p, ECR_MODE_SPP); + return 0; +} + +/*--- Initialization code ----------------------------------------------*/ + +/** + * parport_ip32_make_isa_registers - compute (ISA) register addresses + * @regs: pointer to &struct parport_ip32_regs to fill + * @base: base address of standard and EPP registers + * @base_hi: base address of ECP registers + * @regshift: how much to shift register offset by + * + * Compute register addresses, according to the ISA standard. The addresses + * of the standard and EPP registers are computed from address @base. The + * addresses of the ECP registers are computed from address @base_hi. + */ +static void __init +parport_ip32_make_isa_registers(struct parport_ip32_regs *regs, + void __iomem *base, void __iomem *base_hi, + unsigned int regshift) +{ +#define r_base(offset) ((u8 __iomem *)base + ((offset) << regshift)) +#define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift)) + *regs = (struct parport_ip32_regs){ + .data = r_base(0), + .dsr = r_base(1), + .dcr = r_base(2), + .eppAddr = r_base(3), + .eppData0 = r_base(4), + .eppData1 = r_base(5), + .eppData2 = r_base(6), + .eppData3 = r_base(7), + .ecpAFifo = r_base(0), + .fifo = r_base_hi(0), + .cnfgA = r_base_hi(0), + .cnfgB = r_base_hi(1), + .ecr = r_base_hi(2) + }; +#undef r_base_hi +#undef r_base +} + +/** + * parport_ip32_probe_port - probe and register IP32 built-in parallel port + * + * Returns the new allocated &parport structure. On error, an error code is + * encoded in return value with the ERR_PTR function. + */ +static __init struct parport *parport_ip32_probe_port(void) +{ + struct parport_ip32_regs regs; + struct parport_ip32_private *priv = NULL; + struct parport_operations *ops = NULL; + struct parport *p = NULL; + int err; + + parport_ip32_make_isa_registers(®s, &mace->isa.parallel, + &mace->isa.ecp1284, 8 /* regshift */); + + ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); + priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL); + p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops); + if (ops == NULL || priv == NULL || p == NULL) { + err = -ENOMEM; + goto fail; + } + p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel); + p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284); + p->private_data = priv; + + *ops = parport_ip32_ops; + *priv = (struct parport_ip32_private){ + .regs = regs, + .dcr_writable = DCR_DIR | DCR_SELECT | DCR_nINIT | + DCR_AUTOFD | DCR_STROBE, + .irq_mode = PARPORT_IP32_IRQ_FWD, + }; + init_completion(&priv->irq_complete); + + /* Probe port. */ + if (!parport_ip32_ecp_supported(p)) { + err = -ENODEV; + goto fail; + } + parport_ip32_dump_state(p, "begin init", 0); + + /* We found what looks like a working ECR register. Simply assume + * that all modes are correctly supported. Enable basic modes. */ + p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; + p->modes |= PARPORT_MODE_TRISTATE; + + if (!parport_ip32_fifo_supported(p)) { + printk(KERN_WARNING PPIP32 + "%s: error: FIFO disabled\n", p->name); + /* Disable hardware modes depending on a working FIFO. */ + features &= ~PARPORT_IP32_ENABLE_SPP; + features &= ~PARPORT_IP32_ENABLE_ECP; + /* DMA is not needed if FIFO is not supported. */ + features &= ~PARPORT_IP32_ENABLE_DMA; + } + + /* Request IRQ */ + if (features & PARPORT_IP32_ENABLE_IRQ) { + int irq = MACEISA_PARALLEL_IRQ; + if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) { + printk(KERN_WARNING PPIP32 + "%s: error: IRQ disabled\n", p->name); + /* DMA cannot work without interrupts. */ + features &= ~PARPORT_IP32_ENABLE_DMA; + } else { + pr_probe(p, "Interrupt support enabled\n"); + p->irq = irq; + priv->dcr_writable |= DCR_IRQ; + } + } + + /* Allocate DMA resources */ + if (features & PARPORT_IP32_ENABLE_DMA) { + if (parport_ip32_dma_register()) + printk(KERN_WARNING PPIP32 + "%s: error: DMA disabled\n", p->name); + else { + pr_probe(p, "DMA support enabled\n"); + p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */ + p->modes |= PARPORT_MODE_DMA; + } + } + + if (features & PARPORT_IP32_ENABLE_SPP) { + /* Enable compatibility FIFO mode */ + p->ops->compat_write_data = parport_ip32_compat_write_data; + p->modes |= PARPORT_MODE_COMPAT; + pr_probe(p, "Hardware support for SPP mode enabled\n"); + } + if (features & PARPORT_IP32_ENABLE_EPP) { + /* Set up access functions to use EPP hardware. */ + p->ops->epp_read_data = parport_ip32_epp_read_data; + p->ops->epp_write_data = parport_ip32_epp_write_data; + p->ops->epp_read_addr = parport_ip32_epp_read_addr; + p->ops->epp_write_addr = parport_ip32_epp_write_addr; + p->modes |= PARPORT_MODE_EPP; + pr_probe(p, "Hardware support for EPP mode enabled\n"); + } + if (features & PARPORT_IP32_ENABLE_ECP) { + /* Enable ECP FIFO mode */ + p->ops->ecp_write_data = parport_ip32_ecp_write_data; + /* FIXME - not implemented */ +/* p->ops->ecp_read_data = parport_ip32_ecp_read_data; */ +/* p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */ + p->modes |= PARPORT_MODE_ECP; + pr_probe(p, "Hardware support for ECP mode enabled\n"); + } + + /* Initialize the port with sensible values */ + parport_ip32_set_mode(p, ECR_MODE_PS2); + parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); + parport_ip32_data_forward(p); + parport_ip32_disable_irq(p); + parport_ip32_write_data(p, 0x00); + parport_ip32_dump_state(p, "end init", 0); + + /* Print out what we found */ + printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)", + p->name, p->base, p->base_hi); + if (p->irq != PARPORT_IRQ_NONE) + printk(", irq %d", p->irq); + printk(" ["); +#define printmode(x) if (p->modes & PARPORT_MODE_##x) \ + printk("%s%s", f++ ? "," : "", #x) + { + unsigned int f = 0; + printmode(PCSPP); + printmode(TRISTATE); + printmode(COMPAT); + printmode(EPP); + printmode(ECP); + printmode(DMA); + } +#undef printmode + printk("]\n"); + + parport_announce_port(p); + return p; + +fail: + if (p) + parport_put_port(p); + kfree(priv); + kfree(ops); + return ERR_PTR(err); +} + +/** + * parport_ip32_unregister_port - unregister a parallel port + * @p: pointer to the &struct parport + * + * Unregisters a parallel port and free previously allocated resources + * (memory, IRQ, ...). + */ +static __exit void parport_ip32_unregister_port(struct parport *p) +{ + struct parport_ip32_private * const priv = p->physport->private_data; + struct parport_operations *ops = p->ops; + + parport_remove_port(p); + if (p->modes & PARPORT_MODE_DMA) + parport_ip32_dma_unregister(); + if (p->irq != PARPORT_IRQ_NONE) + free_irq(p->irq, p); + parport_put_port(p); + kfree(priv); + kfree(ops); +} + +/** + * parport_ip32_init - module initialization function + */ +static int __init parport_ip32_init(void) +{ + pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); + pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__); + this_port = parport_ip32_probe_port(); + return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; +} + +/** + * parport_ip32_exit - module termination function + */ +static void __exit parport_ip32_exit(void) +{ + parport_ip32_unregister_port(this_port); +} + +/*--- Module stuff -----------------------------------------------------*/ + +MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>"); +MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.6"); /* update in parport_ip32_init() too */ + +module_init(parport_ip32_init); +module_exit(parport_ip32_exit); + +module_param(verbose_probing, bool, S_IRUGO); +MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization"); + +module_param(features, uint, S_IRUGO); +MODULE_PARM_DESC(features, + "Bit mask of features to enable" + ", bit 0: IRQ support" + ", bit 1: DMA support" + ", bit 2: hardware SPP mode" + ", bit 3: hardware EPP mode" + ", bit 4: hardware ECP mode"); + +/*--- Inform (X)Emacs about preferred coding style ---------------------*/ +/* + * Local Variables: + * mode: c + * c-file-style: "linux" + * indent-tabs-mode: t + * tab-width: 8 + * fill-column: 78 + * ispell-local-dictionary: "american" + * End: + */ diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 76dd077e3184..166de3507780 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -329,9 +329,9 @@ static int __devinit parport_register (struct pci_dev *dev, if (priv->num_par == ARRAY_SIZE (priv->port)) { printk (KERN_WARNING - "parport_serial: %s: only %u parallel ports " + "parport_serial: %s: only %zu parallel ports " "supported (%d reported)\n", pci_name (dev), - ARRAY_SIZE (priv->port), card->numports); + ARRAY_SIZE(priv->port), card->numports); break; } diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index b62aee8de3cb..ea83b70e0de2 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c @@ -199,7 +199,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer, if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) { if (belen != len) { - printk (KERN_DEBUG "%s: Device ID was %d bytes" + printk (KERN_DEBUG "%s: Device ID was %zd bytes" " while device told it would be %d" " bytes\n", port->name, len, belen); @@ -214,7 +214,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer, if (buffer[len-1] == ';') { printk (KERN_DEBUG "%s: Device ID reading stopped" " before device told data not available. " - "Current idlen %d of %d, len bytes %02X %02X\n", + "Current idlen %u of %u, len bytes %02X %02X\n", port->name, current_idlen, numidlens, length[0], length[1]); goto done; diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 2f1289eebb3c..222a1cc4aa28 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -11,8 +11,7 @@ config HOTPLUG_PCI ---help--- Say Y here if you have a motherboard with a PCI Hotplug controller. This allows you to add and remove PCI cards while the machine is - powered up and running. The file system pcihpfs must be mounted - in order to interact with any PCI Hotplug controllers. + powered up and running. To compile this driver as a module, choose M here: the module will be called pci_hotplug. diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 7e7f913ba7b9..317457dd4014 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -302,7 +302,7 @@ static int ibm_get_table_from_acpi(char **bufp) } package = (union acpi_object *) buffer.pointer; - if(!(package) || + if (!(package) || (package->type != ACPI_TYPE_PACKAGE) || !(package->package.elements)) { err("%s: Invalid APCI object\n", __FUNCTION__); @@ -405,7 +405,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, } info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0'; - if(info.current_status && (info.valid & ACPI_VALID_HID) && + if (info.current_status && (info.valid & ACPI_VALID_HID) && (!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) || !strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) { dbg("found hardware: %s, handle: %p\n", info.hardware_id.value, @@ -449,13 +449,11 @@ static int __init ibm_acpiphp_init(void) } ibm_note.device = device; - status = acpi_install_notify_handler( - ibm_acpi_handle, - ACPI_DEVICE_NOTIFY, - ibm_handle_events, + status = acpi_install_notify_handler(ibm_acpi_handle, + ACPI_DEVICE_NOTIFY, ibm_handle_events, &ibm_note); if (ACPI_FAILURE(status)) { - err("%s: Failed to register notification handler\n", + err("%s: Failed to register notification handler\n", __FUNCTION__); retval = -EBUSY; goto init_cleanup; @@ -482,14 +480,13 @@ static void __exit ibm_acpiphp_exit(void) if (acpiphp_unregister_attention(&ibm_attention_info)) err("%s: attention info deregistration failed", __FUNCTION__); - status = acpi_remove_notify_handler( + status = acpi_remove_notify_handler( ibm_acpi_handle, ACPI_DEVICE_NOTIFY, ibm_handle_events); - if (ACPI_FAILURE(status)) - err("%s: Notification handler removal failed\n", - __FUNCTION__); - // remove the /sys entries + if (ACPI_FAILURE(status)) + err("%s: Notification handler removal failed\n", __FUNCTION__); + /* remove the /sys entries */ if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr)) err("%s: removal of sysfs file apci_table failed\n", __FUNCTION__); diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index aabf1e70b528..dc59da675c08 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -235,12 +235,12 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { int rc = 0; struct slot *pslot; - u8 cmd; + u8 cmd = 0x00; /* avoid compiler warning */ debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value); ibmphp_lock_operations(); - cmd = 0x00; // avoid compiler warning + if (hotplug_slot) { switch (value) { diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7d93dbaf628d..3eefe2cec72d 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -103,13 +103,13 @@ static struct slot *find_slot(struct device_node *dn) struct list_head *tmp, *n; struct slot *slot; - list_for_each_safe(tmp, n, &rpaphp_slot_head) { - slot = list_entry(tmp, struct slot, rpaphp_slot_list); - if (slot->dn == dn) - return slot; - } + list_for_each_safe(tmp, n, &rpaphp_slot_head) { + slot = list_entry(tmp, struct slot, rpaphp_slot_list); + if (slot->dn == dn) + return slot; + } - return NULL; + return NULL; } static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, @@ -126,9 +126,9 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, return NULL; } -static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) +static void dlpar_pci_add_bus(struct device_node *dn) { - struct pci_dn *pdn = dn->data; + struct pci_dn *pdn = PCI_DN(dn); struct pci_controller *phb = pdn->phb; struct pci_dev *dev = NULL; @@ -139,52 +139,52 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) if (!dev) { printk(KERN_ERR "%s: failed to create pci dev for %s\n", __FUNCTION__, dn->full_name); - return NULL; + return; } if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) of_scan_pci_bridge(dn, dev); - rpaphp_init_new_devs(dev->subordinate); + pcibios_fixup_new_pci_devices(dev->subordinate,0); /* Claim new bus resources */ pcibios_claim_one_bus(dev->bus); /* ioremap() for child bus, which may or may not succeed */ - (void) remap_bus_range(dev->bus); + remap_bus_range(dev->subordinate); /* Add new devices to global lists. Register in proc, sysfs. */ pci_bus_add_devices(phb->bus); - - /* Confirm new bridge dev was created */ - dev = dlpar_find_new_dev(phb->bus, dn); - if (dev) { - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - printk(KERN_ERR "%s: unexpected header type %d\n", - __FUNCTION__, dev->hdr_type); - return NULL; - } - } - - return dev; } static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; + struct pci_controller *phb; - if (rpaphp_find_pci_bus(dn)) + if (pcibios_find_pci_bus(dn)) return -EINVAL; /* Add pci bus */ - dev = dlpar_pci_add_bus(dn); + dlpar_pci_add_bus(dn); + + /* Confirm new bridge dev was created */ + phb = PCI_DN(dn)->phb; + dev = dlpar_find_new_dev(phb->bus, dn); + if (!dev) { printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__, drc_name); return -EIO; } + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n", + __FUNCTION__, dev->hdr_type, drc_name); + return -EIO; + } + /* Add hotplug slot */ if (rpaphp_add_slot(dn)) { printk(KERN_ERR "%s: unable to add hotplug slot %s\n", @@ -221,13 +221,13 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) struct pci_dn *pdn; int rc = 0; - if (!rpaphp_find_pci_bus(dn)) + if (!pcibios_find_pci_bus(dn)) return -EINVAL; slot = find_slot(dn); if (slot) { /* Remove hotplug slot */ - if (rpaphp_remove_slot(slot)) { + if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", __FUNCTION__, drc_name); @@ -366,21 +366,25 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) struct pci_bus *bus; struct slot *slot; - bus = rpaphp_find_pci_bus(dn); + bus = pcibios_find_pci_bus(dn); if (!bus) return -EINVAL; slot = find_slot(dn); if (slot) { /* Remove hotplug slot */ - if (rpaphp_remove_slot(slot)) { + if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", __FUNCTION__, drc_name); return -EIO; } } else { - rpaphp_unconfig_pci_adapter(bus); + struct pci_dev *dev, *tmp; + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { + eeh_remove_bus_device(dev); + pci_remove_bus_device(dev); + } } if (unmap_bus_range(bus)) { diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 57ea71a7bda5..310b6186c0e5 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -88,16 +88,10 @@ extern int num_slots; /* function prototypes */ /* rpaphp_pci.c */ -extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn); -extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); extern int rpaphp_enable_pci_slot(struct slot *slot); -extern int register_pci_slot(struct slot *slot); +extern int rpaphp_register_pci_slot(struct slot *slot); extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); -extern void rpaphp_init_new_devs(struct pci_bus *bus); -extern void rpaphp_eeh_init_nodes(struct device_node *dn); - -extern int rpaphp_config_pci_adapter(struct pci_bus *bus); -extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus); +extern int rpaphp_get_sensor_state(struct slot *slot, int *state); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); @@ -108,8 +102,8 @@ extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, /* rpaphp_slot.c */ extern void dealloc_slot_struct(struct slot *slot); extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); -extern int register_slot(struct slot *slot); -extern int deregister_slot(struct slot *slot); +extern int rpaphp_register_slot(struct slot *slot); +extern int rpaphp_deregister_slot(struct slot *slot); extern int rpaphp_get_power_status(struct slot *slot, u8 * value); extern int rpaphp_set_attention_status(struct slot *slot, u8 status); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index cf075c34b578..6e79f5675b0d 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -56,25 +56,6 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, 0644); -static int enable_slot(struct hotplug_slot *slot); -static int disable_slot(struct hotplug_slot *slot); -static int set_attention_status(struct hotplug_slot *slot, u8 value); -static int get_power_status(struct hotplug_slot *slot, u8 * value); -static int get_attention_status(struct hotplug_slot *slot, u8 * value); -static int get_adapter_status(struct hotplug_slot *slot, u8 * value); -static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); - -struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { - .owner = THIS_MODULE, - .enable_slot = enable_slot, - .disable_slot = disable_slot, - .set_attention_status = set_attention_status, - .get_power_status = get_power_status, - .get_attention_status = get_attention_status, - .get_adapter_status = get_adapter_status, - .get_max_bus_speed = get_max_bus_speed, -}; - static int rpaphp_get_attention_status(struct slot *slot) { return slot->hotplug_slot->info->attention_status; @@ -196,11 +177,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe return 0; } -int rpaphp_remove_slot(struct slot *slot) -{ - return deregister_slot(slot); -} - static int get_children_props(struct device_node *dn, int **drc_indexes, int **drc_names, int **drc_types, int **drc_power_domains) { @@ -307,13 +283,15 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names, return 0; } -/**************************************************************** +/** + * rpaphp_add_slot -- add hotplug or dlpar slot + * * rpaphp not only registers PCI hotplug slots(HOTPLUG), * but also logical DR slots(EMBEDDED). * HOTPLUG slot: An adapter can be physically added/removed. * EMBEDDED slot: An adapter can be logically removed/added * from/to a partition with the slot. - ***************************************************************/ + */ int rpaphp_add_slot(struct device_node *dn) { struct slot *slot; @@ -344,7 +322,7 @@ int rpaphp_add_slot(struct device_node *dn) dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", indexes[i + 1], name, type); - retval = register_pci_slot(slot); + retval = rpaphp_register_pci_slot(slot); } } exit: @@ -393,53 +371,85 @@ static void __exit rpaphp_exit(void) cleanup_slots(); } -static int enable_slot(struct hotplug_slot *hotplug_slot) +static int __enable_slot(struct slot *slot) { - int retval = 0; - struct slot *slot = (struct slot *)hotplug_slot->private; + int state; + int retval; - if (slot->state == CONFIGURED) { - dbg("%s: %s is already enabled\n", __FUNCTION__, slot->name); - goto exit; + if (slot->state == CONFIGURED) + return 0; + + retval = rpaphp_get_sensor_state(slot, &state); + if (retval) + return retval; + + if (state == PRESENT) { + pcibios_add_pci_devices(slot->bus); + slot->state = CONFIGURED; + } else if (state == EMPTY) { + slot->state = EMPTY; + } else { + err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name); + slot->state = NOT_VALID; + return -EINVAL; } + return 0; +} + +static int enable_slot(struct hotplug_slot *hotplug_slot) +{ + int retval; + struct slot *slot = (struct slot *)hotplug_slot->private; - dbg("ENABLING SLOT %s\n", slot->name); down(&rpaphp_sem); - retval = rpaphp_enable_pci_slot(slot); + retval = __enable_slot(slot); up(&rpaphp_sem); -exit: - dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); + return retval; } -static int disable_slot(struct hotplug_slot *hotplug_slot) +static int __disable_slot(struct slot *slot) { - int retval = -EINVAL; - struct slot *slot = (struct slot *)hotplug_slot->private; + struct pci_dev *dev, *tmp; - dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name); + if (slot->state == NOT_CONFIGURED) + return -EINVAL; - if (slot->state == NOT_CONFIGURED) { - dbg("%s: %s is already disabled\n", __FUNCTION__, slot->name); - goto exit; + list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) { + eeh_remove_bus_device(dev); + pci_remove_bus_device(dev); } - dbg("DISABLING SLOT %s\n", slot->name); + slot->state = NOT_CONFIGURED; + return 0; +} + +static int disable_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = (struct slot *)hotplug_slot->private; + int retval; + down(&rpaphp_sem); - retval = rpaphp_unconfig_pci_adapter(slot->bus); + retval = __disable_slot (slot); up(&rpaphp_sem); - slot->state = NOT_CONFIGURED; - info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__, - slot->name); -exit: - dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); + return retval; } +struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .set_attention_status = set_attention_status, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, +}; + module_init(rpaphp_init); module_exit(rpaphp_exit); EXPORT_SYMBOL_GPL(rpaphp_add_slot); -EXPORT_SYMBOL_GPL(rpaphp_remove_slot); EXPORT_SYMBOL_GPL(rpaphp_slot_head); EXPORT_SYMBOL_GPL(rpaphp_get_drc_props); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 396b54b0c847..6f6cbede5135 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -32,37 +32,7 @@ #include "../pci.h" /* for pci_add_new_bus */ #include "rpaphp.h" -static struct pci_bus *find_bus_among_children(struct pci_bus *bus, - struct device_node *dn) -{ - struct pci_bus *child = NULL; - struct list_head *tmp; - struct device_node *busdn; - - busdn = pci_bus_to_OF_node(bus); - if (busdn == dn) - return bus; - - list_for_each(tmp, &bus->children) { - child = find_bus_among_children(pci_bus_b(tmp), dn); - if (child) - break; - } - return child; -} - -struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn) -{ - struct pci_dn *pdn = dn->data; - - if (!pdn || !pdn->phb || !pdn->phb->bus) - return NULL; - - return find_bus_among_children(pdn->phb->bus, dn); -} -EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus); - -static int rpaphp_get_sensor_state(struct slot *slot, int *state) +int rpaphp_get_sensor_state(struct slot *slot, int *state) { int rc; int setlevel; @@ -120,7 +90,7 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) /* config/unconfig adapter */ *value = slot->state; } else { - bus = rpaphp_find_pci_bus(slot->dn); + bus = pcibios_find_pci_bus(slot->dn); if (bus && !list_empty(&bus->devices)) *value = CONFIGURED; else @@ -131,140 +101,6 @@ exit: return rc; } -/* Must be called before pci_bus_add_devices */ -void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - /* - * Skip already-present devices (which are on the - * global device list.) - */ - if (list_empty(&dev->global_list)) { - int i; - - /* Need to setup IOMMU tables */ - ppc_md.iommu_dev_setup(dev); - - if(fix_bus) - pcibios_fixup_device_resources(dev, bus); - pci_read_irq_line(dev); - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; - - if (r->parent || !r->start || !r->flags) - continue; - pci_claim_resource(dev, i); - } - } - } -} - -static void rpaphp_eeh_add_bus_device(struct pci_bus *bus) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - eeh_add_device_late(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - struct pci_bus *subbus = dev->subordinate; - if (subbus) - rpaphp_eeh_add_bus_device (subbus); - } - } -} - -static int rpaphp_pci_config_bridge(struct pci_dev *dev) -{ - u8 sec_busno; - struct pci_bus *child_bus; - struct pci_dev *child_dev; - - dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev)); - - /* get busno of downstream bus */ - pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno); - - /* add to children of PCI bridge dev->bus */ - child_bus = pci_add_new_bus(dev->bus, dev, sec_busno); - if (!child_bus) { - err("%s: could not add second bus\n", __FUNCTION__); - return -EIO; - } - sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number); - /* do pci_scan_child_bus */ - pci_scan_child_bus(child_bus); - - list_for_each_entry(child_dev, &child_bus->devices, bus_list) { - eeh_add_device_late(child_dev); - } - - /* fixup new pci devices without touching bus struct */ - rpaphp_fixup_new_pci_devices(child_bus, 0); - - /* Make the discovered devices available */ - pci_bus_add_devices(child_bus); - return 0; -} - -void rpaphp_init_new_devs(struct pci_bus *bus) -{ - rpaphp_fixup_new_pci_devices(bus, 0); - rpaphp_eeh_add_bus_device(bus); -} -EXPORT_SYMBOL_GPL(rpaphp_init_new_devs); - -/***************************************************************************** - rpaphp_pci_config_slot() will configure all devices under the - given slot->dn and return the the first pci_dev. - *****************************************************************************/ -static struct pci_dev * -rpaphp_pci_config_slot(struct pci_bus *bus) -{ - struct device_node *dn = pci_bus_to_OF_node(bus); - struct pci_dev *dev = NULL; - int slotno; - int num; - - dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); - if (!dn || !dn->child) - return NULL; - - if (_machine == PLATFORM_PSERIES_LPAR) { - of_scan_bus(dn, bus); - if (list_empty(&bus->devices)) { - err("%s: No new device found\n", __FUNCTION__); - return NULL; - } - - rpaphp_init_new_devs(bus); - pci_bus_add_devices(bus); - dev = list_entry(&bus->devices, struct pci_dev, bus_list); - } else { - slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); - - /* pci_scan_slot should find all children */ - num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); - if (num) { - rpaphp_fixup_new_pci_devices(bus, 1); - pci_bus_add_devices(bus); - } - if (list_empty(&bus->devices)) { - err("%s: No new device found\n", __FUNCTION__); - return NULL; - } - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - rpaphp_pci_config_bridge(dev); - - rpaphp_eeh_add_bus_device(bus); - } - } - - return dev; -} - static void print_slot_pci_funcs(struct pci_bus *bus) { struct device_node *dn; @@ -280,60 +116,6 @@ static void print_slot_pci_funcs(struct pci_bus *bus) return; } -int rpaphp_config_pci_adapter(struct pci_bus *bus) -{ - struct device_node *dn = pci_bus_to_OF_node(bus); - struct pci_dev *dev; - int rc = -ENODEV; - - dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name); - if (!dn) - goto exit; - - eeh_add_device_tree_early(dn); - dev = rpaphp_pci_config_slot(bus); - if (!dev) { - err("%s: can't find any devices.\n", __FUNCTION__); - goto exit; - } - print_slot_pci_funcs(bus); - rc = 0; -exit: - dbg("Exit %s: rc=%d\n", __FUNCTION__, rc); - return rc; -} -EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter); - -static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) -{ - eeh_remove_device(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - struct pci_bus *bus = dev->subordinate; - struct list_head *ln; - if (!bus) - return; - for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { - struct pci_dev *pdev = pci_dev_b(ln); - if (pdev) - rpaphp_eeh_remove_bus_device(pdev); - } - - } - return; -} - -int rpaphp_unconfig_pci_adapter(struct pci_bus *bus) -{ - struct pci_dev *dev, *tmp; - - list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { - rpaphp_eeh_remove_bus_device(dev); - pci_remove_bus_device(dev); - } - return 0; -} -EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter); - static int setup_pci_hotplug_slot_info(struct slot *slot) { struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; @@ -370,7 +152,7 @@ static int setup_pci_slot(struct slot *slot) struct pci_bus *bus; BUG_ON(!dn); - bus = rpaphp_find_pci_bus(dn); + bus = pcibios_find_pci_bus(dn); if (!bus) { err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); goto exit_rc; @@ -395,10 +177,7 @@ static int setup_pci_slot(struct slot *slot) if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { dbg("%s CONFIGURING pci adapter in slot[%s]\n", __FUNCTION__, slot->name); - if (rpaphp_config_pci_adapter(slot->bus)) { - err("%s: CONFIG pci adapter failed\n", __FUNCTION__); - goto exit_rc; - } + pcibios_add_pci_devices(slot->bus); } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", @@ -420,7 +199,7 @@ exit_rc: return -EINVAL; } -int register_pci_slot(struct slot *slot) +int rpaphp_register_pci_slot(struct slot *slot) { int rc = -EINVAL; @@ -428,42 +207,8 @@ int register_pci_slot(struct slot *slot) goto exit_rc; if (setup_pci_slot(slot)) goto exit_rc; - rc = register_slot(slot); + rc = rpaphp_register_slot(slot); exit_rc: return rc; } -int rpaphp_enable_pci_slot(struct slot *slot) -{ - int retval = 0, state; - - retval = rpaphp_get_sensor_state(slot, &state); - if (retval) - goto exit; - dbg("%s: sensor state[%d]\n", __FUNCTION__, state); - /* if slot is not empty, enable the adapter */ - if (state == PRESENT) { - dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name); - retval = rpaphp_config_pci_adapter(slot->bus); - if (!retval) { - slot->state = CONFIGURED; - info("%s: devices in slot[%s] configured\n", - __FUNCTION__, slot->name); - } else { - slot->state = NOT_CONFIGURED; - dbg("%s: no pci_dev struct for adapter in slot[%s]\n", - __FUNCTION__, slot->name); - } - } else if (state == EMPTY) { - dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name); - slot->state = EMPTY; - } else { - err("%s: slot[%s] is in invalid state\n", __FUNCTION__, - slot->name); - slot->state = NOT_VALID; - retval = -EINVAL; - } -exit: - dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); - return retval; -} diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index daa89ae57123..78943e064b59 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -35,16 +35,16 @@ static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) { - char *value; - int retval = -ENOENT; + char *value; + int retval = -ENOENT; struct slot *slot = (struct slot *)php_slot->private; if (!slot) return retval; - value = slot->location; - retval = sprintf (buf, "%s\n", value); - return retval; + value = slot->location; + retval = sprintf (buf, "%s\n", value); + return retval; } static struct hotplug_slot_attribute hotplug_slot_attr_location = { @@ -137,7 +137,7 @@ static int is_registered(struct slot *slot) return 0; } -int deregister_slot(struct slot *slot) +int rpaphp_deregister_slot(struct slot *slot) { int retval = 0; struct hotplug_slot *php_slot = slot->hotplug_slot; @@ -159,8 +159,9 @@ int deregister_slot(struct slot *slot) dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } +EXPORT_SYMBOL_GPL(rpaphp_deregister_slot); -int register_slot(struct slot *slot) +int rpaphp_register_slot(struct slot *slot) { int retval; @@ -169,7 +170,7 @@ int register_slot(struct slot *slot) slot->power_domain, slot->type); /* should not try to register the same slot twice */ if (is_registered(slot)) { /* should't be here */ - err("register_slot: slot[%s] is already registered\n", slot->name); + err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); rpaphp_release_slot(slot->hotplug_slot); return -EAGAIN; } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ce0e9b6ce833..7d6f521d02ea 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -95,6 +95,7 @@ struct controller { u8 function; u8 slot_device_offset; u8 add_support; + u32 pcix_misc2_reg; /* for amd pogo errata */ enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ @@ -113,6 +114,26 @@ struct hotplug_params { /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 +#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 + +/* AMD PCIX bridge registers */ + +#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C +#define PCIX_MISCII_OFFSET 0x48 +#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 + +/* AMD PCIX_MISCII masks and offsets */ +#define PERRNONFATALENABLE_MASK 0x00040000 +#define PERRFATALENABLE_MASK 0x00080000 +#define PERRFLOODENABLE_MASK 0x00100000 +#define SERRNONFATALENABLE_MASK 0x00200000 +#define SERRFATALENABLE_MASK 0x00400000 + +/* AMD PCIX_MISC_BRIDGE_ERRORS masks and offsets */ +#define PERR_OBSERVED_MASK 0x00000001 + +/* AMD PCIX_MEM_BASE_LIMIT masks */ +#define RSE_MASK 0x40000000 #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 @@ -333,6 +354,79 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) return retval; } +static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) +{ + u32 pcix_misc2_temp; + + /* save MiscII register */ + pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp); + + p_slot->ctrl->pcix_misc2_reg = pcix_misc2_temp; + + /* clear SERR/PERR enable bits */ + pcix_misc2_temp &= ~SERRFATALENABLE_MASK; + pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK; + pcix_misc2_temp &= ~PERRFLOODENABLE_MASK; + pcix_misc2_temp &= ~PERRFATALENABLE_MASK; + pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK; + pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); +} + +static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) +{ + u32 pcix_misc2_temp; + u32 pcix_bridge_errors_reg; + u32 pcix_mem_base_reg; + u8 perr_set; + u8 rse_set; + + /* write-one-to-clear Bridge_Errors[ PERR_OBSERVED ] */ + pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg); + perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK; + if (perr_set) { + dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set); + + pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set); + } + + /* write-one-to-clear Memory_Base_Limit[ RSE ] */ + pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg); + rse_set = pcix_mem_base_reg & RSE_MASK; + if (rse_set) { + dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ ); + + pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set); + } + /* restore MiscII register */ + pci_read_config_dword( p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp ); + + if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK) + pcix_misc2_temp |= SERRFATALENABLE_MASK; + else + pcix_misc2_temp &= ~SERRFATALENABLE_MASK; + + if (p_slot->ctrl->pcix_misc2_reg & SERRNONFATALENABLE_MASK) + pcix_misc2_temp |= SERRNONFATALENABLE_MASK; + else + pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK; + + if (p_slot->ctrl->pcix_misc2_reg & PERRFLOODENABLE_MASK) + pcix_misc2_temp |= PERRFLOODENABLE_MASK; + else + pcix_misc2_temp &= ~PERRFLOODENABLE_MASK; + + if (p_slot->ctrl->pcix_misc2_reg & PERRFATALENABLE_MASK) + pcix_misc2_temp |= PERRFATALENABLE_MASK; + else + pcix_misc2_temp &= ~PERRFATALENABLE_MASK; + + if (p_slot->ctrl->pcix_misc2_reg & PERRNONFATALENABLE_MASK) + pcix_misc2_temp |= PERRNONFATALENABLE_MASK; + else + pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK; + pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); +} + #define SLOT_NAME_SIZE 10 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 25ccb0e47593..643252d9bf3b 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -894,7 +894,17 @@ int shpchp_enable_slot (struct slot *p_slot) dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - rc = board_added(p_slot); + if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) || + (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)) + && p_slot->ctrl->num_slots == 1) { + /* handle amd pogo errata; this must be done before enable */ + amd_pogo_errata_save_misc_reg(p_slot); + rc = board_added(p_slot); + /* handle amd pogo errata; this must be done after enable */ + amd_pogo_errata_restore_misc_reg(p_slot); + } else + rc = board_added(p_slot); + if (rc) { p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 202b7507a357..48723d6fa60f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -137,6 +137,8 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) break; } } +#else +#define set_msi_affinity NULL #endif /* CONFIG_SMP */ static void mask_MSI_irq(unsigned int vector) @@ -214,7 +216,7 @@ static struct hw_interrupt_type msix_irq_type = { .disable = mask_MSI_irq, .ack = mask_MSI_irq, .end = end_msi_irq_w_maskbit, - .set_affinity = set_msi_irq_affinity + .set_affinity = set_msi_affinity }; /* @@ -230,7 +232,7 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = { .disable = mask_MSI_irq, .ack = mask_MSI_irq, .end = end_msi_irq_w_maskbit, - .set_affinity = set_msi_irq_affinity + .set_affinity = set_msi_affinity }; /* @@ -246,7 +248,7 @@ static struct hw_interrupt_type msi_irq_wo_maskbit_type = { .disable = do_nothing, .ack = do_nothing, .end = end_msi_irq_wo_maskbit, - .set_affinity = set_msi_irq_affinity + .set_affinity = set_msi_affinity }; static void msi_data_init(struct msg_data *msi_data, @@ -416,7 +418,9 @@ static void attach_msi_entry(struct msi_desc *entry, int vector) static void irq_handler_init(int cap_id, int pos, int mask) { - spin_lock(&irq_desc[pos].lock); + unsigned long flags; + + spin_lock_irqsave(&irq_desc[pos].lock, flags); if (cap_id == PCI_CAP_ID_MSIX) irq_desc[pos].handler = &msix_irq_type; else { @@ -425,7 +429,7 @@ static void irq_handler_init(int cap_id, int pos, int mask) else irq_desc[pos].handler = &msi_irq_w_maskbit_type; } - spin_unlock(&irq_desc[pos].lock); + spin_unlock_irqrestore(&irq_desc[pos].lock, flags); } static void enable_msi_mode(struct pci_dev *dev, int pos, int type) diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 402136a5c9e4..4ac52d441e47 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -22,12 +22,6 @@ extern int vector_irq[NR_VECTORS]; extern void (*interrupt[NR_IRQS])(void); extern int pci_vector_resources(int last, int nr_released); -#ifdef CONFIG_SMP -#define set_msi_irq_affinity set_msi_affinity -#else -#define set_msi_irq_affinity NULL -#endif - /* * MSI-X Address Register */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d2a633efa10a..d2d187916643 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -163,6 +163,7 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap); } +#if 0 /** * pci_find_ext_capability - Find an extended capability * @dev: PCI device to query @@ -210,6 +211,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) return 0; } +#endif /* 0 */ /** * pci_find_parent_resource - return resource region of parent bus of given region diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 50d6685dcbcc..ea9277b7f899 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -112,6 +112,7 @@ pci_claim_resource(struct pci_dev *dev, int resource) return err; } +EXPORT_SYMBOL_GPL(pci_claim_resource); int pci_assign_resource(struct pci_dev *dev, int resno) { diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 0ecbe4edbec1..aaa568a3806e 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -363,7 +363,7 @@ static int card_resume(struct pnp_dev *dev) int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count = 0; + int count; struct list_head *pos, *temp; drv->link.name = drv->name; @@ -374,10 +374,15 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) drv->link.suspend = drv->suspend ? card_suspend : NULL; drv->link.resume = drv->resume ? card_resume : NULL; + count = pnp_register_driver(&drv->link); + if (count < 0) + return count; + spin_lock(&pnp_lock); list_add_tail(&drv->global_list, &pnp_card_drivers); spin_unlock(&pnp_lock); - pnp_register_driver(&drv->link); + + count = 0; list_for_each_safe(pos,temp,&pnp_cards){ struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 816479ad217b..f104577f73e0 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -27,12 +27,15 @@ static int num = 0; +/* We need only to blacklist devices that have already an acpi driver that + * can't use pnp layer. We don't need to blacklist device that are directly + * used by the kernel (PCI root, ...), as it is harmless and there were + * already present in pnpbios. But there is an exception for devices that + * have irqs (PIC, Timer) because we call acpi_register_gsi. + * Finaly only devices that have a CRS method need to be in this list. + */ static char __initdata excluded_id_list[] = - "PNP0C0A," /* Battery */ - "PNP0C0C,PNP0C0E,PNP0C0D," /* Button */ "PNP0C09," /* EC */ - "PNP0C0B," /* Fan */ - "PNP0A03," /* PCI root */ "PNP0C0F," /* Link device */ "PNP0000," /* PIC */ "PNP0100," /* Timer */ @@ -131,7 +134,8 @@ static int __init pnpacpi_add_device(struct acpi_device *device) struct pnp_id *dev_id; struct pnp_dev *dev; - if (!ispnpidacpi(acpi_device_hid(device)) || + status = acpi_get_handle(device->handle, "_CRS", &temp); + if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || is_exclusive_device(device)) return 0; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 416d30debe6c..407b4eaddcbf 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -3,7 +3,7 @@ * * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> - * + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any @@ -32,17 +32,17 @@ /* * Allocated Resources */ -static int irq_flags(int edge_level, int active_high_low) +static int irq_flags(int triggering, int polarity) { int flag; - if (edge_level == ACPI_LEVEL_SENSITIVE) { - if(active_high_low == ACPI_ACTIVE_LOW) + if (triggering == ACPI_LEVEL_SENSITIVE) { + if(polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWLEVEL; else flag = IORESOURCE_IRQ_HIGHLEVEL; } else { - if(active_high_low == ACPI_ACTIVE_LOW) + if(polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWEDGE; else flag = IORESOURCE_IRQ_HIGHEDGE; @@ -50,31 +50,31 @@ static int irq_flags(int edge_level, int active_high_low) return flag; } -static void decode_irq_flags(int flag, int *edge_level, int *active_high_low) +static void decode_irq_flags(int flag, int *triggering, int *polarity) { switch (flag) { case IORESOURCE_IRQ_LOWLEVEL: - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; + *triggering = ACPI_LEVEL_SENSITIVE; + *polarity = ACPI_ACTIVE_LOW; break; case IORESOURCE_IRQ_HIGHLEVEL: - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_HIGH; + *triggering = ACPI_LEVEL_SENSITIVE; + *polarity = ACPI_ACTIVE_HIGH; break; case IORESOURCE_IRQ_LOWEDGE: - *edge_level = ACPI_EDGE_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; + *triggering = ACPI_EDGE_SENSITIVE; + *polarity = ACPI_ACTIVE_LOW; break; case IORESOURCE_IRQ_HIGHEDGE: - *edge_level = ACPI_EDGE_SENSITIVE; - *active_high_low = ACPI_ACTIVE_HIGH; + *triggering = ACPI_EDGE_SENSITIVE; + *polarity = ACPI_ACTIVE_HIGH; break; } } static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, - int edge_level, int active_high_low) + int triggering, int polarity) { int i = 0; int irq; @@ -89,7 +89,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, return; res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag - irq = acpi_register_gsi(gsi, edge_level, active_high_low); + irq = acpi_register_gsi(gsi, triggering, polarity); if (irq < 0) { res->irq_resource[i].flags |= IORESOURCE_DISABLED; return; @@ -163,77 +163,96 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; int i; - switch (res->id) { - case ACPI_RSTYPE_IRQ: + switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: /* * Per spec, only one interrupt per descriptor is allowed in * _CRS, but some firmware violates this, so parse them all. */ - for (i = 0; i < res->data.irq.number_of_interrupts; i++) { + for (i = 0; i < res->data.irq.interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, res->data.irq.interrupts[i], - res->data.irq.edge_level, - res->data.irq.active_high_low); + res->data.irq.triggering, + res->data.irq.polarity); } break; - case ACPI_RSTYPE_EXT_IRQ: - for (i = 0; i < res->data.extended_irq.number_of_interrupts; i++) { - pnpacpi_parse_allocated_irqresource(res_table, - res->data.extended_irq.interrupts[i], - res->data.extended_irq.edge_level, - res->data.extended_irq.active_high_low); - } - break; - case ACPI_RSTYPE_DMA: - if (res->data.dma.number_of_channels > 0) - pnpacpi_parse_allocated_dmaresource(res_table, + case ACPI_RESOURCE_TYPE_DMA: + if (res->data.dma.channel_count > 0) + pnpacpi_parse_allocated_dmaresource(res_table, res->data.dma.channels[0]); break; - case ACPI_RSTYPE_IO: - pnpacpi_parse_allocated_ioresource(res_table, - res->data.io.min_base_address, - res->data.io.range_length); + + case ACPI_RESOURCE_TYPE_IO: + pnpacpi_parse_allocated_ioresource(res_table, + res->data.io.minimum, + res->data.io.address_length); break; - case ACPI_RSTYPE_FIXED_IO: - pnpacpi_parse_allocated_ioresource(res_table, - res->data.fixed_io.base_address, - res->data.fixed_io.range_length); + + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_DEPENDENT: break; - case ACPI_RSTYPE_MEM24: - pnpacpi_parse_allocated_memresource(res_table, - res->data.memory24.min_base_address, - res->data.memory24.range_length); + + case ACPI_RESOURCE_TYPE_FIXED_IO: + pnpacpi_parse_allocated_ioresource(res_table, + res->data.fixed_io.address, + res->data.fixed_io.address_length); + break; + + case ACPI_RESOURCE_TYPE_VENDOR: break; - case ACPI_RSTYPE_MEM32: - pnpacpi_parse_allocated_memresource(res_table, - res->data.memory32.min_base_address, - res->data.memory32.range_length); + + case ACPI_RESOURCE_TYPE_END_TAG: + break; + + case ACPI_RESOURCE_TYPE_MEMORY24: + pnpacpi_parse_allocated_memresource(res_table, + res->data.memory24.minimum, + res->data.memory24.address_length); break; - case ACPI_RSTYPE_FIXED_MEM32: - pnpacpi_parse_allocated_memresource(res_table, - res->data.fixed_memory32.range_base_address, - res->data.fixed_memory32.range_length); + case ACPI_RESOURCE_TYPE_MEMORY32: + pnpacpi_parse_allocated_memresource(res_table, + res->data.memory32.minimum, + res->data.memory32.address_length); break; - case ACPI_RSTYPE_ADDRESS16: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address16.min_address_range, + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + pnpacpi_parse_allocated_memresource(res_table, + res->data.fixed_memory32.address, + res->data.fixed_memory32.address_length); + break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + pnpacpi_parse_allocated_memresource(res_table, + res->data.address16.minimum, res->data.address16.address_length); break; - case ACPI_RSTYPE_ADDRESS32: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address32.min_address_range, + case ACPI_RESOURCE_TYPE_ADDRESS32: + pnpacpi_parse_allocated_memresource(res_table, + res->data.address32.minimum, res->data.address32.address_length); break; - case ACPI_RSTYPE_ADDRESS64: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address64.min_address_range, + case ACPI_RESOURCE_TYPE_ADDRESS64: + pnpacpi_parse_allocated_memresource(res_table, + res->data.address64.minimum, res->data.address64.address_length); break; - case ACPI_RSTYPE_VENDOR: + + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { + pnpacpi_parse_allocated_irqresource(res_table, + res->data.extended_irq.interrupts[i], + res->data.extended_irq.triggering, + res->data.extended_irq.polarity); + } + break; + + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: break; + default: - pnp_warn("PnPACPI: unknown resource type %d", res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } @@ -253,13 +272,13 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso int i; struct pnp_dma * dma; - if (p->number_of_channels == 0) + if (p->channel_count == 0) return; dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); if (!dma) return; - for(i = 0; i < p->number_of_channels; i++) + for(i = 0; i < p->channel_count; i++) dma->map |= 1 << p->channels[i]; dma->flags = 0; if (p->bus_master) @@ -309,37 +328,37 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, int i; struct pnp_irq * irq; - if (p->number_of_interrupts == 0) + if (p->interrupt_count == 0) return; irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; - for(i = 0; i < p->number_of_interrupts; i++) + for(i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); - irq->flags = irq_flags(p->edge_level, p->active_high_low); + irq->flags = irq_flags(p->triggering, p->polarity); pnp_register_irq_resource(option, irq); return; } static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, - struct acpi_resource_ext_irq *p) + struct acpi_resource_extended_irq *p) { int i; struct pnp_irq * irq; - if (p->number_of_interrupts == 0) + if (p->interrupt_count == 0) return; irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; - for(i = 0; i < p->number_of_interrupts; i++) + for(i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); - irq->flags = irq_flags(p->edge_level, p->active_high_low); + irq->flags = irq_flags(p->triggering, p->polarity); pnp_register_irq_resource(option, irq); return; @@ -351,16 +370,16 @@ pnpacpi_parse_port_option(struct pnp_option *option, { struct pnp_port * port; - if (io->range_length == 0) + if (io->address_length == 0) return; port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; - port->min = io->min_base_address; - port->max = io->max_base_address; + port->min = io->minimum; + port->max = io->maximum; port->align = io->alignment; - port->size = io->range_length; - port->flags = ACPI_DECODE_16 == io->io_decode ? + port->size = io->address_length; + port->flags = ACPI_DECODE_16 == io->io_decode ? PNP_PORT_FLAG_16BITADDR : 0; pnp_register_port_resource(option,port); return; @@ -372,13 +391,13 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, { struct pnp_port * port; - if (io->range_length == 0) + if (io->address_length == 0) return; port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; - port->min = port->max = io->base_address; - port->size = io->range_length; + port->min = port->max = io->address; + port->size = io->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; pnp_register_port_resource(option,port); @@ -387,21 +406,21 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, static void pnpacpi_parse_mem24_option(struct pnp_option *option, - struct acpi_resource_mem24 *p) + struct acpi_resource_memory24 *p) { struct pnp_mem * mem; - if (p->range_length == 0) + if (p->address_length == 0) return; mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; - mem->min = p->min_base_address; - mem->max = p->max_base_address; + mem->min = p->minimum; + mem->max = p->maximum; mem->align = p->alignment; - mem->size = p->range_length; + mem->size = p->address_length; - mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option,mem); @@ -410,21 +429,21 @@ pnpacpi_parse_mem24_option(struct pnp_option *option, static void pnpacpi_parse_mem32_option(struct pnp_option *option, - struct acpi_resource_mem32 *p) + struct acpi_resource_memory32 *p) { struct pnp_mem * mem; - if (p->range_length == 0) + if (p->address_length == 0) return; mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; - mem->min = p->min_base_address; - mem->max = p->max_base_address; + mem->min = p->minimum; + mem->max = p->maximum; mem->align = p->alignment; - mem->size = p->range_length; + mem->size = p->address_length; - mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option,mem); @@ -433,33 +452,72 @@ pnpacpi_parse_mem32_option(struct pnp_option *option, static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, - struct acpi_resource_fixed_mem32 *p) + struct acpi_resource_fixed_memory32 *p) { struct pnp_mem * mem; - if (p->range_length == 0) + if (p->address_length == 0) return; mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; - mem->min = mem->max = p->range_base_address; - mem->size = p->range_length; + mem->min = mem->max = p->address; + mem->size = p->address_length; mem->align = 0; - mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ? + mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option,mem); return; } +static void +pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) +{ + struct acpi_resource_address64 addr, *p = &addr; + acpi_status status; + struct pnp_mem * mem; + struct pnp_port * port; + + status = acpi_resource_to_address64(r, p); + if (!ACPI_SUCCESS(status)) { + pnp_warn("PnPACPI: failed to convert resource type %d", r->type); + return; + } + + if (p->address_length == 0) + return; + + if (p->resource_type == ACPI_MEMORY_RANGE) { + mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); + if (!mem) + return; + mem->min = mem->max = p->minimum; + mem->size = p->address_length; + mem->align = 0; + mem->flags = (p->info.mem.write_protect == + ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; + pnp_register_mem_resource(option,mem); + } else if (p->resource_type == ACPI_IO_RANGE) { + port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); + if (!port) + return; + port->min = port->max = p->minimum; + port->size = p->address_length; + port->align = 0; + port->flags = PNP_PORT_FLAG_FIXED; + pnp_register_port_resource(option,port); + } +} + struct acpipnp_parse_option_s { struct pnp_option *option; struct pnp_option *option_independent; struct pnp_dev *dev; }; -static acpi_status pnpacpi_option_resource(struct acpi_resource *res, +static acpi_status pnpacpi_option_resource(struct acpi_resource *res, void *data) { int priority = 0; @@ -467,35 +525,16 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, struct pnp_dev *dev = parse_data->dev; struct pnp_option *option = parse_data->option; - switch (res->id) { - case ACPI_RSTYPE_IRQ: + switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: pnpacpi_parse_irq_option(option, &res->data.irq); break; - case ACPI_RSTYPE_EXT_IRQ: - pnpacpi_parse_ext_irq_option(option, - &res->data.extended_irq); - break; - case ACPI_RSTYPE_DMA: + + case ACPI_RESOURCE_TYPE_DMA: pnpacpi_parse_dma_option(option, &res->data.dma); break; - case ACPI_RSTYPE_IO: - pnpacpi_parse_port_option(option, &res->data.io); - break; - case ACPI_RSTYPE_FIXED_IO: - pnpacpi_parse_fixed_port_option(option, - &res->data.fixed_io); - break; - case ACPI_RSTYPE_MEM24: - pnpacpi_parse_mem24_option(option, &res->data.memory24); - break; - case ACPI_RSTYPE_MEM32: - pnpacpi_parse_mem32_option(option, &res->data.memory32); - break; - case ACPI_RSTYPE_FIXED_MEM32: - pnpacpi_parse_fixed_mem32_option(option, - &res->data.fixed_memory32); - break; - case ACPI_RSTYPE_START_DPF: + + case ACPI_RESOURCE_TYPE_START_DEPENDENT: switch (res->data.start_dpf.compatibility_priority) { case ACPI_GOOD_CONFIGURATION: priority = PNP_RES_PRIORITY_PREFERRED; @@ -518,7 +557,8 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, return AE_ERROR; parse_data->option = option; break; - case ACPI_RSTYPE_END_DPF: + + case ACPI_RESOURCE_TYPE_END_DEPENDENT: /*only one EndDependentFn is allowed*/ if (!parse_data->option_independent) { pnp_warn("PnPACPI: more than one EndDependentFn"); @@ -527,15 +567,59 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, parse_data->option = parse_data->option_independent; parse_data->option_independent = NULL; break; + + case ACPI_RESOURCE_TYPE_IO: + pnpacpi_parse_port_option(option, &res->data.io); + break; + + case ACPI_RESOURCE_TYPE_FIXED_IO: + pnpacpi_parse_fixed_port_option(option, + &res->data.fixed_io); + break; + + case ACPI_RESOURCE_TYPE_VENDOR: + case ACPI_RESOURCE_TYPE_END_TAG: + break; + + case ACPI_RESOURCE_TYPE_MEMORY24: + pnpacpi_parse_mem24_option(option, &res->data.memory24); + break; + + case ACPI_RESOURCE_TYPE_MEMORY32: + pnpacpi_parse_mem32_option(option, &res->data.memory32); + break; + + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + pnpacpi_parse_fixed_mem32_option(option, + &res->data.fixed_memory32); + break; + + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + pnpacpi_parse_address_option(option, res); + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + pnpacpi_parse_ext_irq_option(option, + &res->data.extended_irq); + break; + + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: + break; + default: - pnp_warn("PnPACPI: unknown resource type %d", res->id); + pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } return AE_OK; } -acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, +acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, struct pnp_dev *dev) { acpi_status status; @@ -546,7 +630,7 @@ acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, return AE_ERROR; parse_data.option_independent = parse_data.option; parse_data.dev = dev; - status = acpi_walk_resources(handle, METHOD_NAME__PRS, + status = acpi_walk_resources(handle, METHOD_NAME__PRS, pnpacpi_option_resource, &parse_data); return status; @@ -559,21 +643,24 @@ static acpi_status pnpacpi_count_resources(struct acpi_resource *res, void *data) { int *res_cnt = (int *)data; - switch (res->id) { - case ACPI_RSTYPE_IRQ: - case ACPI_RSTYPE_EXT_IRQ: - case ACPI_RSTYPE_DMA: - case ACPI_RSTYPE_IO: - case ACPI_RSTYPE_FIXED_IO: - case ACPI_RSTYPE_MEM24: - case ACPI_RSTYPE_MEM32: - case ACPI_RSTYPE_FIXED_MEM32: -#if 0 - case ACPI_RSTYPE_ADDRESS16: - case ACPI_RSTYPE_ADDRESS32: - case ACPI_RSTYPE_ADDRESS64: -#endif + switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: + case ACPI_RESOURCE_TYPE_DMA: + case ACPI_RESOURCE_TYPE_IO: + case ACPI_RESOURCE_TYPE_FIXED_IO: + case ACPI_RESOURCE_TYPE_MEMORY24: + case ACPI_RESOURCE_TYPE_MEMORY32: + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: (*res_cnt) ++; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + case ACPI_RESOURCE_TYPE_VENDOR: + case ACPI_RESOURCE_TYPE_END_TAG: + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: return AE_OK; } @@ -584,22 +671,25 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) { struct acpi_resource **resource = (struct acpi_resource **)data; - switch (res->id) { - case ACPI_RSTYPE_IRQ: - case ACPI_RSTYPE_EXT_IRQ: - case ACPI_RSTYPE_DMA: - case ACPI_RSTYPE_IO: - case ACPI_RSTYPE_FIXED_IO: - case ACPI_RSTYPE_MEM24: - case ACPI_RSTYPE_MEM32: - case ACPI_RSTYPE_FIXED_MEM32: -#if 0 - case ACPI_RSTYPE_ADDRESS16: - case ACPI_RSTYPE_ADDRESS32: - case ACPI_RSTYPE_ADDRESS64: -#endif - (*resource)->id = res->id; + switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: + case ACPI_RESOURCE_TYPE_DMA: + case ACPI_RESOURCE_TYPE_IO: + case ACPI_RESOURCE_TYPE_FIXED_IO: + case ACPI_RESOURCE_TYPE_MEMORY24: + case ACPI_RESOURCE_TYPE_MEMORY32: + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + (*resource)->type = res->type; (*resource)++; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + case ACPI_RESOURCE_TYPE_VENDOR: + case ACPI_RESOURCE_TYPE_END_TAG: + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: return AE_OK; } @@ -607,14 +697,14 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, return AE_OK; } -int pnpacpi_build_resource_template(acpi_handle handle, +int pnpacpi_build_resource_template(acpi_handle handle, struct acpi_buffer *buffer) { struct acpi_resource *resource; int res_cnt = 0; acpi_status status; - status = acpi_walk_resources(handle, METHOD_NAME__CRS, + status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_count_resources, &res_cnt); if (ACPI_FAILURE(status)) { pnp_err("Evaluate _CRS failed"); @@ -628,7 +718,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, return -ENOMEM; pnp_dbg("Res cnt %d", res_cnt); resource = (struct acpi_resource *)buffer->pointer; - status = acpi_walk_resources(handle, METHOD_NAME__CRS, + status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_type_resources, &resource); if (ACPI_FAILURE(status)) { kfree(buffer->pointer); @@ -636,54 +726,54 @@ int pnpacpi_build_resource_template(acpi_handle handle, return -EINVAL; } /* resource will pointer the end resource now */ - resource->id = ACPI_RSTYPE_END_TAG; + resource->type = ACPI_RESOURCE_TYPE_END_TAG; return 0; } -static void pnpacpi_encode_irq(struct acpi_resource *resource, +static void pnpacpi_encode_irq(struct acpi_resource *resource, struct resource *p) { - int edge_level, active_high_low; + int triggering, polarity; - decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, - &active_high_low); - resource->id = ACPI_RSTYPE_IRQ; + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, + &polarity); + resource->type = ACPI_RESOURCE_TYPE_IRQ; resource->length = sizeof(struct acpi_resource); - resource->data.irq.edge_level = edge_level; - resource->data.irq.active_high_low = active_high_low; - if (edge_level == ACPI_EDGE_SENSITIVE) - resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE; + resource->data.irq.triggering = triggering; + resource->data.irq.polarity = polarity; + if (triggering == ACPI_EDGE_SENSITIVE) + resource->data.irq.sharable = ACPI_EXCLUSIVE; else - resource->data.irq.shared_exclusive = ACPI_SHARED; - resource->data.irq.number_of_interrupts = 1; + resource->data.irq.sharable = ACPI_SHARED; + resource->data.irq.interrupt_count = 1; resource->data.irq.interrupts[0] = p->start; } static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, struct resource *p) { - int edge_level, active_high_low; + int triggering, polarity; - decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, - &active_high_low); - resource->id = ACPI_RSTYPE_EXT_IRQ; + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, + &polarity); + resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; resource->length = sizeof(struct acpi_resource); resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; - resource->data.extended_irq.edge_level = edge_level; - resource->data.extended_irq.active_high_low = active_high_low; - if (edge_level == ACPI_EDGE_SENSITIVE) - resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE; + resource->data.extended_irq.triggering = triggering; + resource->data.extended_irq.polarity = polarity; + if (triggering == ACPI_EDGE_SENSITIVE) + resource->data.irq.sharable = ACPI_EXCLUSIVE; else - resource->data.irq.shared_exclusive = ACPI_SHARED; - resource->data.extended_irq.number_of_interrupts = 1; + resource->data.irq.sharable = ACPI_SHARED; + resource->data.extended_irq.interrupt_count = 1; resource->data.extended_irq.interrupts[0] = p->start; } static void pnpacpi_encode_dma(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_DMA; + resource->type = ACPI_RESOURCE_TYPE_DMA; resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ if (p->flags & IORESOURCE_DMA_COMPATIBLE) @@ -701,75 +791,75 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, else if (p->flags & IORESOURCE_DMA_16BIT) resource->data.dma.transfer = ACPI_TRANSFER_16; resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; - resource->data.dma.number_of_channels = 1; + resource->data.dma.channel_count = 1; resource->data.dma.channels[0] = p->start; } static void pnpacpi_encode_io(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_IO; + resource->type = ACPI_RESOURCE_TYPE_IO; resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? - ACPI_DECODE_16 : ACPI_DECODE_10; - resource->data.io.min_base_address = p->start; - resource->data.io.max_base_address = p->end; + ACPI_DECODE_16 : ACPI_DECODE_10; + resource->data.io.minimum = p->start; + resource->data.io.maximum = p->end; resource->data.io.alignment = 0; /* Correct? */ - resource->data.io.range_length = p->end - p->start + 1; + resource->data.io.address_length = p->end - p->start + 1; } static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_FIXED_IO; + resource->type = ACPI_RESOURCE_TYPE_FIXED_IO; resource->length = sizeof(struct acpi_resource); - resource->data.fixed_io.base_address = p->start; - resource->data.fixed_io.range_length = p->end - p->start + 1; + resource->data.fixed_io.address = p->start; + resource->data.fixed_io.address_length = p->end - p->start + 1; } static void pnpacpi_encode_mem24(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_MEM24; + resource->type = ACPI_RESOURCE_TYPE_MEMORY24; resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ - resource->data.memory24.read_write_attribute = + resource->data.memory24.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.memory24.min_base_address = p->start; - resource->data.memory24.max_base_address = p->end; + resource->data.memory24.minimum = p->start; + resource->data.memory24.maximum = p->end; resource->data.memory24.alignment = 0; - resource->data.memory24.range_length = p->end - p->start + 1; + resource->data.memory24.address_length = p->end - p->start + 1; } static void pnpacpi_encode_mem32(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_MEM32; + resource->type = ACPI_RESOURCE_TYPE_MEMORY32; resource->length = sizeof(struct acpi_resource); - resource->data.memory32.read_write_attribute = + resource->data.memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.memory32.min_base_address = p->start; - resource->data.memory32.max_base_address = p->end; + resource->data.memory32.minimum = p->start; + resource->data.memory32.maximum = p->end; resource->data.memory32.alignment = 0; - resource->data.memory32.range_length = p->end - p->start + 1; + resource->data.memory32.address_length = p->end - p->start + 1; } static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, struct resource *p) { - resource->id = ACPI_RSTYPE_FIXED_MEM32; + resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32; resource->length = sizeof(struct acpi_resource); - resource->data.fixed_memory32.read_write_attribute = + resource->data.fixed_memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; - resource->data.fixed_memory32.range_base_address = p->start; - resource->data.fixed_memory32.range_length = p->end - p->start + 1; + resource->data.fixed_memory32.address = p->start; + resource->data.fixed_memory32.address_length = p->end - p->start + 1; } -int pnpacpi_encode_resources(struct pnp_resource_table *res_table, +int pnpacpi_encode_resources(struct pnp_resource_table *res_table, struct acpi_buffer *buffer) { int i = 0; @@ -780,58 +870,67 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, pnp_dbg("res cnt %d", res_cnt); while (i < res_cnt) { - switch(resource->id) { - case ACPI_RSTYPE_IRQ: + switch(resource->type) { + case ACPI_RESOURCE_TYPE_IRQ: pnp_dbg("Encode irq"); - pnpacpi_encode_irq(resource, + pnpacpi_encode_irq(resource, &res_table->irq_resource[irq]); irq++; break; - case ACPI_RSTYPE_EXT_IRQ: - pnp_dbg("Encode ext irq"); - pnpacpi_encode_ext_irq(resource, - &res_table->irq_resource[irq]); - irq++; - break; - case ACPI_RSTYPE_DMA: + case ACPI_RESOURCE_TYPE_DMA: pnp_dbg("Encode dma"); - pnpacpi_encode_dma(resource, + pnpacpi_encode_dma(resource, &res_table->dma_resource[dma]); dma ++; break; - case ACPI_RSTYPE_IO: + case ACPI_RESOURCE_TYPE_IO: pnp_dbg("Encode io"); - pnpacpi_encode_io(resource, + pnpacpi_encode_io(resource, &res_table->port_resource[port]); port ++; break; - case ACPI_RSTYPE_FIXED_IO: + case ACPI_RESOURCE_TYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, &res_table->port_resource[port]); port ++; break; - case ACPI_RSTYPE_MEM24: + case ACPI_RESOURCE_TYPE_MEMORY24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, &res_table->mem_resource[mem]); mem ++; break; - case ACPI_RSTYPE_MEM32: + case ACPI_RESOURCE_TYPE_MEMORY32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, &res_table->mem_resource[mem]); mem ++; break; - case ACPI_RSTYPE_FIXED_MEM32: + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, &res_table->mem_resource[mem]); mem ++; break; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + pnp_dbg("Encode ext irq"); + pnpacpi_encode_ext_irq(resource, + &res_table->irq_resource[irq]); + irq++; + break; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + case ACPI_RESOURCE_TYPE_VENDOR: + case ACPI_RESOURCE_TYPE_END_TAG: + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: /* other type */ - pnp_warn("unknown resource type %d", resource->id); + pnp_warn("unknown resource type %d", resource->type); return -EINVAL; } resource ++; diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index a86a650f3d6d..721787cc5a1c 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig @@ -51,6 +51,13 @@ config UNIX98_PTY_COUNT When not in use, each additional set of 256 PTYs occupy approximately 8 KB of kernel memory on 32-bit architectures. +config HANGCHECK_TIMER + tristate "Hangcheck timer" + help + The hangcheck-timer module detects when the system has gone + out to lunch past a certain margin. It can reboot the system + or merely print a warning. + source "drivers/char/watchdog/Kconfig" comment "S/390 character device drivers" diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 6f50cc9323d9..6912399d0937 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -55,13 +55,21 @@ config DASD_DIAG Disks under VM. If you are not running under VM or unsure what it is, say "N". +config DASD_EER + tristate "Extended error reporting (EER)" + depends on DASD + help + This driver provides a character device interface to the + DASD extended error reporting. This is only needed if you want to + use applications written for the EER facility. + config DASD_CMB tristate "Compatibility interface for DASD channel measurement blocks" depends on DASD help - This driver provides an additional interface to the channel measurement - facility, which is normally accessed though sysfs, with a set of - ioctl functions specific to the dasd driver. + This driver provides an additional interface to the channel + measurement facility, which is normally accessed though sysfs, with + a set of ioctl functions specific to the dasd driver. This is only needed if you want to use applications written for linux-2.4 dasd channel measurement facility interface. diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 58c6780134f7..0c0d871e8f51 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile @@ -5,6 +5,7 @@ dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o dasd_diag_mod-objs := dasd_diag.o +dasd_eer_mod-objs := dasd_eer.o dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ dasd_genhd.o dasd_erp.o @@ -13,5 +14,6 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o obj-$(CONFIG_DASD_CMB) += dasd_cmb.o +obj-$(CONFIG_DASD_EER) += dasd_eer.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o obj-$(CONFIG_DCSSBLK) += dcssblk.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index ef4c687e7c01..08c88fcd8963 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.172 $ */ #include <linux/config.h> @@ -19,6 +18,7 @@ #include <linux/slab.h> #include <linux/buffer_head.h> #include <linux/hdreg.h> +#include <linux/notifier.h> #include <asm/ccwdev.h> #include <asm/ebcdic.h> @@ -58,6 +58,7 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static void dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(void *data); +static void dasd_disable_eer(struct dasd_device *device); /* * SECTION: Operations on the device structure. @@ -152,6 +153,8 @@ dasd_state_new_to_known(struct dasd_device *device) static inline void dasd_state_known_to_new(struct dasd_device * device) { + /* disable extended error reporting for this device */ + dasd_disable_eer(device); /* Forget the discipline information. */ device->discipline = NULL; device->state = DASD_STATE_NEW; @@ -675,11 +678,8 @@ dasd_term_IO(struct dasd_ccw_req * cqr) rc = ccw_device_clear(device->cdev, (long) cqr); switch (rc) { case 0: /* termination successful */ - if (cqr->retries > 0) { - cqr->retries--; - cqr->status = DASD_CQR_CLEAR; - } else - cqr->status = DASD_CQR_FAILED; + cqr->retries--; + cqr->status = DASD_CQR_CLEAR; cqr->stopclk = get_clock(); DBF_DEV_EVENT(DBF_DEBUG, device, "terminate cqr %p successful", @@ -871,6 +871,9 @@ dasd_handle_state_change_pending(struct dasd_device *device) struct dasd_ccw_req *cqr; struct list_head *l, *n; + /* first of all call extended error reporting */ + dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL); + device->stopped &= ~DASD_STOPPED_PENDING; /* restart all 'running' IO on queue */ @@ -1090,6 +1093,19 @@ restart: } goto restart; } + + /* first of all call extended error reporting */ + if (device->eer && cqr->status == DASD_CQR_FAILED) { + dasd_write_eer_trigger(DASD_EER_FATALERROR, + device, cqr); + + /* restart request */ + cqr->status = DASD_CQR_QUEUED; + cqr->retries = 255; + device->stopped |= DASD_STOPPED_QUIESCE; + goto restart; + } + /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); @@ -1227,7 +1243,8 @@ __dasd_start_head(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); /* check FAILFAST */ if (device->stopped & ~DASD_STOPPED_PENDING && - test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && + (!device->eer)) { cqr->status = DASD_CQR_FAILED; dasd_schedule_bh(device); } @@ -1308,7 +1325,7 @@ dasd_tasklet(struct dasd_device * device) /* Now call the callback function of requests with final status */ list_for_each_safe(l, n, &final_queue) { cqr = list_entry(l, struct dasd_ccw_req, list); - list_del(&cqr->list); + list_del_init(&cqr->list); if (cqr->callback != NULL) (cqr->callback)(cqr, cqr->callback_data); } @@ -1393,7 +1410,9 @@ _wait_for_wakeup(struct dasd_ccw_req *cqr) device = cqr->device; spin_lock_irq(get_ccwdev_lock(device->cdev)); - rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED; + rc = ((cqr->status == DASD_CQR_DONE || + cqr->status == DASD_CQR_FAILED) && + list_empty(&cqr->list)); spin_unlock_irq(get_ccwdev_lock(device->cdev)); return rc; } @@ -1457,15 +1476,37 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr) while (!finished) { rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr)); if (rc != -ERESTARTSYS) { - /* Request status is either done or failed. */ - rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; + /* Request is final (done or failed) */ + rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; break; } spin_lock_irq(get_ccwdev_lock(device->cdev)); - if (cqr->status == DASD_CQR_IN_IO && - device->discipline->term_IO(cqr) == 0) { - list_del(&cqr->list); + switch (cqr->status) { + case DASD_CQR_IN_IO: + /* terminate runnig cqr */ + if (device->discipline->term_IO) { + cqr->retries = -1; + device->discipline->term_IO(cqr); + /*nished = + * wait (non-interruptible) for final status + * because signal ist still pending + */ + spin_unlock_irq(get_ccwdev_lock(device->cdev)); + wait_event(wait_q, _wait_for_wakeup(cqr)); + spin_lock_irq(get_ccwdev_lock(device->cdev)); + rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; + finished = 1; + } + break; + case DASD_CQR_QUEUED: + /* request */ + list_del_init(&cqr->list); + rc = -EIO; finished = 1; + break; + default: + /* cqr with 'non-interruptable' status - just wait */ + break; } spin_unlock_irq(get_ccwdev_lock(device->cdev)); } @@ -1945,6 +1986,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: case CIO_NO_PATH: + /* first of all call extended error reporting */ + dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL); + if (device->state < DASD_STATE_BASIC) break; /* Device is active. We want to keep it. */ @@ -2002,6 +2046,51 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) put_driver(drv); } +/* + * notifications for extended error reports + */ +static struct notifier_block *dasd_eer_chain; + +int +dasd_register_eer_notifier(struct notifier_block *nb) +{ + return notifier_chain_register(&dasd_eer_chain, nb); +} + +int +dasd_unregister_eer_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&dasd_eer_chain, nb); +} + +/* + * Notify the registered error reporting module of a problem + */ +void +dasd_write_eer_trigger(unsigned int id, struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + if (device->eer) { + struct dasd_eer_trigger temp; + temp.id = id; + temp.device = device; + temp.cqr = cqr; + notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER, + (void *)&temp); + } +} + +/* + * Tell the registered error reporting module to disable error reporting for + * a given device and to cleanup any private data structures on that device. + */ +static void +dasd_disable_eer(struct dasd_device *device) +{ + notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device); +} + + static int __init dasd_init(void) { @@ -2083,6 +2172,11 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); EXPORT_SYMBOL_GPL(dasd_generic_auto_online); +EXPORT_SYMBOL(dasd_register_eer_notifier); +EXPORT_SYMBOL(dasd_unregister_eer_notifier); +EXPORT_SYMBOL(dasd_write_eer_trigger); + + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c index 84565c8f584e..1d11c2a9525d 100644 --- a/drivers/s390/block/dasd_3370_erp.c +++ b/drivers/s390/block/dasd_3370_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.9 $ */ #define PRINTK_HEADER "dasd_erp(3370)" diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c143ecb53d9d..c811380b9079 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -5,7 +5,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.36 $ */ #include <linux/timer.h> @@ -1109,6 +1108,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x0B: DEV_MESSAGE(KERN_WARNING, device, "%s", "FORMAT F - Volume is suspended duplex"); + /* call extended error reporting (EER) */ + dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device, + erp->refers); break; case 0x0C: DEV_MESSAGE(KERN_WARNING, device, "%s", diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c index 01e87170a3a2..dc861446d056 100644 --- a/drivers/s390/block/dasd_9336_erp.c +++ b/drivers/s390/block/dasd_9336_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.8 $ */ #define PRINTK_HEADER "dasd_erp(9336)" diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c index 2a23b74faf3f..4a5b79569aaa 100644 --- a/drivers/s390/block/dasd_9343_erp.c +++ b/drivers/s390/block/dasd_9343_erp.c @@ -4,7 +4,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 * - * $Revision: 1.13 $ */ #define PRINTK_HEADER "dasd_erp(9343)" diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c index 4f365bff275c..e88f73ee72ce 100644 --- a/drivers/s390/block/dasd_cmb.c +++ b/drivers/s390/block/dasd_cmb.c @@ -1,6 +1,4 @@ /* - * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $) - * * Linux on zSeries Channel Measurement Facility support * (dasd device driver interface) * diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index caee16a3dc62..1629b27c48ab 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -11,7 +11,6 @@ * functions may not be called from interrupt context. In particular * dasd_get_device is a no-no from interrupt context. * - * $Revision: 1.43 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index ba80fdea7ebf..3f9d704d2657 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,7 +6,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.53 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index a4f80bd735f1..38a4e55f8953 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -6,7 +6,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.9 $ */ #define MDSK_WRITE_REQ 0x01 diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 96eb48258580..822e2a265578 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -7,7 +7,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.74 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index b6888c68b224..e15dd7978050 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -5,7 +5,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.10 $ */ #ifndef DASD_ECKD_H @@ -30,6 +29,7 @@ #define DASD_ECKD_CCW_PSF 0x27 #define DASD_ECKD_CCW_RSSD 0x3e #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 +#define DASD_ECKD_CCW_SNSS 0x54 #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 #define DASD_ECKD_CCW_WRITE_MT 0x85 #define DASD_ECKD_CCW_READ_MT 0x86 diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c new file mode 100644 index 000000000000..f70cd7716b24 --- /dev/null +++ b/drivers/s390/block/dasd_eer.c @@ -0,0 +1,1090 @@ +/* + * character device driver for extended error reporting + * + * + * Copyright (C) 2005 IBM Corporation + * extended error reporting for DASD ECKD devices + * Author(s): Stefan Weinhuber <wein@de.ibm.com> + * + */ + +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/device.h> +#include <linux/workqueue.h> +#include <linux/poll.h> +#include <linux/notifier.h> + +#include <asm/uaccess.h> +#include <asm/semaphore.h> +#include <asm/atomic.h> +#include <asm/ebcdic.h> + +#include "dasd_int.h" +#include "dasd_eckd.h" + + +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>"); +MODULE_DESCRIPTION("DASD extended error reporting module"); + + +#ifdef PRINTK_HEADER +#undef PRINTK_HEADER +#endif /* PRINTK_HEADER */ +#define PRINTK_HEADER "dasd(eer):" + + + + + +/*****************************************************************************/ +/* the internal buffer */ +/*****************************************************************************/ + +/* + * The internal buffer is meant to store obaque blobs of data, so it doesn't + * know of higher level concepts like triggers. + * It consists of a number of pages that are used as a ringbuffer. Each data + * blob is stored in a simple record that consists of an integer, which + * contains the size of the following data, and the data bytes themselfes. + * + * To allow for multiple independent readers we create one internal buffer + * each time the device is opened and destroy the buffer when the file is + * closed again. + * + * One record can be written to a buffer by using the functions + * - dasd_eer_start_record (one time per record to write the size to the buffer + * and reserve the space for the data) + * - dasd_eer_write_buffer (one or more times per record to write the data) + * The data can be written in several steps but you will have to compute + * the total size up front for the invocation of dasd_eer_start_record. + * If the ringbuffer is full, dasd_eer_start_record will remove the required + * number of old records. + * + * A record is typically read in two steps, first read the integer that + * specifies the size of the following data, then read the data. + * Both can be done by + * - dasd_eer_read_buffer + * + * For all mentioned functions you need to get the bufferlock first and keep it + * until a complete record is written or read. + */ + + +/* + * Alle information necessary to keep track of an internal buffer is kept in + * a struct eerbuffer. The buffer specific to a file pointer is strored in + * the private_data field of that file. To be able to write data to all + * existing buffers, each buffer is also added to the bufferlist. + * If the user doesn't want to read a complete record in one go, we have to + * keep track of the rest of the record. residual stores the number of bytes + * that are still to deliver. If the rest of the record is invalidated between + * two reads then residual will be set to -1 so that the next read will fail. + * All entries in the eerbuffer structure are protected with the bufferlock. + * To avoid races between writing to a buffer on the one side and creating + * and destroying buffers on the other side, the bufferlock must also be used + * to protect the bufferlist. + */ + +struct eerbuffer { + struct list_head list; + char **buffer; + int buffersize; + int buffer_page_count; + int head; + int tail; + int residual; +}; + +LIST_HEAD(bufferlist); + +static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED; + +DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue); + +/* + * How many free bytes are available on the buffer. + * needs to be called with bufferlock held + */ +static int +dasd_eer_get_free_bytes(struct eerbuffer *eerb) +{ + if (eerb->head < eerb->tail) { + return eerb->tail - eerb->head - 1; + } else + return eerb->buffersize - eerb->head + eerb->tail -1; +} + +/* + * How many bytes of buffer space are used. + * needs to be called with bufferlock held + */ +static int +dasd_eer_get_filled_bytes(struct eerbuffer *eerb) +{ + + if (eerb->head >= eerb->tail) { + return eerb->head - eerb->tail; + } else + return eerb->buffersize - eerb->tail + eerb->head; +} + +/* + * The dasd_eer_write_buffer function just copies count bytes of data + * to the buffer. Make sure to call dasd_eer_start_record first, to + * make sure that enough free space is available. + * needs to be called with bufferlock held + */ +static void +dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data) +{ + + unsigned long headindex,localhead; + unsigned long rest, len; + char *nextdata; + + nextdata = data; + rest = count; + while (rest > 0) { + headindex = eerb->head / PAGE_SIZE; + localhead = eerb->head % PAGE_SIZE; + len = min(rest, (PAGE_SIZE - localhead)); + memcpy(eerb->buffer[headindex]+localhead, nextdata, len); + nextdata += len; + rest -= len; + eerb->head += len; + if ( eerb->head == eerb->buffersize ) + eerb->head = 0; /* wrap around */ + if (eerb->head > eerb->buffersize) { + MESSAGE(KERN_ERR, "%s", "runaway buffer head."); + BUG(); + } + } +} + +/* + * needs to be called with bufferlock held + */ +static int +dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data) +{ + + unsigned long tailindex,localtail; + unsigned long rest, len, finalcount; + char *nextdata; + + finalcount = min(count, dasd_eer_get_filled_bytes(eerb)); + nextdata = data; + rest = finalcount; + while (rest > 0) { + tailindex = eerb->tail / PAGE_SIZE; + localtail = eerb->tail % PAGE_SIZE; + len = min(rest, (PAGE_SIZE - localtail)); + memcpy(nextdata, eerb->buffer[tailindex]+localtail, len); + nextdata += len; + rest -= len; + eerb->tail += len; + if ( eerb->tail == eerb->buffersize ) + eerb->tail = 0; /* wrap around */ + if (eerb->tail > eerb->buffersize) { + MESSAGE(KERN_ERR, "%s", "runaway buffer tail."); + BUG(); + } + } + return finalcount; +} + +/* + * Whenever you want to write a blob of data to the internal buffer you + * have to start by using this function first. It will write the number + * of bytes that will be written to the buffer. If necessary it will remove + * old records to make room for the new one. + * needs to be called with bufferlock held + */ +static int +dasd_eer_start_record(struct eerbuffer *eerb, int count) +{ + int tailcount; + if (count + sizeof(count) > eerb->buffersize) + return -ENOMEM; + while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) { + if (eerb->residual > 0) { + eerb->tail += eerb->residual; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + eerb->residual = -1; + } + dasd_eer_read_buffer(eerb, sizeof(tailcount), + (char*)(&tailcount)); + eerb->tail += tailcount; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + } + dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count)); + + return 0; +}; + +/* + * release pages that are not used anymore + */ +static void +dasd_eer_free_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; ++i) { + free_page((unsigned long)buf[i]); + } +} + +/* + * allocate a new set of memory pages + */ +static int +dasd_eer_allocate_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; ++i) { + buf[i] = (char *) get_zeroed_page(GFP_KERNEL); + if (!buf[i]) { + dasd_eer_free_buffer_pages(buf, i); + return -ENOMEM; + } + } + return 0; +} + +/* + * empty the buffer by resetting head and tail + * In case there is a half read data blob in the buffer, we set residual + * to -1 to indicate that the remainder of the blob is lost. + */ +static void +dasd_eer_purge_buffer(struct eerbuffer *eerb) +{ + unsigned long flags; + + spin_lock_irqsave(&bufferlock, flags); + if (eerb->residual > 0) + eerb->residual = -1; + eerb->tail=0; + eerb->head=0; + spin_unlock_irqrestore(&bufferlock, flags); +} + +/* + * set the size of the buffer, newsize is the new number of pages to be used + * we don't try to copy any data back an forth, so any resize will also purge + * the buffer + */ +static int +dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize) +{ + int i, oldcount, reuse; + char **new; + char **old; + unsigned long flags; + + if (newsize < 1) + return -EINVAL; + if (eerb->buffer_page_count == newsize) { + /* documented behaviour is that any successfull invocation + * will purge all records */ + dasd_eer_purge_buffer(eerb); + return 0; + } + new = kmalloc(newsize*sizeof(char*), GFP_KERNEL); + if (!new) + return -ENOMEM; + + reuse=min(eerb->buffer_page_count, newsize); + for (i = 0; i < reuse; ++i) { + new[i] = eerb->buffer[i]; + } + if (eerb->buffer_page_count < newsize) { + if (dasd_eer_allocate_buffer_pages( + &new[eerb->buffer_page_count], + newsize - eerb->buffer_page_count)) { + kfree(new); + return -ENOMEM; + } + } + + spin_lock_irqsave(&bufferlock, flags); + old = eerb->buffer; + eerb->buffer = new; + if (eerb->residual > 0) + eerb->residual = -1; + eerb->tail = 0; + eerb->head = 0; + oldcount = eerb->buffer_page_count; + eerb->buffer_page_count = newsize; + spin_unlock_irqrestore(&bufferlock, flags); + + if (oldcount > newsize) { + for (i = newsize; i < oldcount; ++i) { + free_page((unsigned long)old[i]); + } + } + kfree(old); + + return 0; +} + + +/*****************************************************************************/ +/* The extended error reporting functionality */ +/*****************************************************************************/ + +/* + * When a DASD device driver wants to report an error, it calls the + * function dasd_eer_write_trigger (via a notifier mechanism) and gives the + * respective trigger ID as parameter. + * Currently there are four kinds of triggers: + * + * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems + * DASD_EER_PPRCSUSPEND: PPRC was suspended + * DASD_EER_NOPATH: There is no path to the device left. + * DASD_EER_STATECHANGE: The state of the device has changed. + * + * For the first three triggers all required information can be supplied by + * the caller. For these triggers a record is written by the function + * dasd_eer_write_standard_trigger. + * + * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE + * trigger, we have to gather the necessary sense data first. We cannot queue + * the necessary SNSS (sense subsystem status) request immediatly, since we + * are likely to run in a deadlock situation. Instead, we schedule a + * work_struct that calls the function dasd_eer_sense_subsystem_status to + * create and start an SNSS request asynchronously. + * + * To avoid memory allocations at runtime, the necessary memory is allocated + * when the extended error reporting is enabled for a device (by + * dasd_eer_probe). There is one private eer data structure for each eer + * enabled DASD device. It contains memory for the work_struct, one SNSS cqr + * and a flags field that is used to coordinate the use of the cqr. The call + * to write a state change trigger can come in at any time, so we have one flag + * CQR_IN_USE that protects the cqr itself. When this flag indicates that the + * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a + * second request but sets the SNSS_REQUESTED flag instead. + * + * When the request is finished, the callback function dasd_eer_SNSS_cb + * is called. This function will invoke the function + * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also + * check the SNSS_REQUESTED flag and if it is set it will call + * dasd_eer_sense_subsystem_status again. + * + * To avoid race conditions during the handling of the lock, the flags must + * be protected by the snsslock. + */ + +struct dasd_eer_private { + struct dasd_ccw_req *cqr; + unsigned long flags; + struct work_struct worker; +}; + +static void dasd_eer_destroy(struct dasd_device *device, + struct dasd_eer_private *eer); +static int +dasd_eer_write_trigger(struct dasd_eer_trigger *trigger); +static void dasd_eer_sense_subsystem_status(void *data); +static int dasd_eer_notify(struct notifier_block *self, + unsigned long action, void *data); + +struct workqueue_struct *dasd_eer_workqueue; + +#define SNSS_DATA_SIZE 44 +static spinlock_t snsslock = SPIN_LOCK_UNLOCKED; + +#define DASD_EER_BUSID_SIZE 10 +struct dasd_eer_header { + __u32 total_size; + __u32 trigger; + __u64 tv_sec; + __u64 tv_usec; + char busid[DASD_EER_BUSID_SIZE]; +} __attribute__ ((packed)); + +static struct notifier_block dasd_eer_nb = { + .notifier_call = dasd_eer_notify, +}; + +/* + * flags for use with dasd_eer_private + */ +#define CQR_IN_USE 0 +#define SNSS_REQUESTED 1 + +/* + * This function checks if extended error reporting is available for a given + * dasd_device. If yes, then it creates and returns a struct dasd_eer, + * otherwise it returns an -EPERM error pointer. + */ +struct dasd_eer_private * +dasd_eer_probe(struct dasd_device *device) +{ + struct dasd_eer_private *private; + + if (!(device && device->discipline + && !strcmp(device->discipline->name, "ECKD"))) { + return ERR_PTR(-EPERM); + } + /* allocate the private data structure */ + private = (struct dasd_eer_private *)kmalloc( + sizeof(struct dasd_eer_private), GFP_KERNEL); + if (!private) { + return ERR_PTR(-ENOMEM); + } + INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status, + (void *)device); + private->cqr = dasd_kmalloc_request("ECKD", + 1 /* SNSS */ , + SNSS_DATA_SIZE , + device); + if (!private->cqr) { + kfree(private); + return ERR_PTR(-ENOMEM); + } + private->flags = 0; + return private; +}; + +/* + * If our private SNSS request is queued, remove it from the + * dasd ccw queue so we can free the requests memory. + */ +static void +dasd_eer_dequeue_SNSS_request(struct dasd_device *device, + struct dasd_eer_private *eer) +{ + struct list_head *lst, *nxt; + struct dasd_ccw_req *cqr, *erpcqr; + dasd_erp_fn_t erp_fn; + + spin_lock_irq(get_ccwdev_lock(device->cdev)); + list_for_each_safe(lst, nxt, &device->ccw_queue) { + cqr = list_entry(lst, struct dasd_ccw_req, list); + /* we are looking for two kinds or requests */ + /* first kind: our SNSS request: */ + if (cqr == eer->cqr) { + if (cqr->status == DASD_CQR_IN_IO) + device->discipline->term_IO(cqr); + list_del(&cqr->list); + break; + } + /* second kind: ERP requests for our SNSS request */ + if (cqr->refers) { + /* If this erp request chain ends in our cqr, then */ + /* cal the erp_postaction to clean it up */ + erpcqr = cqr; + while (erpcqr->refers) { + erpcqr = erpcqr->refers; + } + if (erpcqr == eer->cqr) { + erp_fn = device->discipline->erp_postaction( + cqr); + erp_fn(cqr); + } + continue; + } + } + spin_unlock_irq(get_ccwdev_lock(device->cdev)); +} + +/* + * This function dismantles a struct dasd_eer that was created by + * dasd_eer_probe. Since we want to free our private data structure, + * we must make sure that the memory is not in use anymore. + * We have to flush the work queue and remove a possible SNSS request + * from the dasd queue. + */ +static void +dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer) +{ + flush_workqueue(dasd_eer_workqueue); + dasd_eer_dequeue_SNSS_request(device, eer); + dasd_kfree_request(eer->cqr, device); + kfree(eer); +}; + +/* + * enable the extended error reporting for a particular device + */ +static int +dasd_eer_enable_on_device(struct dasd_device *device) +{ + void *eer; + if (!device) + return -ENODEV; + if (device->eer) + return 0; + if (!try_module_get(THIS_MODULE)) { + return -EINVAL; + } + eer = (void *)dasd_eer_probe(device); + if (IS_ERR(eer)) { + module_put(THIS_MODULE); + return PTR_ERR(eer); + } + device->eer = eer; + return 0; +} + +/* + * enable the extended error reporting for a particular device + */ +static int +dasd_eer_disable_on_device(struct dasd_device *device) +{ + struct dasd_eer_private *eer = device->eer; + + if (!device) + return -ENODEV; + if (!device->eer) + return 0; + device->eer = NULL; + dasd_eer_destroy(device,eer); + module_put(THIS_MODULE); + + return 0; +} + +/* + * Set extended error reporting (eer) + * Note: This will be registered as a DASD ioctl, to be called on DASD devices. + */ +static int +dasd_ioctl_set_eer(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + int intval; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (bdev != bdev->bd_contains) + /* Error-reporting is not allowed for partitions */ + return -EINVAL; + if (get_user(intval, (int __user *) args)) + return -EFAULT; + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + + intval = (intval != 0); + DEV_MESSAGE (KERN_DEBUG, device, + "set eer on device to %d", intval); + if (intval) + return dasd_eer_enable_on_device(device); + else + return dasd_eer_disable_on_device(device); +} + +/* + * Get value of extended error reporting. + * Note: This will be registered as a DASD ioctl, to be called on DASD devices. + */ +static int +dasd_ioctl_get_eer(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + return put_user((device->eer != NULL), (int __user *) args); +} + +/* + * The following function can be used for those triggers that have + * all necessary data available when the function is called. + * If the parameter cqr is not NULL, the chain of requests will be searched + * for valid sense data, and all valid sense data sets will be added to + * the triggers data. + */ +static int +dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + struct dasd_ccw_req *temp_cqr; + int data_size; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + /* go through cqr chain and count the valid sense data sets */ + temp_cqr = cqr; + data_size = 0; + while (temp_cqr) { + if (temp_cqr->irb.esw.esw0.erw.cons) + data_size += 32; + temp_cqr = temp_cqr->refers; + } + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = trigger; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header)); + temp_cqr = cqr; + while (temp_cqr) { + if (temp_cqr->irb.esw.esw0.erw.cons) + dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw); + temp_cqr = temp_cqr->refers; + } + dasd_eer_write_buffer(eerb, 4,"EOR"); + } + spin_unlock_irqrestore(&bufferlock, flags); + + wake_up_interruptible(&dasd_eer_read_wait_queue); + + return 0; +} + +/* + * This function writes a DASD_EER_STATECHANGE trigger. + */ +static void +dasd_eer_write_SNSS_trigger(struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + int data_size; + int snss_rc; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; + if (snss_rc) + data_size = 0; + else + data_size = SNSS_DATA_SIZE; + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = DASD_EER_STATECHANGE; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header)); + if (!snss_rc) + dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data); + dasd_eer_write_buffer(eerb, 4,"EOR"); + } + spin_unlock_irqrestore(&bufferlock, flags); + + wake_up_interruptible(&dasd_eer_read_wait_queue); +} + +/* + * callback function for use with SNSS request + */ +static void +dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data) +{ + struct dasd_device *device; + struct dasd_eer_private *private; + unsigned long irqflags; + + device = (struct dasd_device *)data; + private = (struct dasd_eer_private *)device->eer; + dasd_eer_write_SNSS_trigger(device, cqr); + spin_lock_irqsave(&snsslock, irqflags); + if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) { + clear_bit(CQR_IN_USE, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + return; + }; + clear_bit(CQR_IN_USE, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + dasd_eer_sense_subsystem_status(device); + return; +} + +/* + * clean a used cqr before using it again + */ +static void +dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr) +{ + struct ccw1 *cpaddr = cqr->cpaddr; + void *data = cqr->data; + + memset(cqr, 0, sizeof(struct dasd_ccw_req)); + memset(cpaddr, 0, sizeof(struct ccw1)); + memset(data, 0, SNSS_DATA_SIZE); + cqr->cpaddr = cpaddr; + cqr->data = data; + strncpy((char *) &cqr->magic, "ECKD", 4); + ASCEBC((char *) &cqr->magic, 4); + set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); +} + +/* + * build and start an SNSS request + * This function is called from a work queue so we have to + * pass the dasd_device pointer as a void pointer. + */ +static void +dasd_eer_sense_subsystem_status(void *data) +{ + struct dasd_device *device; + struct dasd_eer_private *private; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + unsigned long irqflags; + + device = (struct dasd_device *)data; + private = (struct dasd_eer_private *)device->eer; + if (!private) /* device not eer enabled any more */ + return; + cqr = private->cqr; + spin_lock_irqsave(&snsslock, irqflags); + if(test_and_set_bit(CQR_IN_USE, &private->flags)) { + set_bit(SNSS_REQUESTED, &private->flags); + spin_unlock_irqrestore(&snsslock, irqflags); + return; + }; + spin_unlock_irqrestore(&snsslock, irqflags); + dasd_eer_clean_SNSS_request(cqr); + cqr->device = device; + cqr->retries = 255; + cqr->expires = 10 * HZ; + + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_SNSS; + ccw->count = SNSS_DATA_SIZE; + ccw->flags = 0; + ccw->cda = (__u32)(addr_t)cqr->data; + + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + cqr->callback = dasd_eer_SNSS_cb; + cqr->callback_data = (void *)device; + dasd_add_request_head(cqr); + + return; +} + +/* + * This function is called for all triggers. It calls the appropriate + * function that writes the actual trigger records. + */ +static int +dasd_eer_write_trigger(struct dasd_eer_trigger *trigger) +{ + int rc; + struct dasd_eer_private *private = trigger->device->eer; + + switch (trigger->id) { + case DASD_EER_FATALERROR: + case DASD_EER_PPRCSUSPEND: + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, trigger->cqr); + break; + case DASD_EER_NOPATH: + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, NULL); + break; + case DASD_EER_STATECHANGE: + if (queue_work(dasd_eer_workqueue, &private->worker)) { + rc=0; + } else { + /* If the work_struct was already queued, it can't + * be queued again. But this is OK since we don't + * need to have it queued twice. + */ + rc = -EBUSY; + } + break; + default: /* unknown trigger, so we write it without any sense data */ + rc = dasd_eer_write_standard_trigger( + trigger->id, trigger->device, NULL); + break; + } + return rc; +} + +/* + * This function is registered with the dasd device driver and gets called + * for all dasd eer notifications. + */ +static int dasd_eer_notify(struct notifier_block *self, + unsigned long action, void *data) +{ + switch (action) { + case DASD_EER_DISABLE: + dasd_eer_disable_on_device((struct dasd_device *)data); + break; + case DASD_EER_TRIGGER: + dasd_eer_write_trigger((struct dasd_eer_trigger *)data); + break; + } + return NOTIFY_OK; +} + + +/*****************************************************************************/ +/* the device operations */ +/*****************************************************************************/ + +/* + * On the one side we need a lock to access our internal buffer, on the + * other side a copy_to_user can sleep. So we need to copy the data we have + * to transfer in a readbuffer, which is protected by the readbuffer_mutex. + */ +static char readbuffer[PAGE_SIZE]; +DECLARE_MUTEX(readbuffer_mutex); + + +static int +dasd_eer_open(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL); + eerb->head = 0; + eerb->tail = 0; + eerb->residual = 0; + eerb->buffer_page_count = 1; + eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; + eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*), + GFP_KERNEL); + if (!eerb->buffer) + return -ENOMEM; + if (dasd_eer_allocate_buffer_pages(eerb->buffer, + eerb->buffer_page_count)) { + kfree(eerb->buffer); + return -ENOMEM; + } + filp->private_data = eerb; + spin_lock_irqsave(&bufferlock, flags); + list_add(&eerb->list, &bufferlist); + spin_unlock_irqrestore(&bufferlock, flags); + + return nonseekable_open(inp,filp); +} + +static int +dasd_eer_close(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = (struct eerbuffer *)filp->private_data; + spin_lock_irqsave(&bufferlock, flags); + list_del(&eerb->list); + spin_unlock_irqrestore(&bufferlock, flags); + dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count); + kfree(eerb->buffer); + kfree(eerb); + + return 0; +} + +static long +dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int intval; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + switch (cmd) { + case DASD_EER_PURGE: + dasd_eer_purge_buffer(eerb); + return 0; + case DASD_EER_SETBUFSIZE: + if (get_user(intval, (int __user *)arg)) + return -EFAULT; + return dasd_eer_resize_buffer(eerb, intval); + default: + return -ENOIOCTLCMD; + } +} + +static ssize_t +dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) +{ + int tc,rc; + int tailcount,effective_count; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + if(down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + + spin_lock_irqsave(&bufferlock, flags); + + if (eerb->residual < 0) { /* the remainder of this record */ + /* has been deleted */ + eerb->residual = 0; + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + return -EIO; + } else if (eerb->residual > 0) { + /* OK we still have a second half of a record to deliver */ + effective_count = min(eerb->residual, (int)count); + eerb->residual -= effective_count; + } else { + tc = 0; + while (!tc) { + tc = dasd_eer_read_buffer(eerb, + sizeof(tailcount), (char*)(&tailcount)); + if (!tc) { + /* no data available */ + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + rc = wait_event_interruptible( + dasd_eer_read_wait_queue, + eerb->head != eerb->tail); + if (rc) { + return rc; + } + if(down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + spin_lock_irqsave(&bufferlock, flags); + } + } + WARN_ON(tc != sizeof(tailcount)); + effective_count = min(tailcount,(int)count); + eerb->residual = tailcount - effective_count; + } + + tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer); + WARN_ON(tc != effective_count); + + spin_unlock_irqrestore(&bufferlock, flags); + + if (copy_to_user(buf, readbuffer, effective_count)) { + up(&readbuffer_mutex); + return -EFAULT; + } + + up(&readbuffer_mutex); + return effective_count; +} + +static unsigned int +dasd_eer_poll (struct file *filp, poll_table *ptable) +{ + unsigned int mask; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *)filp->private_data; + poll_wait(filp, &dasd_eer_read_wait_queue, ptable); + spin_lock_irqsave(&bufferlock, flags); + if (eerb->head != eerb->tail) + mask = POLLIN | POLLRDNORM ; + else + mask = 0; + spin_unlock_irqrestore(&bufferlock, flags); + return mask; +} + +static struct file_operations dasd_eer_fops = { + .open = &dasd_eer_open, + .release = &dasd_eer_close, + .unlocked_ioctl = &dasd_eer_ioctl, + .compat_ioctl = &dasd_eer_ioctl, + .read = &dasd_eer_read, + .poll = &dasd_eer_poll, + .owner = THIS_MODULE, +}; + +static struct miscdevice dasd_eer_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dasd_eer", + .fops = &dasd_eer_fops, +}; + + +/*****************************************************************************/ +/* Init and exit */ +/*****************************************************************************/ + +static int +__init dasd_eer_init(void) +{ + int rc; + + dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer"); + if (!dasd_eer_workqueue) { + MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not " + "create workqueue \n"); + rc = -ENOMEM; + goto out; + } + + rc = dasd_register_eer_notifier(&dasd_eer_nb); + if (rc) { + MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + "register error reporting"); + goto queue; + } + + dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer); + dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer); + + /* we don't need our own character device, + * so we just register as misc device */ + rc = misc_register(&dasd_eer_dev); + if (rc) { + MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + "register misc device"); + goto unregister; + } + + return 0; + +unregister: + dasd_unregister_eer_notifier(&dasd_eer_nb); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, + dasd_ioctl_set_eer); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, + dasd_ioctl_get_eer); +queue: + destroy_workqueue(dasd_eer_workqueue); +out: + return rc; + +} +module_init(dasd_eer_init); + +static void +__exit dasd_eer_exit(void) +{ + dasd_unregister_eer_notifier(&dasd_eer_nb); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, + dasd_ioctl_set_eer); + dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, + dasd_ioctl_get_eer); + destroy_workqueue(dasd_eer_workqueue); + + WARN_ON(misc_deregister(&dasd_eer_dev) != 0); +} +module_exit(dasd_eer_exit); diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 7cb98d25f341..8fd71ab02ef0 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -7,7 +7,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.14 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 8ec75dc08e2c..91145698f8e9 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -4,7 +4,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.41 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h index 624f0402ee22..da1fa91fc01d 100644 --- a/drivers/s390/block/dasd_fba.h +++ b/drivers/s390/block/dasd_fba.h @@ -4,7 +4,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.6 $ */ #ifndef DASD_FBA_H diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index a601c9a33541..65dc844b975c 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -9,7 +9,6 @@ * * gendisk related functions for the dasd driver. * - * $Revision: 1.51 $ */ #include <linux/config.h> diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index e4b401500b01..d1b08fa13fd2 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.68 $ */ #ifndef DASD_INT_H @@ -276,6 +275,34 @@ struct dasd_discipline { extern struct dasd_discipline *dasd_diag_discipline_pointer; + +/* + * Notification numbers for extended error reporting notifications: + * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's + * eer pointer) is freed. The error reporting module needs to do all necessary + * cleanup steps. + * The DASD_EER_TRIGGER notification sends the actual error reports (triggers). + */ +#define DASD_EER_DISABLE 0 +#define DASD_EER_TRIGGER 1 + +/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */ +#define DASD_EER_FATALERROR 1 +#define DASD_EER_NOPATH 2 +#define DASD_EER_STATECHANGE 3 +#define DASD_EER_PPRCSUSPEND 4 + +/* + * The dasd_eer_trigger structure contains all data that we need to send + * along with an DASD_EER_TRIGGER notification. + */ +struct dasd_eer_trigger { + unsigned int id; + struct dasd_device *device; + struct dasd_ccw_req *cqr; +}; + + struct dasd_device { /* Block device stuff. */ struct gendisk *gdp; @@ -289,6 +316,9 @@ struct dasd_device { unsigned long flags; /* per device flags */ unsigned short features; /* copy of devmap-features (read-only!) */ + /* extended error reporting stuff (eer) */ + void *eer; + /* Device discipline stuff. */ struct dasd_discipline *discipline; char *private; @@ -489,6 +519,12 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); int dasd_generic_set_offline (struct ccw_device *cdev); int dasd_generic_notify(struct ccw_device *, int); void dasd_generic_auto_online (struct ccw_driver *); +int dasd_register_eer_notifier(struct notifier_block *); +int dasd_unregister_eer_notifier(struct notifier_block *); +void dasd_write_eer_trigger(unsigned int , struct dasd_device *, + struct dasd_ccw_req *); + + /* externals in dasd_devmap.c */ extern int dasd_max_devindex; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 9396fcacb8f8..fafeeae52675 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -7,8 +7,6 @@ * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.50 $ - * * i/o controls for the dasd driver. */ #include <linux/config.h> @@ -423,8 +421,15 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) dasd_info->cu_model = cdev->id.cu_model; dasd_info->dev_type = cdev->id.dev_type; dasd_info->dev_model = cdev->id.dev_model; - dasd_info->open_count = atomic_read(&device->open_count); dasd_info->status = device->state; + /* + * The open_count is increased for every opener, that includes + * the blkdev_get in dasd_scan_partitions. + * This must be hidden from user-space. + */ + dasd_info->open_count = atomic_read(&device->open_count); + if (!device->bdev) + dasd_info->open_count++; /* * check if device is really formatted diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index fff9020d4886..2d5da3c75ca7 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -9,7 +9,6 @@ * * /proc interface for the dasd driver. * - * $Revision: 1.33 $ */ #include <linux/config.h> diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 1f060914cfa4..606f6ad285a0 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/interrupt.h> +#include <linux/err.h> #include <linux/slab.h> #include <linux/bootmem.h> @@ -864,7 +865,7 @@ con3215_init(void) } cdev = ccw_device_probe_console(); - if (!cdev) + if (IS_ERR(cdev)) return -ENODEV; raw3215[0] = raw = (struct raw3215_info *) diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index c570a9f6ce9c..ef607a1de55a 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -15,6 +15,7 @@ #include <linux/interrupt.h> #include <linux/list.h> #include <linux/types.h> +#include <linux/err.h> #include <asm/ccwdev.h> #include <asm/cio.h> @@ -597,7 +598,7 @@ con3270_init(void) } cdev = ccw_device_probe_console(); - if (!cdev) + if (IS_ERR(cdev)) return -ENODEV; rp = raw3270_setup_console(cdev); if (IS_ERR(rp)) diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 5bda2340a39d..a317a123daba 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -440,7 +440,11 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, return -EPERM; len = strnlen_user(u_kbs->kb_string, sizeof(u_kbs->kb_string) - 1); - p = kmalloc(len, GFP_KERNEL); + if (!len) + return -EFAULT; + if (len > sizeof(u_kbs->kb_string) - 1) + return -EINVAL; + p = kmalloc(len + 1, GFP_KERNEL); if (!p) return -ENOMEM; if (copy_from_user(p, u_kbs->kb_string, len)) { diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index ceb0e474fde4..4138564402b8 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t { /* Maximum retry counts */ #define SCLP_INIT_RETRY 3 #define SCLP_MASK_RETRY 3 -#define SCLP_REQUEST_RETRY 3 /* Timeout intervals in seconds.*/ -#define SCLP_BUSY_INTERVAL 2 -#define SCLP_RETRY_INTERVAL 5 +#define SCLP_BUSY_INTERVAL 10 +#define SCLP_RETRY_INTERVAL 15 static void sclp_process_queue(void); static int sclp_init_mask(int calculate); @@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; del_timer(&sclp_request_timer); - if (req->start_count <= SCLP_REQUEST_RETRY) { - rc = service_call(req->command, req->sccb); - req->start_count++; - } else - rc = -EIO; + rc = service_call(req->command, req->sccb); + req->start_count++; + if (rc == 0) { /* Sucessfully started request */ req->status = SCLP_REQ_RUNNING; diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 20be88e91fa1..682039cac15b 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1357,7 +1357,7 @@ tape_34xx_init (void) debug_set_level(TAPE_DBF_AREA, 6); #endif - DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n"); + DBF_EVENT(3, "34xx init\n"); /* Register driver for 3480/3490 tapes. */ rc = ccw_driver_register(&tape_34xx_driver); if (rc) @@ -1377,8 +1377,7 @@ tape_34xx_exit(void) MODULE_DEVICE_TABLE(ccw, tape_34xx_ids); MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH"); -MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape " - "device driver ($Revision: 1.23 $)"); +MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape device driver"); MODULE_LICENSE("GPL"); module_init(tape_34xx_init); diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index fcaee447d6fe..b3569c82bb16 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c @@ -1,6 +1,6 @@ /* * (C) Copyright IBM Corp. 2004 - * tape_class.c ($Revision: 1.8 $) + * tape_class.c * * Tape class device support * @@ -12,7 +12,7 @@ MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); MODULE_DESCRIPTION( "(C) Copyright IBM Corp. 2004 All Rights Reserved.\n" - "tape_class.c ($Revision: 1.8 $)" + "tape_class.c" ); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h index 33133ad00ba2..3d0ca054cdee 100644 --- a/drivers/s390/char/tape_class.h +++ b/drivers/s390/char/tape_class.h @@ -1,6 +1,6 @@ /* * (C) Copyright IBM Corp. 2004 All Rights Reserved. - * tape_class.h ($Revision: 1.4 $) + * tape_class.h * * Tape class device support * diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 8f486e1a8507..4ea438c749c9 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -1239,7 +1239,7 @@ tape_init (void) #ifdef DBF_LIKE_HELL debug_set_level(TAPE_DBF_AREA, 6); #endif - DBF_EVENT(3, "tape init: ($Revision: 1.54 $)\n"); + DBF_EVENT(3, "tape init\n"); tape_proc_init(); tapechar_init (); tapeblock_init (); @@ -1263,8 +1263,7 @@ tape_exit(void) MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); -MODULE_DESCRIPTION("Linux on zSeries channel attached " - "tape device driver ($Revision: 1.54 $)"); +MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver"); MODULE_LICENSE("GPL"); module_init(tape_init); diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index cd2cc28e16a7..5287631fbfc8 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -2,8 +2,6 @@ * drivers/s390/cio/airq.c * S/390 common I/O routines -- support for adapter interruptions * - * $Revision: 1.15 $ - * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 72f27c151c09..cb8e2e672b68 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.42 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 6c077ad71edc..8013c8eb76fe 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.35 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 2cbb724791a8..8cf9905d484b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.128 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -233,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) return 0; mask = 0x80 >> j; - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); stsch(sch->schid, &schib); if (!schib.pmcw.dnv) @@ -282,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); out_unlock: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); return 0; out_unreg: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); sch->lpm = 0; if (css_enqueue_subchannel_slow(sch->schid)) { css_clear_subchannel_slow_list(); @@ -653,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data) if (!sch) /* Check if the subchannel is now available. */ return __chp_add_new_sch(schid); - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); for (i=0; i<8; i++) if (sch->schib.pmcw.chpid[i] == chp->id) { if (stsch(sch->schid, &sch->schib) != 0) { @@ -675,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); put_device(&sch->dev); return 0; } diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 44e4b4bb1c5a..3e75095f35d0 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -68,6 +68,6 @@ extern void *chsc_get_chp_desc(struct subchannel*, int); extern int chsc_enable_facility(int); -#define to_channelpath(dev) container_of(dev, struct channel_path, dev) +#define to_channelpath(device) container_of(device, struct channel_path, dev) #endif diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 6223b06d27d5..cbb86fa5f293 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.140 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 0b03714e696a..07ef3f640f4a 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $) + * linux/drivers/s390/cio/cmf.c * * Linux on zSeries Channel Measurement Facility support * diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 516108779f60..1bbf231f8aaf 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.96 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a67e7e60e330..062fb100d94c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1,7 +1,6 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.140 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -255,7 +254,7 @@ modalias_show (struct device *dev, struct device_attribute *attr, char *buf) struct ccw_device_id *id = &(cdev->id); int ret; - ret = sprintf(buf, "ccw:t%04Xm%02x", + ret = sprintf(buf, "ccw:t%04Xm%02X", id->cu_type, id->cu_model); if (id->dev_type != 0) ret += sprintf(buf + ret, "dt%04Xdm%02X\n", @@ -1013,7 +1012,7 @@ ccw_device_probe_console(void) int ret; if (xchg(&console_cdev_in_use, 1) != 0) - return NULL; + return ERR_PTR(-EBUSY); sch = cio_probe_console(); if (IS_ERR(sch)) { console_cdev_in_use = 0; diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 8b0218949b62..3a50b1903287 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,8 +1,6 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.61 $ - * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 77be2c39bfe4..45ce032772f4 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,8 +56,6 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.117 $" - /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); MODULE_DESCRIPTION("QDIO base support version 2, " \ @@ -66,8 +64,7 @@ MODULE_LICENSE("GPL"); /******************** HERE WE GO ***********************************/ -static const char version[] = "QDIO base support version 2 (" - VERSION_QDIO_C "/" VERSION_QDIO_H "/" VERSION_CIO_QDIO_H ")"; +static const char version[] = "QDIO base support version 2"; #ifdef QDIO_PERFORMANCE_STATS static int proc_perf_file_registration; diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index fa385e761fe1..ceb3ab31ee08 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -5,8 +5,6 @@ #include "schid.h" -#define VERSION_CIO_QDIO_H "$Revision: 1.40 $" - #ifdef CONFIG_QDIO_DEBUG #define QDIO_VERBOSE_LEVEL 9 #else /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h index f87c785f2039..dbbcda3c846a 100644 --- a/drivers/s390/crypto/z90common.h +++ b/drivers/s390/crypto/z90common.h @@ -27,8 +27,6 @@ #ifndef _Z90COMMON_H_ #define _Z90COMMON_H_ -#define VERSION_Z90COMMON_H "$Revision: 1.17 $" - #define RESPBUFFSIZE 256 #define PCI_FUNC_KEY_DECRYPT 0x5044 diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index 3a18443fdfa7..5e6b1f535f62 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -29,8 +29,6 @@ #include <linux/ioctl.h> -#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $" - #define z90crypt_VERSION 1 #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards #define z90crypt_VARIANT 3 // 3 = CEX2A support diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c index d7f7494a0cbe..4141919da805 100644 --- a/drivers/s390/crypto/z90hardware.c +++ b/drivers/s390/crypto/z90hardware.c @@ -32,12 +32,6 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $" - -char z90hardware_version[] __initdata = - "z90hardware.o (" VERSION_Z90HARDWARE_C "/" - VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; - struct cca_token_hdr { unsigned char token_identifier; unsigned char version; diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 2f54d033d7cf..7d6f19030ef9 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -38,14 +38,6 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90MAIN_C "$Revision: 1.62 $" - -static char z90main_version[] __initdata = - "z90main.o (" VERSION_Z90MAIN_C "/" - VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; - -extern char z90hardware_version[]; - /** * Defaults that may be modified. */ @@ -594,8 +586,6 @@ z90crypt_init_module(void) PRINTKN("Version %d.%d.%d loaded, built on %s %s\n", z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT, __DATE__, __TIME__); - PRINTKN("%s\n", z90main_version); - PRINTKN("%s\n", z90hardware_version); PDEBUG("create_z90crypt (domain index %d) successful.\n", domain); } else diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index e70af7f39946..a86436a7a606 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2,8 +2,6 @@ * drivers/s390/net/claw.c * ESCON CLAW network driver * - * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ - * * Linux for zSeries version * Copyright (C) 2002,2005 IBM Corporation * Author(s) Original code written by: @@ -4391,14 +4389,7 @@ static int __init claw_init(void) { int ret = 0; - printk(KERN_INFO "claw: starting driver " -#ifdef MODULE - "module " -#else - "compiled into kernel " -#endif - " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n"); - + printk(KERN_INFO "claw: starting driver\n"); #ifdef FUNCTRACE printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__); diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 3df71970f601..969be465309c 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -2,7 +2,7 @@ * Define constants * * * ********************************************************/ -#define VERSION_CLAW_H "$Revision: 1.6 $" + /*-----------------------------------------------------* * CCW command codes for CLAW protocol * *------------------------------------------------------*/ diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c index 0e2a8bb93032..e6e72deb36b5 100644 --- a/drivers/s390/net/ctcdbug.c +++ b/drivers/s390/net/ctcdbug.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $) + * linux/drivers/s390/net/ctcdbug.c * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,8 +9,6 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) @@ -80,4 +78,3 @@ ctc_register_dbf_views(void) return 0; } - diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h index 7d6afa1627c3..413925ee23d1 100644 --- a/drivers/s390/net/ctcdbug.h +++ b/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $) + * linux/drivers/s390/net/ctcdbug.h * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,8 +9,6 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 1901feef07d9..af9f212314b3 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,6 +1,4 @@ /* - * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $ - * * CTC / ESCON network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -37,8 +35,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $ - * */ #undef DEBUG #include <linux/module.h> @@ -248,22 +244,11 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.79 $"; - char *version = vbuf; if (printed) return; - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO "CTC driver Version%s" -#ifdef DEBUG - " (DEBUG-VERSION, " __DATE__ __TIME__ ")" -#endif - " initialized\n", version); + + printk(KERN_INFO "CTC driver initialized\n"); printed = 1; } diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h index ba3605f16335..d2e835c0c134 100644 --- a/drivers/s390/net/ctcmain.h +++ b/drivers/s390/net/ctcmain.h @@ -1,6 +1,4 @@ /* - * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $ - * * CTC / ESCON network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -29,8 +27,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $ - * */ #ifndef _CTCMAIN_H_ diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 93d1725eb79b..5cdcdbf92962 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -1,6 +1,4 @@ /* - * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $ - * * CTC / ESCON network driver, tty interface. * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h index 84b2f8f23ab3..7254dc006311 100644 --- a/drivers/s390/net/ctctty.h +++ b/drivers/s390/net/ctctty.h @@ -1,6 +1,4 @@ /* - * $Id: ctctty.h,v 1.4 2003/09/18 08:01:10 mschwide Exp $ - * * CTC / ESCON network driver, tty interface. * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 2014fb7a4881..b12533104c1f 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c @@ -1,6 +1,4 @@ /* - * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $ - * * CTC / LCS ccw_device driver * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 24029bd9c7d0..6caf5fa6a3b5 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c @@ -1,6 +1,4 @@ /** - * $Id: fsm.c,v 1.6 2003/10/15 11:37:29 mschwide Exp $ - * * A generic FSM based on fsm used in isdn4linux * */ diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index 5b98253be7aa..af679c10f1bd 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h @@ -1,5 +1,3 @@ -/* $Id: fsm.h,v 1.1.1.1 2002/03/13 19:33:09 mschwide Exp $ - */ #ifndef _FSM_H_ #define _FSM_H_ diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index ea8177392564..760e77ec5a11 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,6 +1,4 @@ /* - * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $ - * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -29,8 +27,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $ - * */ /* #define DEBUG */ @@ -355,17 +351,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.47 $"; - char *version = vbuf; - - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO - "IUCV lowlevel driver Version%s initialized\n", version); + printk(KERN_INFO "IUCV lowlevel driver initialized\n"); } /** diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index da8c515743e8..6229ba4995ad 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,8 +11,6 @@ * Frank Pavlic (fpavlic@de.ibm.com) and * Martin Schwidefsky <schwidefsky@de.ibm.com> * - * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ - * * 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, or (at your option) @@ -59,9 +57,8 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.99 $" -static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; +static char version[] __initdata = "LCS driver"; static char debug_buffer[255]; /** diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index a7f348ef1b08..08e60ad43916 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -6,8 +6,6 @@ #include <linux/workqueue.h> #include <asm/ccwdev.h> -#define VERSION_LCS_H "$Revision: 1.19 $" - #define LCS_DBF_TEXT(level, name, text) \ do { \ debug_text_event(lcs_dbf_##name, level, text); \ diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index ac4c4b83fe17..71d3853e8682 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1,6 +1,4 @@ /* - * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $ - * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation @@ -31,8 +29,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.69 $ - * */ #undef DEBUG @@ -2077,16 +2073,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write); static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.69 $"; - char *version = vbuf; - - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - PRINT_INFO("NETIUCV driver Version%s initialized\n", version); + PRINT_INFO("NETIUCV driver initialized\n"); } static void __exit diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index d238c7ed103b..9a064d4727ad 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -25,8 +25,6 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.152 $" - #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" #else diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index f94f1f25eec6..b02313127780 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -1,6 +1,5 @@ /* - * - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $) + * linux/drivers/s390/net/qeth_eddp.c * * Enhanced Device Driver Packing (EDDP) support for the qeth driver. * @@ -8,8 +7,6 @@ * * Author(s): Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $ - * */ #include <linux/config.h> #include <linux/errno.h> diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h index e1b51860bc57..cae9ba265056 100644 --- a/drivers/s390/net/qeth_eddp.h +++ b/drivers/s390/net/qeth_eddp.h @@ -1,14 +1,12 @@ /* - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.5 $) + * linux/drivers/s390/net/qeth_eddp.h * - * Header file for qeth enhanced device driver pakcing. + * Header file for qeth enhanced device driver packing. * * Copyright 2004 IBM Corporation * * Author(s): Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.5 $ $Date: 2005/03/24 09:04:18 $ - * */ #ifndef __QETH_EDDP_H__ #define __QETH_EDDP_H__ diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h index c0b4c8d82c45..e422b41c656e 100644 --- a/drivers/s390/net/qeth_fs.h +++ b/drivers/s390/net/qeth_fs.h @@ -12,11 +12,6 @@ #ifndef __QETH_FS_H__ #define __QETH_FS_H__ -#define VERSION_QETH_FS_H "$Revision: 1.10 $" - -extern const char *VERSION_QETH_PROC_C; -extern const char *VERSION_QETH_SYS_C; - #ifdef CONFIG_PROC_FS extern int qeth_create_procfs_entries(void); diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 97f927c01a82..410abeada6c4 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,5 @@ /* - * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $) + * linux/drivers/s390/net/qeth_main.c * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,8 +11,6 @@ * Frank Pavlic (fpavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.251 $ $Date: 2005/05/04 20:19:18 $ - * * 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, or (at your option) @@ -73,7 +70,6 @@ #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.251 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -8626,12 +8622,7 @@ qeth_init(void) { int rc=0; - PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", - version, VERSION_QETH_C, VERSION_QETH_H, - VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, - VERSION_QETH_FS_H, VERSION_QETH_PROC_C, - VERSION_QETH_SYS_C, QETH_VERSION_IPV6, - QETH_VERSION_VLAN); + PRINT_INFO("loading %s\n", version); INIT_LIST_HEAD(&qeth_card_list.list); INIT_LIST_HEAD(&qeth_notify_list); diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c index 5f8754addc14..77c83209d70e 100644 --- a/drivers/s390/net/qeth_mpc.c +++ b/drivers/s390/net/qeth_mpc.c @@ -11,8 +11,6 @@ #include <asm/cio.h> #include "qeth_mpc.h" -const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $"; - unsigned char IDX_ACTIVATE_READ[]={ 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, 0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00, diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 864cec5f6c62..011c41041029 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h @@ -14,10 +14,6 @@ #include <asm/qeth.h> -#define VERSION_QETH_MPC_H "$Revision: 1.46 $" - -extern const char *VERSION_QETH_MPC_C; - #define IPA_PDU_HEADER_SIZE 0x40 #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 7bf35098831e..3c6339df879d 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $) + * linux/drivers/s390/net/qeth_fs.c * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to procfs. @@ -21,8 +21,6 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $"; - /***** /proc/qeth *****/ #define QETH_PROCFILE_NAME "qeth" static struct proc_dir_entry *qeth_procfile; diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 0ea185f70f75..c1831f572585 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.60 $) + * linux/drivers/s390/net/qeth_sys.c * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,8 +20,6 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $"; - /*****************************************************************************/ /* */ /* /sys-fs stuff UNDER DEVELOPMENT !!! */ diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 3c50b6f24f51..1286ddea450b 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $) + * linux/drivers/s390/net/qeth_tso.h * * Header file for qeth TCP Segmentation Offload support. * @@ -7,8 +7,6 @@ * * Author(s): Frank Pavlic <fpavlic@de.ibm.com> * - * $Revision: 1.8 $ $Date: 2005/05/04 20:19:18 $ - * */ #ifndef __QETH_TSO_H__ #define __QETH_TSO_H__ diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index 206518c7d332..e3f647169827 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c @@ -1,7 +1,6 @@ /* * drivers/s390/s390_rdev.c * s390 root device - * $Revision: 1.4 $ * * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, * IBM Corporation diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index d9ea7ed2e46e..7abb42a09ae2 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h @@ -90,15 +90,16 @@ struct crw { static inline int stcrw(struct crw *pcrw ) { - int ccode; + int ccode; - __asm__ __volatile__( - "STCRW 0(%1)\n\t" - "IPM %0\n\t" - "SRL %0,28\n\t" - : "=d" (ccode) : "a" (pcrw) - : "cc", "1" ); - return ccode; + __asm__ __volatile__( + "stcrw 0(%2)\n\t" + "ipm %0\n\t" + "srl %0,28\n\t" + : "=d" (ccode), "=m" (*pcrw) + : "a" (pcrw) + : "cc" ); + return ccode; } #endif /* __s390mach */ diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 167fef39d8a7..95b92f317b6f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -29,8 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_AUX_REVISION "$Revision: 1.145 $" - #include "zfcp_ext.h" /* accumulated log level (module parameter) */ diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 0fc46381fc22..241136d0c6eb 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_CCW_C_REVISION "$Revision: 1.58 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 95599719f8ab..4d7d47cf2394 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -23,8 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_DBF_REVISION "$Revision$" - #include <asm/debug.h> #include <linux/ctype.h> #include "zfcp_ext.h" diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9bb511083a26..e260d19fa717 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -34,8 +34,6 @@ #ifndef ZFCP_DEF_H #define ZFCP_DEF_H -#define ZFCP_DEF_REVISION "$Revision: 1.111 $" - /*************************** INCLUDES *****************************************/ #include <linux/init.h> diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c065cb836c97..da947e662031 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -31,8 +31,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP -#define ZFCP_ERP_REVISION "$Revision: 1.86 $" - #include "zfcp_ext.h" static int zfcp_erp_adisc(struct zfcp_port *); diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c3782261cb5c..c1ba7cf1b496 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -32,8 +32,6 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H -#define ZFCP_EXT_REVISION "$Revision: 1.62 $" - #include "zfcp_def.h" extern struct zfcp_data zfcp_data; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cbfab09899c8..9f0cb3d820c0 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -30,8 +30,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.92 $" - #include "zfcp_ext.h" static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *); diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index d719f66a29a4..1c3275163c91 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -29,8 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_QDIO_C_REVISION "$Revision: 1.20 $" - #include "zfcp_ext.h" static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3c2cbcccbf54..e0803757c0fa 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -31,8 +31,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -#define ZFCP_SCSI_REVISION "$Revision: 1.74 $" - #include "zfcp_ext.h" static void zfcp_scsi_slave_destroy(struct scsi_device *sdp); diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index 9f262250043a..dfc07370f412 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.38 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c index 77a5e2dcc0ff..6622d55e0a45 100644 --- a/drivers/s390/scsi/zfcp_sysfs_driver.c +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c @@ -27,8 +27,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.17 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index 3924eb38805c..f401d42db21c 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -28,8 +28,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 2f50815f65c7..ad5dfb889bee 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -28,8 +28,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $" - #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 38d6d00fb0fc..014cc8d54a9f 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -38,10 +38,10 @@ #include <linux/slab.h> #include <linux/completion.h> #include <linux/blkdev.h> +#include <linux/delay.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <asm/semaphore.h> -#include <asm/delay.h> #include "aacraid.h" diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 19bd346951dd..a800fb51168b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -286,6 +286,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* ICH8M */ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH8M */ + { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB360 */ + { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB363 */ { } /* terminate list */ }; @@ -802,7 +806,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void __iomem *mmio = probe_ent->mmio_base; u32 tmp, cap_save; - u16 tmp16; unsigned int i, j, using_dac; int rc; void __iomem *port_mmio; @@ -836,9 +839,13 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) writel(0xf, mmio + HOST_PORTS_IMPL); (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ - pci_read_config_word(pdev, 0x92, &tmp16); - tmp16 |= 0xf; - pci_write_config_word(pdev, 0x92, tmp16); + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + u16 tmp16; + + pci_read_config_word(pdev, 0x92, &tmp16); + tmp16 |= 0xf; + pci_write_config_word(pdev, 0x92, tmp16); + } hpriv->cap = readl(mmio + HOST_CAP); hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); @@ -1082,6 +1089,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (have_msi) hpriv->flags |= AHCI_FLAG_MSI; + /* JMicron-specific fixup: make sure we're in AHCI mode */ + if (pdev->vendor == 0x197b) + pci_write_config_byte(pdev, 0x41, 0xa1); + /* initialize adapter */ rc = ahci_host_init(probe_ent); if (rc) diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index 69ed77fcb71f..7955ebe8e1e8 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -37,13 +37,13 @@ config AIC79XX_CMDS_PER_DEVICE config AIC79XX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" depends on SCSI_AIC79XX - default "15000" + default "5000" ---help--- The number of milliseconds to delay after an initial bus reset. The bus settle delay following all error recovery actions is dictated by the SCSI layer and is not affected by this value. - Default: 15000 (15 seconds) + Default: 5000 (5 seconds) config AIC79XX_BUILD_FIRMWARE bool "Build Adapter Firmware with Kernel Build" diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 2cfdbef447db..1d11f7e77564 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#109 $ * * $FreeBSD$ */ @@ -222,6 +222,7 @@ typedef enum { typedef enum { AHD_FENONE = 0x00000, AHD_WIDE = 0x00001,/* Wide Channel */ + AHD_AIC79XXB_SLOWCRC = 0x00002,/* SLOWCRC bit should be set */ AHD_MULTI_FUNC = 0x00100,/* Multi-Function/Channel Device */ AHD_TARGETMODE = 0x01000,/* Has tested target mode support */ AHD_MULTIROLE = 0x02000,/* Space for two roles at a time */ diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index 3a3204703b15..be14e2ecb8f7 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg @@ -1,7 +1,7 @@ /* * Aic79xx register and scratch ram definitions. * - * Copyright (c) 1994-2001 Justin T. Gibbs. + * Copyright (c) 1994-2001, 2004 Justin T. Gibbs. * Copyright (c) 2000-2002 Adaptec Inc. * All rights reserved. * @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -3715,8 +3715,9 @@ scratch_ram { SEQ_FLAGS2 { size 1 - field TARGET_MSG_PENDING 0x02 - field SELECTOUT_QFROZEN 0x04 + field PENDING_MK_MESSAGE 0x01 + field TARGET_MSG_PENDING 0x02 + field SELECTOUT_QFROZEN 0x04 } ALLOCFIFO_SCBPTR { @@ -3777,6 +3778,26 @@ scratch_ram { CMDSIZE_TABLE { size 8 } + /* + * When an SCB with the MK_MESSAGE flag is + * queued to the controller, it cannot enter + * the waiting for selection list until the + * selections for any previously queued + * commands to that target complete. During + * the wait, the MK_MESSAGE SCB is queued + * here. + */ + MK_MESSAGE_SCB { + size 2 + } + /* + * Saved SCSIID of MK_MESSAGE_SCB to avoid + * an extra SCBPTR operation when deciding + * if the MK_MESSAGE_SCB can be run. + */ + MK_MESSAGE_SCSIID { + size 1 + } } /************************* Hardware SCB Definition ****************************/ diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index bef1f9d369b6..58bc17591b54 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq @@ -1,7 +1,7 @@ /* * Adaptec U320 device driver firmware for Linux and FreeBSD. * - * Copyright (c) 1994-2001 Justin T. Gibbs. + * Copyright (c) 1994-2001, 2004 Justin T. Gibbs. * Copyright (c) 2000-2002 Adaptec Inc. * All rights reserved. * @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -110,10 +110,8 @@ check_waiting_list: * one last time. */ test SSTAT0, SELDO jnz select_out; -END_CRITICAL; call start_selection; idle_loop_checkbus: -BEGIN_CRITICAL; test SSTAT0, SELDO jnz select_out; END_CRITICAL; test SSTAT0, SELDI jnz select_in; @@ -294,7 +292,6 @@ fetch_new_scb_inprog: test CCSCBCTL, ARRDONE jz return; fetch_new_scb_done: and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov REG0, SCBPTR, 2; clr A; add CMDS_PENDING, 1; adc CMDS_PENDING[1], A; @@ -316,43 +313,117 @@ fetch_new_scb_done: clr SCB_FIFO_USE_COUNT; /* Update the next SCB address to download. */ bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; + /* + * NULL out the SCB links since these fields + * occupy the same location as SCB_NEXT_SCB_BUSADDR. + */ mvi SCB_NEXT[1], SCB_LIST_NULL; mvi SCB_NEXT2[1], SCB_LIST_NULL; /* Increment our position in the QINFIFO. */ mov NONE, SNSCB_QOFF; + /* - * SCBs that want to send messages are always - * queued independently. This ensures that they - * are at the head of the SCB list to select out - * to a target and we will see the MK_MESSAGE flag. + * Save SCBID of this SCB in REG0 since + * SCBPTR will be clobbered during target + * list updates. We also record the SCB's + * flags so that we can refer to them even + * after SCBPTR has been changed. + */ + bmov REG0, SCBPTR, 2; + mov A, SCB_CONTROL; + + /* + * Find the tail SCB of the execution queue + * for this target. */ - test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb; shr SINDEX, 3, SCB_SCSIID; and SINDEX, ~0x1; mvi SINDEX[1], (WAITING_SCB_TAILS >> 8); bmov DINDEX, SINDEX, 2; bmov SCBPTR, SINDIR, 2; + + /* + * Update the tail to point to the new SCB. + */ bmov DINDIR, REG0, 2; + + /* + * If the queue was empty, queue this SCB as + * the first for this target. + */ cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb; + + /* + * SCBs that want to send messages must always be + * at the head of their per-target queue so that + * ATN can be asserted even if the current + * negotiation agreement is packetized. If the + * target queue is empty, the SCB can be queued + * immediately. If the queue is not empty, we must + * wait for it to empty before entering this SCB + * into the waiting for selection queue. Otherwise + * our batching and round-robin selection scheme + * could allow commands to be queued out of order. + * To simplify the implementation, we stop pulling + * new commands from the host until the MK_MESSAGE + * SCB can be queued to the waiting for selection + * list. + */ + test A, MK_MESSAGE jz batch_scb; + + /* + * If the last SCB is also a MK_MESSAGE SCB, then + * order is preserved even if we batch. + */ + test SCB_CONTROL, MK_MESSAGE jz batch_scb; + + /* + * Defer this SCB and stop fetching new SCBs until + * it can be queued. Since the SCB_SCSIID of the + * tail SCB must be the same as that of the newly + * queued SCB, there is no need to restore the SCBID + * here. + */ + or SEQ_FLAGS2, PENDING_MK_MESSAGE; + bmov MK_MESSAGE_SCB, REG0, 2; + mov MK_MESSAGE_SCSIID, SCB_SCSIID ret; + +batch_scb: + /* + * Otherwise just update the previous tail SCB to + * point to the new tail. + */ bmov SCB_NEXT, REG0, 2 ret; + first_new_target_scb: + /* + * Append SCB to the tail of the waiting for + * selection list. + */ cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb; bmov SCBPTR, WAITING_TID_TAIL, 2; bmov SCB_NEXT2, REG0, 2; bmov WAITING_TID_TAIL, REG0, 2 ret; first_new_scb: + /* + * Whole list is empty, so the head of + * the list must be initialized too. + */ bmov WAITING_TID_HEAD, REG0, 2; bmov WAITING_TID_TAIL, REG0, 2 ret; END_CRITICAL; scbdma_idle: /* - * Give precedence to downloading new SCBs to execute - * unless select-outs are currently frozen. + * Don't bother downloading new SCBs to execute + * if select-outs are currently frozen or we have + * a MK_MESSAGE SCB waiting to enter the queue. */ - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2; + test SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE + jnz scbdma_no_new_scbs; BEGIN_CRITICAL; test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb; +scbdma_no_new_scbs: cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb; cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return; /* FALLTHROUGH */ @@ -671,27 +742,41 @@ curscb_ww_done: } /* - * Requeue any SCBs not sent, to the tail of the waiting Q. + * The whole list made it. Clear our tail pointer to indicate + * that the per-target selection queue is now empty. */ - cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done; + cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail; /* + * Requeue any SCBs not sent, to the tail of the waiting Q. * We know that neither the per-TID list nor the list of - * TIDs is empty. Use this knowledge to our advantage. + * TIDs is empty. Use this knowledge to our advantage and + * queue the remainder to the tail of the global execution + * queue. */ bmov REG0, SCB_NEXT, 2; +select_out_queue_remainder: bmov SCBPTR, WAITING_TID_TAIL, 2; bmov SCB_NEXT2, REG0, 2; bmov WAITING_TID_TAIL, REG0, 2; jmp select_out_inc_tid_q; -select_out_list_done: +select_out_clear_tail: + /* + * Queue any pending MK_MESSAGE SCB for this target now + * that the queue is empty. + */ + test SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb; + mov A, MK_MESSAGE_SCSIID; + cmp SCB_SCSIID, A jne select_out_no_mk_message_scb; + and SEQ_FLAGS2, ~PENDING_MK_MESSAGE; + bmov REG0, MK_MESSAGE_SCB, 2; + jmp select_out_queue_remainder; + +select_out_no_mk_message_scb: /* - * The whole list made it. Just clear our TID's tail pointer - * unless we were queued independently due to our need to - * send a message. + * Clear this target's execution tail and increment the queue. */ - test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q; shr DINDEX, 3, SCB_SCSIID; or DINDEX, 1; /* Want only the second byte */ mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); @@ -703,8 +788,8 @@ select_out_inc_tid_q: mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; bmov SCBPTR, CURRSCB, 2; mvi CLRSINT0, CLRSELDO; - test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase; - test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase; + test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared; + test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared; /* * If this is a packetized connection, return to our @@ -2127,6 +2212,18 @@ SET_DST_MODE M_DFF0; mvi DFFSXFRCTL, CLRCHN; unexpected_nonpkt_mode_cleared: mvi CLRSINT2, CLRNONPACKREQ; + if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { + /* + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. + */ + test SCSISIGI, BSYI jz . + 2; + mvi CLRSINT1,CLRBUSFREE; + or SIMODE1, ENBUSFREE; + } test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; SET_SEQINTCODE(ENTERING_NONPACK) jmp ITloop; diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index db8f5ce99ee3..342f77966a5b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#250 $ */ #ifdef __linux__ @@ -197,7 +197,8 @@ static int ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, ahd_search_action action, - u_int *list_head, u_int tid); + u_int *list_head, u_int *list_tail, + u_int tid); static void ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next); @@ -1660,7 +1661,8 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) * so just clear the error. */ ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ); - } else if ((status & BUSFREE) != 0) { + } else if ((status & BUSFREE) != 0 + || (lqistat1 & LQOBUSFREE) != 0) { u_int lqostat1; int restart; int clear_fifo; @@ -2025,10 +2027,6 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) u_int waiting_t; u_int next; - if ((busfreetime & BUSFREE_LQO) == 0) - printf("%s: Warning, BUSFREE time is 0x%x. " - "Expected BUSFREE_LQO.\n", - ahd_name(ahd), busfreetime); /* * The LQO manager detected an unexpected busfree * either: @@ -2251,8 +2249,14 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) struct ahd_tmode_tstate *tstate; /* - * PPR Rejected. Try non-ppr negotiation - * and retry command. + * PPR Rejected. + * + * If the previous negotiation was packetized, + * this could be because the device has been + * reset without our knowledge. Force our + * current negotiation to async and retry the + * negotiation. Otherwise retry the command + * with non-ppr negotiation. */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) @@ -2261,11 +2265,34 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - tinfo->goal.ppr_options = 0; - ahd_qinfifo_requeue_tail(ahd, scb); - printerror = 0; + if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) { + ahd_set_width(ahd, &devinfo, + MSG_EXT_WDTR_BUS_8_BIT, + AHD_TRANS_CUR, + /*paused*/TRUE); + ahd_set_syncrate(ahd, &devinfo, + /*period*/0, /*offset*/0, + /*ppr_options*/0, + AHD_TRANS_CUR, + /*paused*/TRUE); + /* + * The expect PPR busfree handler below + * will effect the retry and necessary + * abort. + */ + } else { + tinfo->curr.transport_version = 2; + tinfo->goal.transport_version = 2; + tinfo->goal.ppr_options = 0; + /* + * Remove any SCBs in the waiting for selection + * queue that may also be for this target so + * that command ordering is preserved. + */ + ahd_freeze_devq(ahd, scb); + ahd_qinfifo_requeue_tail(ahd, scb); + printerror = 0; + } } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE) && ppr_busfree == 0) { /* @@ -2280,6 +2307,12 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); + /* + * Remove any SCBs in the waiting for selection + * queue that may also be for this target so that + * command ordering is preserved. + */ + ahd_freeze_devq(ahd, scb); ahd_qinfifo_requeue_tail(ahd, scb); printerror = 0; } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE) @@ -2297,6 +2330,12 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); + /* + * Remove any SCBs in the waiting for selection + * queue that may also be for this target so that + * command ordering is preserved. + */ + ahd_freeze_devq(ahd, scb); ahd_qinfifo_requeue_tail(ahd, scb); printerror = 0; } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0 @@ -2369,14 +2408,14 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ printf("%s: ", ahd_name(ahd)); } - if (lastphase != P_BUSFREE) - ahd_force_renegotiation(ahd, &devinfo); printf("Unexpected busfree %s, %d SCBs aborted, " "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); + if (lastphase != P_BUSFREE) + ahd_force_renegotiation(ahd, &devinfo); } /* Always restart the sequencer. */ return (1); @@ -3293,6 +3332,15 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, con_opts |= WIDEXFER; /* + * Slow down our CRC interval to be + * compatible with packetized U320 devices + * that can't handle a CRC at full speed + */ + if (ahd->features & AHD_AIC79XXB_SLOWCRC) { + con_opts |= ENSLOWCRC; + } + + /* * During packetized transfers, the target will * give us the oportunity to send command packets * without us asserting attention. @@ -3315,7 +3363,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) { struct scb *pending_scb; int pending_scb_count; - u_int scb_tag; int paused; u_int saved_scbptr; ahd_mode_state saved_modes; @@ -3333,7 +3380,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) pending_scb_count = 0; LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { struct ahd_devinfo devinfo; - struct hardware_scb *pending_hscb; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; @@ -3341,11 +3387,10 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); - pending_hscb = pending_scb->hscb; if ((tstate->auto_negotiate & devinfo.target_mask) == 0 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; - pending_hscb->control &= ~MK_MESSAGE; + pending_scb->hscb->control &= ~MK_MESSAGE; } ahd_sync_scb(ahd, pending_scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); @@ -3377,18 +3422,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); saved_scbptr = ahd_get_scbptr(ahd); /* Ensure that the hscbs down on the card match the new information */ - for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { - struct hardware_scb *pending_hscb; + LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { + u_int scb_tag; u_int control; - pending_scb = ahd_lookup_scb(ahd, scb_tag); - if (pending_scb == NULL) - continue; + scb_tag = SCB_GET_TAG(pending_scb); ahd_set_scbptr(ahd, scb_tag); - pending_hscb = pending_scb->hscb; control = ahd_inb_scbram(ahd, SCB_CONTROL); control &= ~MK_MESSAGE; - control |= pending_hscb->control & MK_MESSAGE; + control |= pending_scb->hscb->control & MK_MESSAGE; ahd_outb(ahd, SCB_CONTROL, control); } ahd_set_scbptr(ahd, saved_scbptr); @@ -6500,13 +6542,14 @@ ahd_chip_init(struct ahd_softc *ahd) | ENLQIOVERI_LQ|ENLQIOVERI_NLQ); ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC); /* - * An interrupt from LQOBUSFREE is made redundant by the - * BUSFREE interrupt. We choose to have the sequencer catch - * LQOPHCHGINPKT errors manually for the command phase at the - * start of a packetized selection case. - ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE|ENLQOPHACHGINPKT); + * We choose to have the sequencer catch LQOPHCHGINPKT errors + * manually for the command phase at the start of a packetized + * selection case. ENLQOBUSFREE should be made redundant by + * the BUSFREE interrupt, but it seems that some LQOBUSFREE + * events fail to assert the BUSFREE interrupt so we must + * also enable LQOBUSFREE interrupts. */ - ahd_outb(ahd, LQOMODE1, 0); + ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE); /* * Setup sequencer interrupt handlers. @@ -6617,6 +6660,8 @@ ahd_chip_init(struct ahd_softc *ahd) /* We don't have any waiting selections */ ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL); ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL); + ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF); for (i = 0; i < AHD_NUM_TARGETS; i++) ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL); @@ -6704,6 +6749,18 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_loadseq(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + + if (ahd->features & AHD_AIC79XXB_SLOWCRC) { + u_int negodat3 = ahd_inb(ahd, NEGCONOPTS); + + negodat3 |= ENSLOWCRC; + ahd_outb(ahd, NEGCONOPTS, negodat3); + negodat3 = ahd_inb(ahd, NEGCONOPTS); + if (!(negodat3 & ENSLOWCRC)) + printf("aic79xx: failed to set the SLOWCRC bit\n"); + else + printf("aic79xx: SLOWCRC bit set\n"); + } } /* @@ -7260,12 +7317,28 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd) ahd->flags &= ~AHD_UPDATE_PEND_CMDS; } +void +ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status) +{ + cam_status ostat; + cam_status cstat; + + ostat = ahd_get_transaction_status(scb); + if (ostat == CAM_REQ_INPROG) + ahd_set_transaction_status(scb, status); + cstat = ahd_get_transaction_status(scb); + if (cstat != CAM_REQ_CMP) + ahd_freeze_scb(scb); + ahd_done(ahd, scb); +} + int ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, ahd_search_action action) { struct scb *scb; + struct scb *mk_msg_scb; struct scb *prev_scb; ahd_mode_state saved_modes; u_int qinstart; @@ -7274,6 +7347,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, u_int tid_next; u_int tid_prev; u_int scbid; + u_int seq_flags2; u_int savedscbptr; uint32_t busaddr; int found; @@ -7329,23 +7403,10 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, found++; switch (action) { case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, - status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); - ahd_done(ahd, scb); - + ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ - } case SEARCH_REMOVE: break; case SEARCH_PRINT: @@ -7375,21 +7436,24 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * looking for matches. */ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2); + if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) { + scbid = ahd_inw(ahd, MK_MESSAGE_SCB); + mk_msg_scb = ahd_lookup_scb(ahd, scbid); + } else + mk_msg_scb = NULL; savedscbptr = ahd_get_scbptr(ahd); tid_next = ahd_inw(ahd, WAITING_TID_HEAD); tid_prev = SCB_LIST_NULL; targets = 0; for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) { u_int tid_head; + u_int tid_tail; - /* - * We limit based on the number of SCBs since - * MK_MESSAGE SCBs are not in the per-tid lists. - */ targets++; - if (targets > AHD_SCB_MAX) { + if (targets > AHD_NUM_TARGETS) panic("TID LIST LOOP"); - } + if (scbid >= ahd->scb_data.numscbs) { printf("%s: Waiting TID List inconsistency. " "SCB index == 0x%x, yet numscbs == 0x%x.", @@ -7419,8 +7483,71 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, tid_head = scbid; found += ahd_search_scb_list(ahd, target, channel, lun, tag, role, status, - action, &tid_head, + action, &tid_head, &tid_tail, SCB_GET_TARGET(ahd, scb)); + /* + * Check any MK_MESSAGE SCB that is still waiting to + * enter this target's waiting for selection queue. + */ + if (mk_msg_scb != NULL + && ahd_match_scb(ahd, mk_msg_scb, target, channel, + lun, tag, role)) { + + /* + * We found an scb that needs to be acted on. + */ + found++; + switch (action) { + case SEARCH_COMPLETE: + if ((mk_msg_scb->flags & SCB_ACTIVE) == 0) + printf("Inactive SCB pending MK_MSG\n"); + ahd_done_with_status(ahd, mk_msg_scb, status); + /* FALLTHROUGH */ + case SEARCH_REMOVE: + { + u_int tail_offset; + + printf("Removing MK_MSG scb\n"); + + /* + * Reset our tail to the tail of the + * main per-target list. + */ + tail_offset = WAITING_SCB_TAILS + + (2 * SCB_GET_TARGET(ahd, mk_msg_scb)); + ahd_outw(ahd, tail_offset, tid_tail); + + seq_flags2 &= ~PENDING_MK_MESSAGE; + ahd_outb(ahd, SEQ_FLAGS2, seq_flags2); + ahd_outw(ahd, CMDS_PENDING, + ahd_inw(ahd, CMDS_PENDING)-1); + mk_msg_scb = NULL; + break; + } + case SEARCH_PRINT: + printf(" 0x%x", SCB_GET_TAG(scb)); + /* FALLTHROUGH */ + case SEARCH_COUNT: + break; + } + } + + if (mk_msg_scb != NULL + && SCBID_IS_NULL(tid_head) + && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD, + SCB_LIST_NULL, ROLE_UNKNOWN)) { + + /* + * When removing the last SCB for a target + * queue with a pending MK_MESSAGE scb, we + * must queue the MK_MESSAGE scb. + */ + printf("Queueing mk_msg_scb\n"); + tid_head = ahd_inw(ahd, MK_MESSAGE_SCB); + seq_flags2 &= ~PENDING_MK_MESSAGE; + ahd_outb(ahd, SEQ_FLAGS2, seq_flags2); + mk_msg_scb = NULL; + } if (tid_head != scbid) ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next); if (!SCBID_IS_NULL(tid_head)) @@ -7428,6 +7555,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, if (action == SEARCH_PRINT) printf(")\n"); } + + /* Restore saved state. */ ahd_set_scbptr(ahd, savedscbptr); ahd_restore_modes(ahd, saved_modes); return (found); @@ -7436,7 +7565,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, static int ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, - ahd_search_action action, u_int *list_head, u_int tid) + ahd_search_action action, u_int *list_head, + u_int *list_tail, u_int tid) { struct scb *scb; u_int scbid; @@ -7448,6 +7578,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, found = 0; prev = SCB_LIST_NULL; next = *list_head; + *list_tail = SCB_LIST_NULL; for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) { if (scbid >= ahd->scb_data.numscbs) { printf("%s:SCB List inconsistency. " @@ -7463,6 +7594,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, panic("Waiting List traversal\n"); } ahd_set_scbptr(ahd, scbid); + *list_tail = scbid; next = ahd_inw_scbram(ahd, SCB_NEXT); if (ahd_match_scb(ahd, scb, target, channel, lun, SCB_LIST_NULL, role) == 0) { @@ -7472,24 +7604,14 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, found++; switch (action) { case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in Waiting List\n"); - ahd_done(ahd, scb); + ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ - } case SEARCH_REMOVE: ahd_rem_wscb(ahd, scbid, prev, next, tid); - if (prev == SCB_LIST_NULL) + *list_tail = prev; + if (SCBID_IS_NULL(prev)) *list_head = next; break; case SEARCH_PRINT: @@ -7558,14 +7680,17 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, } /* - * SCBs that had MK_MESSAGE set in them will not - * be queued to the per-target lists, so don't - * blindly clear the tail pointer. + * SCBs that have MK_MESSAGE set in them may + * cause the tail pointer to be updated without + * setting the next pointer of the previous tail. + * Only clear the tail if the removed SCB was + * the tail. */ tail_offset = WAITING_SCB_TAILS + (2 * tid); if (SCBID_IS_NULL(next) && ahd_inw(ahd, tail_offset) == scbid) ahd_outw(ahd, tail_offset, prev); + ahd_add_scb_to_free_list(ahd, scbid); return (next); } @@ -8148,11 +8273,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ahd_setup_data_scb(ahd, scb); scb->flags |= SCB_SENSE; ahd_queue_scb(ahd, scb); - /* - * Ensure we have enough time to actually - * retrieve the sense. - */ - ahd_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: @@ -8793,6 +8913,9 @@ ahd_dump_card_state(struct ahd_softc *ahd) * Mode independent registers. */ cur_col = 0; + ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50); + ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50); + ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50); ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50); ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50); ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50); @@ -8808,6 +8931,12 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50); ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50); ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50); + ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50); + ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT), + &cur_col, 50); + ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50); + ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID), + &cur_col, 50); ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50); ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50); ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50); @@ -8915,7 +9044,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); fifo_scbptr = ahd_get_scbptr(ahd); - printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", + printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", ahd_name(ahd), i, (dffstat & (FIFO0FREE << i)) ? "Free" : "Active", ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr); @@ -8970,6 +9099,9 @@ ahd_dump_card_state(struct ahd_softc *ahd) printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT), ahd_inb(ahd, MAXCMDCNT)); + printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n", + ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID), + ahd_inb(ahd, SAVED_LUN)); ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50); printf("\n"); ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index 91c4f7f484b1..8ad3ce945b9e 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#59 $ * * $FreeBSD$ */ @@ -804,9 +804,10 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) uint64_t host_dataptr; host_dataptr = ahd_le64toh(scb->hscb->dataptr); - printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", + printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), - SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), + SCB_GET_TAG(scb), scb->hscb->scsiid, + ahd_le32toh(scb->hscb->hscb_busaddr), (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), (u_int)(host_dataptr & 0xFFFFFFFF), ahd_le32toh(scb->hscb->datacnt)); diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 2567e29960bd..7254ea535a16 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -314,6 +314,21 @@ static uint32_t aic79xx_seltime; */ uint32_t aic79xx_periodic_otag; +/* Some storage boxes are using an LSI chip which has a bug making it + * impossible to use aic79xx Rev B chip in 320 speeds. The following + * storage boxes have been reported to be buggy: + * EonStor 3U 16-Bay: U16U-G3A3 + * EonStor 2U 12-Bay: U12U-G3A3 + * SentinelRAID: 2500F R5 / R6 + * SentinelRAID: 2500F R1 + * SentinelRAID: 2500F/1500F + * SentinelRAID: 150F + * + * To get around this LSI bug, you can set your board to 160 mode + * or you can enable the SLOWCRC bit. + */ +uint32_t aic79xx_slowcrc; + /* * Module information and settable options. */ @@ -343,6 +358,7 @@ MODULE_PARM_DESC(aic79xx, " amplitude:<int> Set the signal amplitude (0-7).\n" " seltime:<int> Selection Timeout:\n" " (0/256ms,1/128ms,2/64ms,3/32ms)\n" +" slowcrc Turn on the SLOWCRC bit (Rev B only)\n" "\n" " Sample /etc/modprobe.conf line:\n" " Enable verbose logging\n" @@ -1003,6 +1019,7 @@ aic79xx_setup(char *s) { "slewrate", NULL }, { "precomp", NULL }, { "amplitude", NULL }, + { "slowcrc", &aic79xx_slowcrc }, }; end = strchr(s, '\0'); @@ -1072,7 +1089,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa return (ENOMEM); *((struct ahd_softc **)host->hostdata) = ahd; - ahd_lock(ahd, &s); ahd->platform_data->host = host; host->can_queue = AHD_MAX_QUEUE; host->cmd_per_lun = 2; @@ -1083,7 +1099,9 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa host->max_lun = AHD_NUM_LUNS; host->max_channel = 0; host->sg_tablesize = AHD_NSEG; + ahd_lock(ahd, &s); ahd_set_unit(ahd, ahd_linux_unit++); + ahd_unlock(ahd, &s); sprintf(buf, "scsi%d", host->host_no); new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (new_name != NULL) { @@ -1093,7 +1111,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa host->unique_id = ahd->unit; ahd_linux_initialize_scsi_bus(ahd); ahd_intr_enable(ahd, TRUE); - ahd_unlock(ahd, &s); host->transportt = ahd_linux_transport_template; @@ -1127,6 +1144,7 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) { u_int target_id; u_int numtarg; + unsigned long s; target_id = 0; numtarg = 0; @@ -1139,6 +1157,8 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) else numtarg = (ahd->features & AHD_WIDE) ? 16 : 8; + ahd_lock(ahd, &s); + /* * Force negotiation to async for all targets that * will not see an initial bus reset. @@ -1155,16 +1175,12 @@ ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd) ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS); } + ahd_unlock(ahd, &s); /* Give the bus some time to recover */ if ((ahd->flags & AHD_RESET_BUS_A) != 0) { ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = - jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); + msleep(AIC79XX_RESET_DELAY); + ahd_release_simq(ahd); } } @@ -2033,6 +2049,9 @@ ahd_linux_sem_timeout(u_long arg) void ahd_freeze_simq(struct ahd_softc *ahd) { + unsigned long s; + + ahd_lock(ahd, &s); ahd->platform_data->qfrozen++; if (ahd->platform_data->qfrozen == 1) { scsi_block_requests(ahd->platform_data->host); @@ -2040,6 +2059,7 @@ ahd_freeze_simq(struct ahd_softc *ahd) CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR, CAM_REQUEUE_REQ); } + ahd_unlock(ahd, &s); } void @@ -2344,8 +2364,9 @@ done: ahd_name(ahd), dev->active); retval = FAILED; } - } - ahd_unlock(ahd, &flags); + } else + ahd_unlock(ahd, &flags); + return (retval); } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index cb74fccc8100..9cb101345107 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -36,7 +36,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#137 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#166 $ * */ #ifndef _AIC79XX_LINUX_H_ @@ -228,7 +228,6 @@ typedef struct timer_list ahd_timer_t; typedef void ahd_linux_callback_t (u_long); static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg); -static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) @@ -243,12 +242,6 @@ ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) add_timer(timer); } -static __inline void -ahd_scb_timer_reset(struct scb *scb, u_int usec) -{ - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); -} - /***************************** SMP support ************************************/ #include <linux/spinlock.h> @@ -389,7 +382,6 @@ struct ahd_platform_data { spinlock_t spin_lock; u_int qfrozen; - struct timer_list reset_timer; struct semaphore eh_sem; struct Scsi_Host *host; /* pointer to scsi host */ #define AHD_LINUX_NOIRQ ((uint32_t)~0) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index bf360ae021ab..ebbf7e4ff4cc 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -220,10 +220,10 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, *base2 = pci_resource_start(ahd->dev_softc, 3); if (*base == 0 || *base2 == 0) return (ENOMEM); - if (request_region(*base, 256, "aic79xx") == 0) + if (!request_region(*base, 256, "aic79xx")) return (ENOMEM); - if (request_region(*base2, 256, "aic79xx") == 0) { - release_region(*base2, 256); + if (!request_region(*base2, 256, "aic79xx")) { + release_region(*base, 256); return (ENOMEM); } return (0); @@ -237,7 +237,7 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long start; u_long base_page; u_long base_offset; - int error; + int error = 0; if (aic79xx_allow_memio == 0) return (ENOMEM); @@ -245,16 +245,15 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0) return (ENOMEM); - error = 0; start = pci_resource_start(ahd->dev_softc, 1); base_page = start & PAGE_MASK; base_offset = start - base_page; if (start != 0) { *bus_addr = start; - if (request_mem_region(start, 0x1000, "aic79xx") == 0) + if (!request_mem_region(start, 0x1000, "aic79xx")) error = ENOMEM; - if (error == 0) { - *maddr = ioremap_nocache(base_page, base_offset + 256); + if (!error) { + *maddr = ioremap_nocache(base_page, base_offset + 512); if (*maddr == NULL) { error = ENOMEM; release_mem_region(start, 0x1000); @@ -344,7 +343,7 @@ ahd_pci_map_int(struct ahd_softc *ahd) error = request_irq(ahd->dev_softc->irq, ahd_linux_isr, SA_SHIRQ, "aic79xx", ahd); - if (error == 0) + if (!error) ahd->platform_data->irq = ahd->dev_softc->irq; return (-error); diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 196a6344b037..757242e522c2 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $ */ #ifdef __linux__ @@ -950,12 +950,19 @@ ahd_aic790X_setup(struct ahd_softc *ahd) if ((ahd->flags & AHD_HP_BOARD) == 0) AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA); } else { + /* This is revision B and newer. */ + extern uint32_t aic79xx_slowcrc; u_int devconfig1; ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS - | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY; + | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY + | AHD_BUSFREEREV_BUG; ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; + /* If the user requested the the SLOWCRC bit to be set. */ + if (aic79xx_slowcrc) + ahd->features |= AHD_AIC79XXB_SLOWCRC; + /* * Some issues have been resolved in the 7901B. */ diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped index 8763b158856b..2068e00d2c75 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $ */ typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef struct ahd_reg_parse_entry { @@ -2204,6 +2204,20 @@ ahd_reg_print_t ahd_cmdsize_table_print; #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_mk_message_scb_print; +#else +#define ahd_mk_message_scb_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "MK_MESSAGE_SCB", 0x160, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_mk_message_scsiid_print; +#else +#define ahd_mk_message_scsiid_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID", 0x162, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scb_base_print; #else #define ahd_scb_base_print(regvalue, cur_col, wrap) \ @@ -3638,6 +3652,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SEQ_FLAGS2 0x14d #define SELECTOUT_QFROZEN 0x04 #define TARGET_MSG_PENDING 0x02 +#define PENDING_MK_MESSAGE 0x01 #define ALLOCFIFO_SCBPTR 0x14e @@ -3655,6 +3670,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CMDSIZE_TABLE 0x158 +#define MK_MESSAGE_SCB 0x160 + +#define MK_MESSAGE_SCSIID 0x162 + #define SCB_BASE 0x180 #define SCB_RESIDUAL_DATACNT 0x180 @@ -3800,5 +3819,5 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; /* Exported Labels */ -#define LABEL_seq_isr 0x285 -#define LABEL_timer_isr 0x281 +#define LABEL_seq_isr 0x28f +#define LABEL_timer_isr 0x28b diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped index a4137c985376..db38a61a8cb4 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $ */ #include "aic79xx_osm.h" @@ -3382,6 +3382,7 @@ ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) } static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { + { "PENDING_MK_MESSAGE", 0x01, 0x01 }, { "TARGET_MSG_PENDING", 0x02, 0x02 }, { "SELECTOUT_QFROZEN", 0x04, 0x04 } }; @@ -3389,7 +3390,7 @@ static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { int ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", + return (ahd_print_register(SEQ_FLAGS2_parse_table, 3, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap)); } @@ -3450,6 +3451,20 @@ ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) } int +ahd_mk_message_scb_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCB", + 0x160, regvalue, cur_col, wrap)); +} + +int +ahd_mk_message_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "MK_MESSAGE_SCSIID", + 0x162, regvalue, cur_col, wrap)); +} + +int ahd_scb_base_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SCB_BASE", diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped index b1e5365be230..11bed07e90b7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped @@ -2,17 +2,17 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $ */ static uint8_t seqprog[] = { 0xff, 0x02, 0x06, 0x78, - 0x00, 0xea, 0x64, 0x59, + 0x00, 0xea, 0x6e, 0x59, 0x01, 0xea, 0x04, 0x30, 0xff, 0x04, 0x0c, 0x78, - 0x19, 0xea, 0x64, 0x59, + 0x19, 0xea, 0x6e, 0x59, 0x19, 0xea, 0x04, 0x00, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x60, 0x3a, 0x3a, 0x68, 0x04, 0x4d, 0x35, 0x78, @@ -33,15 +33,15 @@ static uint8_t seqprog[] = { 0xff, 0xea, 0x62, 0x02, 0x00, 0xe2, 0x3a, 0x40, 0xff, 0x21, 0x3b, 0x70, - 0x40, 0x4b, 0xaa, 0x69, - 0x00, 0xe2, 0x68, 0x59, - 0x40, 0x4b, 0xaa, 0x69, - 0x20, 0x4b, 0x96, 0x69, + 0x40, 0x4b, 0xb4, 0x69, + 0x00, 0xe2, 0x72, 0x59, + 0x40, 0x4b, 0xb4, 0x69, + 0x20, 0x4b, 0xa0, 0x69, 0xfc, 0x42, 0x44, 0x78, 0x10, 0x40, 0x44, 0x78, - 0x00, 0xe2, 0xfc, 0x5d, + 0x00, 0xe2, 0x10, 0x5e, 0x20, 0x4d, 0x48, 0x78, - 0x00, 0xe2, 0xfc, 0x5d, + 0x00, 0xe2, 0x10, 0x5e, 0x30, 0x3f, 0xc0, 0x09, 0x30, 0xe0, 0x50, 0x60, 0x7f, 0x4a, 0x94, 0x08, @@ -51,7 +51,7 @@ static uint8_t seqprog[] = { 0x00, 0xe2, 0x76, 0x58, 0x00, 0xe2, 0x86, 0x58, 0x00, 0xe2, 0x06, 0x40, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x01, 0x52, 0x84, 0x78, 0x02, 0x58, 0x50, 0x31, @@ -59,26 +59,26 @@ static uint8_t seqprog[] = { 0xff, 0x97, 0x6f, 0x78, 0x50, 0x4b, 0x6a, 0x68, 0xbf, 0x3a, 0x74, 0x08, - 0x14, 0xea, 0x64, 0x59, + 0x14, 0xea, 0x6e, 0x59, 0x14, 0xea, 0x04, 0x00, 0x08, 0x92, 0x25, 0x03, 0xff, 0x90, 0x5f, 0x68, - 0x00, 0xe2, 0x76, 0x5b, + 0x00, 0xe2, 0x8a, 0x5b, 0x00, 0xe2, 0x5e, 0x40, - 0x00, 0xea, 0x5e, 0x59, + 0x00, 0xea, 0x68, 0x59, 0x01, 0xea, 0x00, 0x30, 0x80, 0xf9, 0x7e, 0x68, - 0x00, 0xe2, 0x5c, 0x59, - 0x11, 0xea, 0x5e, 0x59, + 0x00, 0xe2, 0x66, 0x59, + 0x11, 0xea, 0x68, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x80, 0xf9, 0x5c, 0x79, + 0x80, 0xf9, 0x66, 0x79, 0xff, 0xea, 0xd4, 0x0d, - 0x22, 0xea, 0x5e, 0x59, + 0x22, 0xea, 0x68, 0x59, 0x22, 0xea, 0x00, 0x00, 0x10, 0x16, 0x90, 0x78, 0x10, 0x16, 0x2c, 0x00, 0x01, 0x0b, 0xae, 0x32, - 0x18, 0xad, 0x12, 0x79, + 0x18, 0xad, 0x1c, 0x79, 0x04, 0xad, 0xdc, 0x68, 0x80, 0xad, 0x84, 0x78, 0x10, 0xad, 0xaa, 0x78, @@ -118,7 +118,6 @@ static uint8_t seqprog[] = { 0x80, 0x18, 0x30, 0x04, 0x40, 0xad, 0x84, 0x78, 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0xa8, 0x40, 0x31, 0xff, 0xea, 0xc0, 0x09, 0x01, 0x54, 0xa9, 0x1a, 0x00, 0x55, 0xab, 0x22, @@ -128,24 +127,30 @@ static uint8_t seqprog[] = { 0xff, 0xea, 0x5a, 0x03, 0xff, 0xea, 0x5e, 0x03, 0x01, 0x10, 0xd4, 0x31, - 0x10, 0x92, 0x07, 0x69, + 0x02, 0xa8, 0x40, 0x31, + 0x01, 0x92, 0xc1, 0x31, 0x3d, 0x93, 0xc5, 0x29, 0xfe, 0xe2, 0xc4, 0x09, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x50, 0x31, 0x02, 0xa0, 0xda, 0x31, - 0xff, 0xa9, 0x06, 0x71, + 0xff, 0xa9, 0x10, 0x71, + 0x10, 0xe0, 0x0e, 0x79, + 0x10, 0x92, 0x0f, 0x79, + 0x01, 0x4d, 0x9b, 0x02, + 0x02, 0xa0, 0xc0, 0x32, + 0x01, 0x93, 0xc5, 0x36, 0x02, 0xa0, 0x58, 0x37, - 0xff, 0x21, 0x0f, 0x71, + 0xff, 0x21, 0x19, 0x71, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x36, 0x02, 0xa0, 0x40, 0x32, 0x02, 0xa0, 0x44, 0x36, - 0x04, 0x4d, 0x17, 0x69, - 0x40, 0x16, 0x48, 0x69, - 0xff, 0x2d, 0x4d, 0x61, + 0x05, 0x4d, 0x21, 0x69, + 0x40, 0x16, 0x52, 0x69, + 0xff, 0x2d, 0x57, 0x61, 0xff, 0x29, 0x85, 0x70, 0x02, 0x28, 0x55, 0x32, 0x01, 0xea, 0x5a, 0x01, @@ -159,22 +164,22 @@ static uint8_t seqprog[] = { 0x01, 0x56, 0xad, 0x1a, 0xff, 0x54, 0xa9, 0x1a, 0xff, 0x55, 0xab, 0x22, - 0xff, 0x8d, 0x41, 0x71, - 0x80, 0xac, 0x40, 0x71, - 0x20, 0x16, 0x40, 0x69, + 0xff, 0x8d, 0x4b, 0x71, + 0x80, 0xac, 0x4a, 0x71, + 0x20, 0x16, 0x4a, 0x69, 0x00, 0xac, 0xc4, 0x19, - 0x07, 0xe2, 0x40, 0xf9, + 0x07, 0xe2, 0x4a, 0xf9, 0x02, 0x8c, 0x51, 0x31, - 0x00, 0xe2, 0x24, 0x41, + 0x00, 0xe2, 0x2e, 0x41, 0x01, 0xac, 0x08, 0x31, 0x09, 0xea, 0x5a, 0x01, 0x02, 0x8c, 0x51, 0x32, 0xff, 0xea, 0x1a, 0x07, 0x04, 0x24, 0xf9, 0x30, - 0x1d, 0xea, 0x52, 0x41, + 0x1d, 0xea, 0x5c, 0x41, 0x02, 0x2c, 0x51, 0x31, 0x04, 0xa8, 0xf9, 0x30, - 0x19, 0xea, 0x52, 0x41, + 0x19, 0xea, 0x5c, 0x41, 0x06, 0xea, 0x08, 0x81, 0x01, 0xe2, 0x5a, 0x35, 0x02, 0xf2, 0xf0, 0x31, @@ -190,27 +195,27 @@ static uint8_t seqprog[] = { 0x02, 0x20, 0xb9, 0x30, 0x02, 0x20, 0x51, 0x31, 0x4c, 0x93, 0xd7, 0x28, - 0x10, 0x92, 0x77, 0x79, + 0x10, 0x92, 0x81, 0x79, 0x01, 0x6b, 0xc0, 0x30, 0x02, 0x64, 0xc8, 0x00, 0x40, 0x3a, 0x74, 0x04, 0x00, 0xe2, 0x76, 0x58, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x78, 0x61, - 0x20, 0x3f, 0x8e, 0x69, - 0x10, 0x3f, 0x78, 0x79, + 0x30, 0xe0, 0x82, 0x61, + 0x20, 0x3f, 0x98, 0x69, + 0x10, 0x3f, 0x82, 0x79, 0x02, 0xea, 0x7e, 0x00, - 0x00, 0xea, 0x5e, 0x59, + 0x00, 0xea, 0x68, 0x59, 0x01, 0xea, 0x00, 0x30, 0x02, 0x4e, 0x51, 0x35, 0x01, 0xea, 0x7e, 0x00, - 0x11, 0xea, 0x5e, 0x59, + 0x11, 0xea, 0x68, 0x59, 0x11, 0xea, 0x00, 0x00, 0x02, 0x4e, 0x51, 0x35, 0xc0, 0x4a, 0x94, 0x00, - 0x04, 0x41, 0x9c, 0x79, + 0x04, 0x41, 0xa6, 0x79, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, 0x08, 0x3c, 0x78, 0x00, @@ -218,12 +223,12 @@ static uint8_t seqprog[] = { 0x0f, 0x67, 0xc0, 0x09, 0x00, 0x3a, 0x75, 0x02, 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0x14, 0x42, + 0x00, 0xe2, 0x28, 0x42, 0xc0, 0x4a, 0x94, 0x00, - 0x40, 0x3a, 0xc8, 0x69, + 0x40, 0x3a, 0xd2, 0x69, 0x02, 0x55, 0x06, 0x68, - 0x02, 0x56, 0xc8, 0x69, - 0xff, 0x5b, 0xc8, 0x61, + 0x02, 0x56, 0xd2, 0x69, + 0xff, 0x5b, 0xd2, 0x61, 0x02, 0x20, 0x51, 0x31, 0x80, 0xea, 0xb2, 0x01, 0x44, 0xea, 0x00, 0x00, @@ -231,40 +236,45 @@ static uint8_t seqprog[] = { 0x33, 0xea, 0x00, 0x00, 0xff, 0xea, 0xb2, 0x09, 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0xca, 0x79, + 0xff, 0xe0, 0xd4, 0x79, 0x02, 0xac, 0x51, 0x31, - 0x00, 0xe2, 0xc0, 0x41, + 0x00, 0xe2, 0xca, 0x41, 0x02, 0x5e, 0x50, 0x31, 0x02, 0xa8, 0xb8, 0x30, 0x02, 0x5c, 0x50, 0x31, - 0xff, 0xad, 0xdb, 0x71, + 0xff, 0xad, 0xe5, 0x71, 0x02, 0xac, 0x41, 0x31, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0xe4, 0x41, - 0x10, 0x92, 0xe5, 0x69, + 0x00, 0xe2, 0xf8, 0x41, + 0x01, 0x4d, 0xf1, 0x79, + 0x01, 0x62, 0xc1, 0x31, + 0x00, 0x93, 0xf1, 0x61, + 0xfe, 0x4d, 0x9b, 0x0a, + 0x02, 0x60, 0x41, 0x31, + 0x00, 0xe2, 0xdc, 0x41, 0x3d, 0x93, 0xc9, 0x29, 0x01, 0xe4, 0xc8, 0x01, 0x01, 0xea, 0xca, 0x01, 0xff, 0xea, 0xda, 0x01, 0x02, 0x20, 0x51, 0x31, 0x02, 0xae, 0x41, 0x32, - 0xff, 0x21, 0xed, 0x61, + 0xff, 0x21, 0x01, 0x62, 0xff, 0xea, 0x46, 0x02, 0x02, 0x5c, 0x50, 0x31, 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0x04, 0x6e, - 0x01, 0x55, 0x04, 0x6e, - 0x10, 0x92, 0xf9, 0x79, - 0x10, 0x40, 0x02, 0x6a, - 0x01, 0x56, 0x02, 0x7a, + 0x02, 0x56, 0x20, 0x6e, + 0x01, 0x55, 0x20, 0x6e, + 0x10, 0x92, 0x0d, 0x7a, + 0x10, 0x40, 0x16, 0x6a, + 0x01, 0x56, 0x16, 0x7a, 0xff, 0x97, 0x07, 0x78, - 0x13, 0xea, 0x64, 0x59, + 0x13, 0xea, 0x6e, 0x59, 0x13, 0xea, 0x04, 0x00, 0x00, 0xe2, 0x06, 0x40, 0xbf, 0x3a, 0x74, 0x08, - 0x04, 0x41, 0x08, 0x7a, + 0x04, 0x41, 0x1c, 0x7a, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, 0x01, 0x93, 0x75, 0x32, @@ -272,108 +282,108 @@ static uint8_t seqprog[] = { 0x40, 0xea, 0x72, 0x02, 0x08, 0x3c, 0x78, 0x00, 0x80, 0xea, 0x6e, 0x02, - 0x00, 0xe2, 0xe2, 0x5b, + 0x00, 0xe2, 0xf6, 0x5b, 0x01, 0x3c, 0xc1, 0x31, - 0x9f, 0xe0, 0x84, 0x7c, - 0x80, 0xe0, 0x28, 0x72, - 0xa0, 0xe0, 0x64, 0x72, - 0xc0, 0xe0, 0x5a, 0x72, - 0xe0, 0xe0, 0x94, 0x72, - 0x01, 0xea, 0x64, 0x59, + 0x9f, 0xe0, 0x98, 0x7c, + 0x80, 0xe0, 0x3c, 0x72, + 0xa0, 0xe0, 0x78, 0x72, + 0xc0, 0xe0, 0x6e, 0x72, + 0xe0, 0xe0, 0xa8, 0x72, + 0x01, 0xea, 0x6e, 0x59, 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x14, 0x42, - 0x80, 0x39, 0x2f, 0x7a, - 0x03, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x28, 0x42, + 0x80, 0x39, 0x43, 0x7a, + 0x03, 0xea, 0x6e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0xee, 0x00, 0x36, 0x6a, + 0xee, 0x00, 0x4a, 0x6a, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x02, 0xa8, 0x9c, 0x32, - 0x00, 0xe2, 0x7e, 0x59, + 0x00, 0xe2, 0x88, 0x59, 0xef, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x46, 0x52, + 0x00, 0xe2, 0x5a, 0x52, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x4c, 0x42, + 0x00, 0xe2, 0x60, 0x42, 0x01, 0x96, 0xd1, 0x30, 0x10, 0x80, 0x89, 0x31, 0x20, 0xea, 0x32, 0x00, 0xbf, 0x39, 0x73, 0x0a, - 0x10, 0x4c, 0x56, 0x6a, - 0x20, 0x19, 0x4e, 0x6a, - 0x20, 0x19, 0x52, 0x6a, - 0x02, 0x4d, 0x14, 0x6a, + 0x10, 0x4c, 0x6a, 0x6a, + 0x20, 0x19, 0x62, 0x6a, + 0x20, 0x19, 0x66, 0x6a, + 0x02, 0x4d, 0x28, 0x6a, 0x40, 0x39, 0x73, 0x02, - 0x00, 0xe2, 0x14, 0x42, - 0x80, 0x39, 0xd5, 0x6a, + 0x00, 0xe2, 0x28, 0x42, + 0x80, 0x39, 0xe9, 0x6a, 0x01, 0x44, 0x10, 0x33, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0x14, 0x42, + 0x00, 0xe2, 0x28, 0x42, 0x10, 0xea, 0x80, 0x00, 0x01, 0x37, 0xc5, 0x31, - 0x80, 0xe2, 0x80, 0x62, - 0x10, 0x92, 0xa5, 0x6a, + 0x80, 0xe2, 0x94, 0x62, + 0x10, 0x92, 0xb9, 0x6a, 0xc0, 0x94, 0xc5, 0x01, - 0x40, 0x92, 0x71, 0x6a, + 0x40, 0x92, 0x85, 0x6a, 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0x92, 0x85, 0x7a, + 0x20, 0x92, 0x99, 0x7a, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xe2, 0x5b, - 0xa0, 0x3c, 0x8d, 0x62, + 0x00, 0xe2, 0xf6, 0x5b, + 0xa0, 0x3c, 0xa1, 0x62, 0x23, 0x92, 0x89, 0x08, - 0x00, 0xe2, 0xe2, 0x5b, - 0xa0, 0x3c, 0x8d, 0x62, - 0x00, 0xa8, 0x84, 0x42, - 0xff, 0xe2, 0x84, 0x62, - 0x00, 0xe2, 0xa4, 0x42, + 0x00, 0xe2, 0xf6, 0x5b, + 0xa0, 0x3c, 0xa1, 0x62, + 0x00, 0xa8, 0x98, 0x42, + 0xff, 0xe2, 0x98, 0x62, + 0x00, 0xe2, 0xb8, 0x42, 0x40, 0xea, 0x98, 0x00, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xe2, 0x5b, - 0xa0, 0x3c, 0x63, 0x72, + 0x00, 0xe2, 0xf6, 0x5b, + 0xa0, 0x3c, 0x77, 0x72, 0x40, 0xea, 0x98, 0x00, 0x01, 0x37, 0x95, 0x32, 0x08, 0xea, 0x6e, 0x02, - 0x00, 0xe2, 0x14, 0x42, - 0xe0, 0xea, 0xfe, 0x5b, - 0x80, 0xe0, 0xe0, 0x6a, - 0x04, 0xe0, 0x92, 0x73, - 0x02, 0xe0, 0xc4, 0x73, - 0x00, 0xea, 0x3e, 0x73, - 0x03, 0xe0, 0xd4, 0x73, - 0x23, 0xe0, 0xb6, 0x72, - 0x08, 0xe0, 0xdc, 0x72, - 0x00, 0xe2, 0xe2, 0x5b, - 0x07, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x28, 0x42, + 0xe0, 0xea, 0x12, 0x5c, + 0x80, 0xe0, 0xf4, 0x6a, + 0x04, 0xe0, 0xa6, 0x73, + 0x02, 0xe0, 0xd8, 0x73, + 0x00, 0xea, 0x52, 0x73, + 0x03, 0xe0, 0xe8, 0x73, + 0x23, 0xe0, 0xca, 0x72, + 0x08, 0xe0, 0xf0, 0x72, + 0x00, 0xe2, 0xf6, 0x5b, + 0x07, 0xea, 0x6e, 0x59, 0x07, 0xea, 0x04, 0x00, - 0x08, 0x48, 0x15, 0x72, - 0x04, 0x48, 0xb3, 0x62, + 0x08, 0x48, 0x29, 0x72, + 0x04, 0x48, 0xc7, 0x62, 0x01, 0x49, 0x89, 0x30, - 0x00, 0xe2, 0xa4, 0x42, + 0x00, 0xe2, 0xb8, 0x42, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xa4, 0x42, + 0x00, 0xe2, 0xb8, 0x42, 0x01, 0x00, 0x6c, 0x32, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x4c, 0x3a, 0xc1, 0x28, 0x01, 0x64, 0xc0, 0x31, - 0x00, 0x36, 0x5f, 0x59, + 0x00, 0x36, 0x69, 0x59, 0x01, 0x36, 0x01, 0x30, - 0x01, 0xe0, 0xda, 0x7a, - 0xa0, 0xea, 0xf4, 0x5b, - 0x01, 0xa0, 0xda, 0x62, - 0x01, 0x84, 0xcf, 0x7a, - 0x01, 0x95, 0xdd, 0x6a, - 0x05, 0xea, 0x64, 0x59, + 0x01, 0xe0, 0xee, 0x7a, + 0xa0, 0xea, 0x08, 0x5c, + 0x01, 0xa0, 0xee, 0x62, + 0x01, 0x84, 0xe3, 0x7a, + 0x01, 0x95, 0xf1, 0x6a, + 0x05, 0xea, 0x6e, 0x59, 0x05, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xdc, 0x42, - 0x03, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0xf0, 0x42, + 0x03, 0xea, 0x6e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xdc, 0x42, - 0x07, 0xea, 0x06, 0x5c, + 0x00, 0xe2, 0xf0, 0x42, + 0x07, 0xea, 0x1a, 0x5c, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x14, 0x42, + 0x00, 0xe2, 0x28, 0x42, 0x3f, 0xe0, 0x76, 0x0a, 0xc0, 0x3a, 0xc1, 0x09, 0x00, 0x3b, 0x51, 0x01, @@ -384,54 +394,54 @@ static uint8_t seqprog[] = { 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x40, 0x31, - 0xff, 0xa1, 0xfc, 0x72, + 0xff, 0xa1, 0x10, 0x73, 0x02, 0xe8, 0xda, 0x31, 0x02, 0xa0, 0x50, 0x31, - 0x00, 0xe2, 0x1e, 0x43, + 0x00, 0xe2, 0x32, 0x43, 0x80, 0x39, 0x73, 0x02, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xe2, 0x5b, + 0x00, 0xe2, 0xf6, 0x5b, 0x01, 0x39, 0x73, 0x02, - 0xe0, 0x3c, 0x39, 0x63, + 0xe0, 0x3c, 0x4d, 0x63, 0x02, 0x39, 0x73, 0x02, - 0x20, 0x46, 0x32, 0x63, + 0x20, 0x46, 0x46, 0x63, 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0xf4, 0x5b, - 0x04, 0x92, 0x19, 0x7b, + 0xa8, 0xea, 0x08, 0x5c, + 0x04, 0x92, 0x2d, 0x7b, 0x01, 0x3a, 0xc1, 0x31, - 0x00, 0x93, 0x19, 0x63, + 0x00, 0x93, 0x2d, 0x63, 0x01, 0x3b, 0xc1, 0x31, - 0x00, 0x94, 0x23, 0x73, + 0x00, 0x94, 0x37, 0x73, 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0x0e, 0x6b, - 0x00, 0xe2, 0x32, 0x43, + 0xff, 0xa9, 0x22, 0x6b, + 0x00, 0xe2, 0x46, 0x43, 0x10, 0x39, 0x73, 0x02, - 0x04, 0x92, 0x33, 0x7b, + 0x04, 0x92, 0x47, 0x7b, 0xfb, 0x92, 0x25, 0x0b, 0xff, 0xea, 0x72, 0x0a, - 0x01, 0xa4, 0x2d, 0x6b, + 0x01, 0xa4, 0x41, 0x6b, 0x02, 0xa8, 0x9c, 0x32, - 0x00, 0xe2, 0x7e, 0x59, - 0x10, 0x92, 0xdd, 0x7a, - 0xff, 0xea, 0x06, 0x5c, - 0x00, 0xe2, 0xdc, 0x42, - 0x04, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x88, 0x59, + 0x10, 0x92, 0xf1, 0x7a, + 0xff, 0xea, 0x1a, 0x5c, + 0x00, 0xe2, 0xf0, 0x42, + 0x04, 0xea, 0x6e, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xdc, 0x42, - 0x04, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0xf0, 0x42, + 0x04, 0xea, 0x6e, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x14, 0x42, - 0x08, 0x92, 0xd5, 0x7a, - 0xc0, 0x39, 0x49, 0x7b, - 0x80, 0x39, 0xd5, 0x6a, - 0xff, 0x88, 0x49, 0x6b, - 0x40, 0x39, 0xd5, 0x6a, - 0x10, 0x92, 0x4f, 0x7b, - 0x0a, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x28, 0x42, + 0x08, 0x92, 0xe9, 0x7a, + 0xc0, 0x39, 0x5d, 0x7b, + 0x80, 0x39, 0xe9, 0x6a, + 0xff, 0x88, 0x5d, 0x6b, + 0x40, 0x39, 0xe9, 0x6a, + 0x10, 0x92, 0x63, 0x7b, + 0x0a, 0xea, 0x6e, 0x59, 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x6e, 0x5b, - 0x00, 0xe2, 0xae, 0x43, - 0x50, 0x4b, 0x56, 0x6b, + 0x00, 0xe2, 0x82, 0x5b, + 0x00, 0xe2, 0xc2, 0x43, + 0x50, 0x4b, 0x6a, 0x6b, 0xbf, 0x3a, 0x74, 0x08, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, @@ -441,31 +451,31 @@ static uint8_t seqprog[] = { 0x01, 0xfa, 0xc0, 0x35, 0x02, 0xa8, 0x90, 0x32, 0x02, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x02, 0x48, 0x51, 0x31, 0xff, 0x90, 0x85, 0x68, - 0xff, 0x88, 0x7b, 0x6b, - 0x01, 0xa4, 0x77, 0x6b, - 0x02, 0xa4, 0x7f, 0x6b, - 0x01, 0x84, 0x7f, 0x7b, + 0xff, 0x88, 0x8f, 0x6b, + 0x01, 0xa4, 0x8b, 0x6b, + 0x02, 0xa4, 0x93, 0x6b, + 0x01, 0x84, 0x93, 0x7b, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0x7f, 0x73, - 0x00, 0xe2, 0x52, 0x5b, + 0xff, 0x88, 0x93, 0x73, + 0x00, 0xe2, 0x66, 0x5b, 0x02, 0xa8, 0x20, 0x33, 0x04, 0xa4, 0x49, 0x03, 0xff, 0xea, 0x1a, 0x03, - 0xff, 0x2d, 0x8b, 0x63, + 0xff, 0x2d, 0x9f, 0x63, 0x02, 0xa8, 0x58, 0x32, 0x02, 0xa8, 0x5c, 0x36, 0x02, 0xa8, 0x40, 0x31, 0x02, 0x2e, 0x51, 0x31, 0x02, 0xa0, 0x18, 0x33, 0x02, 0xa0, 0x5c, 0x36, - 0xc0, 0x39, 0xd5, 0x6a, + 0xc0, 0x39, 0xe9, 0x6a, 0x04, 0x92, 0x25, 0x03, - 0x20, 0x92, 0xaf, 0x6b, + 0x20, 0x92, 0xc3, 0x6b, 0x02, 0xa8, 0x40, 0x31, 0xc0, 0x3a, 0xc1, 0x09, 0x00, 0x3b, 0x51, 0x01, @@ -480,60 +490,60 @@ static uint8_t seqprog[] = { 0xf7, 0x57, 0xae, 0x08, 0x08, 0xea, 0x98, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0xee, 0x00, 0xb8, 0x6b, + 0xee, 0x00, 0xcc, 0x6b, 0x02, 0xea, 0xb4, 0x00, 0xc0, 0xea, 0x72, 0x02, - 0x09, 0x4c, 0xba, 0x7b, + 0x09, 0x4c, 0xce, 0x7b, 0x01, 0xea, 0x78, 0x02, 0x08, 0x4c, 0x06, 0x68, - 0x0b, 0xea, 0x64, 0x59, + 0x0b, 0xea, 0x6e, 0x59, 0x0b, 0xea, 0x04, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x39, 0x15, 0x7a, - 0x00, 0xe2, 0xcc, 0x5b, - 0x00, 0xe2, 0x14, 0x42, - 0x01, 0x84, 0xd1, 0x7b, + 0x20, 0x39, 0x29, 0x7a, + 0x00, 0xe2, 0xe0, 0x5b, + 0x00, 0xe2, 0x28, 0x42, + 0x01, 0x84, 0xe5, 0x7b, 0x01, 0xa4, 0x49, 0x07, 0x08, 0x60, 0x30, 0x33, 0x08, 0x80, 0x41, 0x37, 0xdf, 0x39, 0x73, 0x0a, - 0xee, 0x00, 0xde, 0x6b, + 0xee, 0x00, 0xf2, 0x6b, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x7e, 0x59, - 0x00, 0xe2, 0xdc, 0x42, - 0xff, 0x42, 0xee, 0x6b, - 0x01, 0x41, 0xe2, 0x6b, - 0x02, 0x41, 0xe2, 0x7b, - 0xff, 0x42, 0xee, 0x6b, - 0x01, 0x41, 0xe2, 0x6b, - 0x02, 0x41, 0xe2, 0x7b, - 0xff, 0x42, 0xee, 0x7b, - 0x04, 0x4c, 0xe2, 0x6b, + 0x00, 0xe2, 0x88, 0x59, + 0x00, 0xe2, 0xf0, 0x42, + 0xff, 0x42, 0x02, 0x6c, + 0x01, 0x41, 0xf6, 0x6b, + 0x02, 0x41, 0xf6, 0x7b, + 0xff, 0x42, 0x02, 0x6c, + 0x01, 0x41, 0xf6, 0x6b, + 0x02, 0x41, 0xf6, 0x7b, + 0xff, 0x42, 0x02, 0x7c, + 0x04, 0x4c, 0xf6, 0x6b, 0xe0, 0x41, 0x78, 0x0e, 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0xf6, 0x7b, - 0x04, 0x4c, 0xf6, 0x6b, + 0xff, 0x42, 0x0a, 0x7c, + 0x04, 0x4c, 0x0a, 0x6c, 0xe0, 0x41, 0x78, 0x0a, - 0xe0, 0x3c, 0x15, 0x62, + 0xe0, 0x3c, 0x29, 0x62, 0xff, 0xea, 0xca, 0x09, 0x01, 0xe2, 0xc8, 0x31, 0x01, 0x46, 0xda, 0x35, 0x01, 0x44, 0xd4, 0x35, 0x10, 0xea, 0x80, 0x00, 0x01, 0xe2, 0x6e, 0x36, - 0x04, 0xa6, 0x0e, 0x7c, + 0x04, 0xa6, 0x22, 0x7c, 0xff, 0xea, 0x5a, 0x09, 0xff, 0xea, 0x4c, 0x0d, - 0x01, 0xa6, 0x3a, 0x6c, + 0x01, 0xa6, 0x4e, 0x6c, 0x10, 0xad, 0x84, 0x78, - 0x80, 0xad, 0x32, 0x6c, + 0x80, 0xad, 0x46, 0x6c, 0x08, 0xad, 0x84, 0x68, - 0x20, 0x19, 0x26, 0x7c, + 0x20, 0x19, 0x3a, 0x7c, 0x80, 0xea, 0xb2, 0x01, 0x11, 0x00, 0x00, 0x10, - 0x02, 0xa6, 0x22, 0x7c, + 0x02, 0xa6, 0x36, 0x7c, 0xff, 0xea, 0xb2, 0x0d, 0x11, 0x00, 0x00, 0x10, 0xff, 0xea, 0xb2, 0x09, @@ -561,7 +571,7 @@ static uint8_t seqprog[] = { 0x00, 0x86, 0x0d, 0x23, 0x00, 0x87, 0x0f, 0x23, 0x01, 0x84, 0xc5, 0x31, - 0x80, 0x83, 0x5d, 0x7c, + 0x80, 0x83, 0x71, 0x7c, 0x02, 0xe2, 0xc4, 0x01, 0xff, 0xea, 0x4c, 0x09, 0x01, 0xe2, 0x36, 0x30, @@ -572,75 +582,75 @@ static uint8_t seqprog[] = { 0xfe, 0xa6, 0x4c, 0x0d, 0x0b, 0x98, 0xe1, 0x30, 0xfd, 0xa4, 0x49, 0x09, - 0x80, 0xa3, 0x71, 0x7c, + 0x80, 0xa3, 0x85, 0x7c, 0x02, 0xa4, 0x48, 0x01, 0x01, 0xa4, 0x36, 0x30, 0xa8, 0xea, 0x32, 0x00, 0xfd, 0xa4, 0x49, 0x0b, 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0x7d, 0x6c, + 0x80, 0x83, 0x91, 0x6c, 0x02, 0xea, 0x4c, 0x05, 0xff, 0xea, 0x4c, 0x0d, - 0x00, 0xe2, 0x56, 0x59, - 0x02, 0xa6, 0x10, 0x6c, + 0x00, 0xe2, 0x60, 0x59, + 0x02, 0xa6, 0x24, 0x6c, 0x80, 0xf9, 0xf2, 0x05, - 0xc0, 0x39, 0x8b, 0x7c, - 0x03, 0xea, 0x64, 0x59, + 0xc0, 0x39, 0x9f, 0x7c, + 0x03, 0xea, 0x6e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x20, 0x39, 0xaf, 0x7c, - 0x01, 0x84, 0x95, 0x6c, - 0x06, 0xea, 0x64, 0x59, + 0x20, 0x39, 0xc3, 0x7c, + 0x01, 0x84, 0xa9, 0x6c, + 0x06, 0xea, 0x6e, 0x59, 0x06, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xb2, 0x44, + 0x00, 0xe2, 0xc6, 0x44, 0x01, 0x00, 0x6c, 0x32, - 0xee, 0x00, 0x9e, 0x6c, + 0xee, 0x00, 0xb2, 0x6c, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x5e, 0x59, + 0x33, 0xea, 0x68, 0x59, 0x33, 0xea, 0x00, 0x00, 0x80, 0x3d, 0x7a, 0x00, - 0xfc, 0x42, 0xa0, 0x7c, + 0xfc, 0x42, 0xb4, 0x7c, 0x7f, 0x3d, 0x7a, 0x08, - 0x00, 0x36, 0x5f, 0x59, + 0x00, 0x36, 0x69, 0x59, 0x01, 0x36, 0x01, 0x30, - 0x09, 0xea, 0x64, 0x59, + 0x09, 0xea, 0x6e, 0x59, 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x14, 0x42, - 0x01, 0xa4, 0x95, 0x6c, - 0x00, 0xe2, 0x68, 0x5c, + 0x00, 0xe2, 0x28, 0x42, + 0x01, 0xa4, 0xa9, 0x6c, + 0x00, 0xe2, 0x7c, 0x5c, 0x20, 0x39, 0x73, 0x02, 0x01, 0x00, 0x6c, 0x32, - 0x02, 0xa6, 0xba, 0x7c, - 0x00, 0xe2, 0x7e, 0x5c, + 0x02, 0xa6, 0xce, 0x7c, + 0x00, 0xe2, 0x92, 0x5c, 0x00, 0xe2, 0x76, 0x58, 0x00, 0xe2, 0x86, 0x58, 0x00, 0xe2, 0x5a, 0x58, - 0x00, 0x36, 0x5f, 0x59, + 0x00, 0x36, 0x69, 0x59, 0x01, 0x36, 0x01, 0x30, - 0x20, 0x19, 0xba, 0x6c, - 0x00, 0xe2, 0xea, 0x5c, - 0x04, 0x19, 0xd4, 0x6c, + 0x20, 0x19, 0xce, 0x6c, + 0x00, 0xe2, 0xfe, 0x5c, + 0x04, 0x19, 0xe8, 0x6c, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0xd5, 0x7c, - 0x01, 0x1b, 0xce, 0x7c, - 0x01, 0x1a, 0xd4, 0x6c, - 0x00, 0xe2, 0x84, 0x44, - 0x80, 0x4b, 0xda, 0x6c, - 0x01, 0x4c, 0xd6, 0x7c, - 0x03, 0x42, 0x84, 0x6c, - 0x00, 0xe2, 0x0a, 0x5c, + 0x01, 0x84, 0xe9, 0x7c, + 0x01, 0x1b, 0xe2, 0x7c, + 0x01, 0x1a, 0xe8, 0x6c, + 0x00, 0xe2, 0x98, 0x44, + 0x80, 0x4b, 0xee, 0x6c, + 0x01, 0x4c, 0xea, 0x7c, + 0x03, 0x42, 0x98, 0x6c, + 0x00, 0xe2, 0x1e, 0x5c, 0x80, 0xf9, 0xf2, 0x01, - 0x04, 0x39, 0x15, 0x7a, - 0x00, 0xe2, 0x14, 0x42, - 0x08, 0x5d, 0xf2, 0x6c, + 0x04, 0x39, 0x29, 0x7a, + 0x00, 0xe2, 0x28, 0x42, + 0x08, 0x5d, 0x06, 0x6d, 0x00, 0xe2, 0x76, 0x58, - 0x00, 0x36, 0x5f, 0x59, + 0x00, 0x36, 0x69, 0x59, 0x01, 0x36, 0x01, 0x30, - 0x02, 0x1b, 0xe2, 0x7c, - 0x08, 0x5d, 0xf0, 0x7c, + 0x02, 0x1b, 0xf6, 0x7c, + 0x08, 0x5d, 0x04, 0x7d, 0x03, 0x68, 0x00, 0x37, 0x01, 0x84, 0x09, 0x07, - 0x80, 0x1b, 0xfc, 0x7c, - 0x80, 0x84, 0xfd, 0x6c, + 0x80, 0x1b, 0x10, 0x7d, + 0x80, 0x84, 0x11, 0x6d, 0xff, 0x85, 0x0b, 0x1b, 0xff, 0x86, 0x0d, 0x23, 0xff, 0x87, 0x0f, 0x23, @@ -652,161 +662,164 @@ static uint8_t seqprog[] = { 0xf9, 0xd9, 0xb2, 0x0d, 0x01, 0xd9, 0xb2, 0x05, 0x01, 0x52, 0x48, 0x31, - 0x20, 0xa4, 0x26, 0x7d, - 0x20, 0x5b, 0x26, 0x7d, - 0x80, 0xf9, 0x34, 0x7d, + 0x20, 0xa4, 0x3a, 0x7d, + 0x20, 0x5b, 0x3a, 0x7d, + 0x80, 0xf9, 0x48, 0x7d, 0x02, 0xea, 0xb4, 0x00, 0x11, 0x00, 0x00, 0x10, - 0x04, 0x19, 0x40, 0x7d, + 0x04, 0x19, 0x54, 0x7d, 0xdf, 0x19, 0x32, 0x08, - 0x60, 0x5b, 0x40, 0x6d, - 0x01, 0x4c, 0x1a, 0x7d, + 0x60, 0x5b, 0x54, 0x6d, + 0x01, 0x4c, 0x2e, 0x7d, 0x20, 0x19, 0x32, 0x00, 0x01, 0xd9, 0xb2, 0x05, 0x02, 0xea, 0xb4, 0x00, 0x01, 0xd9, 0xb2, 0x05, - 0x10, 0x5b, 0x38, 0x6d, - 0x08, 0x5b, 0x42, 0x6d, - 0x20, 0x5b, 0x32, 0x6d, - 0x02, 0x5b, 0x62, 0x6d, - 0x0e, 0xea, 0x64, 0x59, + 0x10, 0x5b, 0x4c, 0x6d, + 0x08, 0x5b, 0x56, 0x6d, + 0x20, 0x5b, 0x46, 0x6d, + 0x02, 0x5b, 0x76, 0x6d, + 0x0e, 0xea, 0x6e, 0x59, 0x0e, 0xea, 0x04, 0x00, - 0x80, 0xf9, 0x22, 0x6d, + 0x80, 0xf9, 0x36, 0x6d, 0xdf, 0x5c, 0xb8, 0x08, 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0x1d, 0x6e, - 0x00, 0xe2, 0x68, 0x5c, - 0x00, 0xe2, 0x6c, 0x5d, + 0x01, 0xa4, 0x37, 0x6e, + 0x00, 0xe2, 0x7c, 0x5c, + 0x00, 0xe2, 0x80, 0x5d, 0x01, 0x90, 0x21, 0x1b, 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0x52, 0x5b, + 0x00, 0xe2, 0x66, 0x5b, 0xf3, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x50, 0x55, - 0x80, 0x96, 0x51, 0x6d, - 0x0f, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x64, 0x55, + 0x80, 0x96, 0x65, 0x6d, + 0x0f, 0xea, 0x6e, 0x59, 0x0f, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x58, 0x45, + 0x00, 0xe2, 0x6c, 0x45, 0x04, 0x8c, 0xe1, 0x30, 0x01, 0xea, 0xf2, 0x00, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0xff, 0x97, 0x5f, 0x7d, - 0x14, 0xea, 0x64, 0x59, + 0xff, 0x97, 0x73, 0x7d, + 0x14, 0xea, 0x6e, 0x59, 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xce, 0x5d, + 0x00, 0xe2, 0xe2, 0x5d, 0x01, 0xd9, 0xb2, 0x05, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0xc6, 0x5d, + 0x00, 0xe2, 0xda, 0x5d, 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa6, 0x7c, 0x7d, - 0x00, 0xe2, 0x56, 0x59, - 0x20, 0x5b, 0x8a, 0x6d, - 0xfc, 0x42, 0x76, 0x7d, - 0x10, 0x40, 0x78, 0x6d, - 0x20, 0x4d, 0x7a, 0x7d, - 0x08, 0x5d, 0x8a, 0x6d, - 0x02, 0xa6, 0x10, 0x6c, - 0x00, 0xe2, 0x56, 0x59, - 0x20, 0x5b, 0x8a, 0x6d, - 0x01, 0x1b, 0xaa, 0x6d, - 0xfc, 0x42, 0x86, 0x7d, - 0x10, 0x40, 0x88, 0x6d, + 0x02, 0xa6, 0x90, 0x7d, + 0x00, 0xe2, 0x60, 0x59, + 0x20, 0x5b, 0x9e, 0x6d, + 0xfc, 0x42, 0x8a, 0x7d, + 0x10, 0x40, 0x8c, 0x6d, + 0x20, 0x4d, 0x8e, 0x7d, + 0x08, 0x5d, 0x9e, 0x6d, + 0x02, 0xa6, 0x24, 0x6c, + 0x00, 0xe2, 0x60, 0x59, + 0x20, 0x5b, 0x9e, 0x6d, + 0x01, 0x1b, 0xbe, 0x6d, + 0xfc, 0x42, 0x9a, 0x7d, + 0x10, 0x40, 0x9c, 0x6d, 0x20, 0x4d, 0x84, 0x78, 0x08, 0x5d, 0x84, 0x78, 0x02, 0x19, 0x32, 0x00, 0x01, 0x5b, 0x40, 0x31, - 0x00, 0xe2, 0xea, 0x5c, - 0x00, 0xe2, 0xcc, 0x5b, + 0x00, 0xe2, 0xfe, 0x5c, + 0x00, 0xe2, 0xe0, 0x5b, 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0x0a, 0x5c, + 0x00, 0xe2, 0x1e, 0x5c, 0x20, 0x5c, 0xb8, 0x00, - 0x04, 0x19, 0xa0, 0x6d, - 0x01, 0x1a, 0xa0, 0x6d, - 0x00, 0xe2, 0x56, 0x59, + 0x04, 0x19, 0xb4, 0x6d, + 0x01, 0x1a, 0xb4, 0x6d, + 0x00, 0xe2, 0x60, 0x59, 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0x04, 0x7e, + 0x20, 0xa0, 0x18, 0x7e, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x63, 0x6b, + 0x08, 0x92, 0x77, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0xa4, 0x49, 0x03, - 0x40, 0x5b, 0xba, 0x6d, - 0x00, 0xe2, 0x56, 0x59, - 0x40, 0x5b, 0xba, 0x6d, - 0x04, 0x5d, 0x1e, 0x7e, - 0x01, 0x1a, 0x1e, 0x7e, + 0x40, 0x5b, 0xce, 0x6d, + 0x00, 0xe2, 0x60, 0x59, + 0x40, 0x5b, 0xce, 0x6d, + 0x04, 0x5d, 0x38, 0x7e, + 0x01, 0x1a, 0x38, 0x7e, 0x20, 0x4d, 0x84, 0x78, - 0x40, 0x5b, 0x04, 0x7e, - 0x04, 0x5d, 0x1e, 0x7e, - 0x01, 0x1a, 0x1e, 0x7e, + 0x40, 0x5b, 0x18, 0x7e, + 0x04, 0x5d, 0x38, 0x7e, + 0x01, 0x1a, 0x38, 0x7e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x63, 0x6b, + 0x08, 0x92, 0x77, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x56, 0x59, + 0x00, 0xe2, 0x60, 0x59, 0x01, 0x1b, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x56, 0x59, - 0x01, 0x1b, 0xe2, 0x6d, - 0x40, 0x5b, 0xf0, 0x7d, - 0x01, 0x1b, 0xe2, 0x6d, + 0x00, 0xe2, 0x60, 0x59, + 0x01, 0x1b, 0xf6, 0x6d, + 0x40, 0x5b, 0x04, 0x7e, + 0x01, 0x1b, 0xf6, 0x6d, 0x02, 0x19, 0x32, 0x00, 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0xea, 0x10, 0x03, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0x62, 0x43, - 0x01, 0x1a, 0xec, 0x7d, - 0x40, 0x5b, 0xe8, 0x7d, - 0x01, 0x1a, 0xd6, 0x6d, + 0x00, 0xe2, 0x76, 0x43, + 0x01, 0x1a, 0x00, 0x7e, + 0x40, 0x5b, 0xfc, 0x7d, + 0x01, 0x1a, 0xea, 0x6d, 0xfc, 0x42, 0x84, 0x78, - 0x01, 0x1a, 0xf0, 0x6d, - 0x10, 0xea, 0x64, 0x59, + 0x01, 0x1a, 0x04, 0x6e, + 0x10, 0xea, 0x6e, 0x59, 0x10, 0xea, 0x04, 0x00, 0xfc, 0x42, 0x84, 0x78, - 0x10, 0x40, 0xf6, 0x6d, + 0x10, 0x40, 0x0a, 0x6e, 0x20, 0x4d, 0x84, 0x78, - 0x40, 0x5b, 0xd6, 0x6d, + 0x40, 0x5b, 0xea, 0x6d, 0x01, 0x1a, 0x84, 0x78, 0x01, 0x90, 0x21, 0x1b, 0x30, 0x3f, 0xc0, 0x09, 0x30, 0xe0, 0x84, 0x60, 0x40, 0x4b, 0x84, 0x68, 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0x0c, 0x6e, + 0xee, 0x00, 0x20, 0x6e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, 0x02, 0xea, 0xb4, 0x00, 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0x16, 0x6e, - 0x12, 0xea, 0x64, 0x59, + 0x04, 0x41, 0x26, 0x7e, + 0x08, 0xea, 0x98, 0x00, + 0x08, 0x57, 0xae, 0x00, + 0xf3, 0x42, 0x30, 0x6e, + 0x12, 0xea, 0x6e, 0x59, 0x12, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x14, 0x42, - 0x0d, 0xea, 0x64, 0x59, + 0x00, 0xe2, 0x28, 0x42, + 0x0d, 0xea, 0x6e, 0x59, 0x0d, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x14, 0x42, + 0x00, 0xe2, 0x28, 0x42, 0x01, 0x90, 0x21, 0x1b, - 0x11, 0xea, 0x64, 0x59, + 0x11, 0xea, 0x6e, 0x59, 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x52, 0x5b, + 0x00, 0xe2, 0x66, 0x5b, 0x08, 0x5a, 0xb4, 0x00, - 0x00, 0xe2, 0x44, 0x5e, + 0x00, 0xe2, 0x5e, 0x5e, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x56, 0x59, - 0x80, 0x1a, 0x32, 0x7e, - 0x00, 0xe2, 0x44, 0x5e, + 0x00, 0xe2, 0x60, 0x59, + 0x80, 0x1a, 0x4c, 0x7e, + 0x00, 0xe2, 0x5e, 0x5e, 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x38, 0x6e, - 0x08, 0x5a, 0x38, 0x7e, + 0x40, 0x5b, 0x52, 0x6e, + 0x08, 0x5a, 0x52, 0x7e, 0x20, 0x4d, 0x84, 0x78, 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0x04, 0x7e, + 0x40, 0x5b, 0x18, 0x7e, 0xff, 0x90, 0x21, 0x1b, 0x80, 0xf9, 0xf2, 0x01, - 0x08, 0x92, 0x63, 0x6b, + 0x08, 0x92, 0x77, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0x40, 0xe1, 0x30, 0x05, 0x41, 0xe3, 0x98, @@ -1039,138 +1052,138 @@ static struct patch { { ahd_patch0_func, 64, 1, 1 }, { ahd_patch2_func, 67, 1, 2 }, { ahd_patch0_func, 68, 1, 1 }, - { ahd_patch4_func, 116, 1, 1 }, - { ahd_patch2_func, 175, 3, 1 }, - { ahd_patch1_func, 178, 2, 1 }, - { ahd_patch5_func, 180, 1, 1 }, - { ahd_patch2_func, 189, 1, 2 }, - { ahd_patch0_func, 190, 1, 1 }, - { ahd_patch6_func, 191, 2, 2 }, - { ahd_patch0_func, 193, 6, 3 }, - { ahd_patch2_func, 196, 1, 2 }, - { ahd_patch0_func, 197, 1, 1 }, - { ahd_patch2_func, 200, 1, 2 }, - { ahd_patch0_func, 201, 1, 1 }, - { ahd_patch3_func, 203, 1, 1 }, - { ahd_patch7_func, 204, 3, 1 }, - { ahd_patch3_func, 213, 1, 1 }, - { ahd_patch5_func, 214, 16, 2 }, - { ahd_patch0_func, 230, 1, 1 }, - { ahd_patch8_func, 250, 2, 1 }, - { ahd_patch1_func, 254, 1, 2 }, - { ahd_patch0_func, 255, 1, 1 }, - { ahd_patch7_func, 258, 3, 1 }, - { ahd_patch1_func, 273, 1, 2 }, - { ahd_patch0_func, 274, 1, 1 }, - { ahd_patch1_func, 277, 1, 2 }, - { ahd_patch0_func, 278, 1, 1 }, - { ahd_patch2_func, 281, 1, 2 }, - { ahd_patch0_func, 282, 1, 1 }, - { ahd_patch9_func, 295, 2, 2 }, - { ahd_patch0_func, 297, 1, 1 }, - { ahd_patch1_func, 339, 1, 2 }, - { ahd_patch0_func, 340, 1, 1 }, - { ahd_patch2_func, 348, 1, 2 }, - { ahd_patch0_func, 349, 1, 1 }, - { ahd_patch2_func, 352, 1, 2 }, - { ahd_patch0_func, 353, 1, 1 }, - { ahd_patch1_func, 359, 1, 2 }, - { ahd_patch0_func, 360, 1, 1 }, - { ahd_patch1_func, 362, 1, 2 }, + { ahd_patch4_func, 115, 1, 1 }, + { ahd_patch2_func, 180, 3, 1 }, + { ahd_patch1_func, 183, 2, 1 }, + { ahd_patch5_func, 185, 1, 1 }, + { ahd_patch2_func, 194, 1, 2 }, + { ahd_patch0_func, 195, 1, 1 }, + { ahd_patch6_func, 196, 2, 2 }, + { ahd_patch0_func, 198, 6, 3 }, + { ahd_patch2_func, 201, 1, 2 }, + { ahd_patch0_func, 202, 1, 1 }, + { ahd_patch2_func, 205, 1, 2 }, + { ahd_patch0_func, 206, 1, 1 }, + { ahd_patch3_func, 208, 1, 1 }, + { ahd_patch7_func, 209, 3, 1 }, + { ahd_patch3_func, 218, 1, 1 }, + { ahd_patch5_func, 219, 16, 2 }, + { ahd_patch0_func, 235, 1, 1 }, + { ahd_patch8_func, 260, 2, 1 }, + { ahd_patch1_func, 264, 1, 2 }, + { ahd_patch0_func, 265, 1, 1 }, + { ahd_patch7_func, 268, 3, 1 }, + { ahd_patch1_func, 283, 1, 2 }, + { ahd_patch0_func, 284, 1, 1 }, + { ahd_patch1_func, 287, 1, 2 }, + { ahd_patch0_func, 288, 1, 1 }, + { ahd_patch2_func, 291, 1, 2 }, + { ahd_patch0_func, 292, 1, 1 }, + { ahd_patch9_func, 305, 2, 2 }, + { ahd_patch0_func, 307, 1, 1 }, + { ahd_patch1_func, 349, 1, 2 }, + { ahd_patch0_func, 350, 1, 1 }, + { ahd_patch2_func, 358, 1, 2 }, + { ahd_patch0_func, 359, 1, 1 }, + { ahd_patch2_func, 362, 1, 2 }, { ahd_patch0_func, 363, 1, 1 }, - { ahd_patch10_func, 382, 1, 1 }, - { ahd_patch10_func, 385, 1, 1 }, - { ahd_patch10_func, 387, 1, 1 }, - { ahd_patch10_func, 399, 1, 1 }, - { ahd_patch1_func, 409, 1, 2 }, - { ahd_patch0_func, 410, 1, 1 }, - { ahd_patch1_func, 412, 1, 2 }, - { ahd_patch0_func, 413, 1, 1 }, - { ahd_patch1_func, 421, 1, 2 }, - { ahd_patch0_func, 422, 1, 1 }, - { ahd_patch2_func, 435, 1, 2 }, - { ahd_patch0_func, 436, 1, 1 }, - { ahd_patch11_func, 472, 1, 1 }, - { ahd_patch1_func, 480, 1, 2 }, - { ahd_patch0_func, 481, 1, 1 }, - { ahd_patch2_func, 493, 1, 2 }, - { ahd_patch0_func, 494, 1, 1 }, - { ahd_patch12_func, 497, 6, 2 }, - { ahd_patch0_func, 503, 1, 1 }, - { ahd_patch13_func, 524, 7, 1 }, - { ahd_patch14_func, 533, 1, 1 }, - { ahd_patch15_func, 542, 1, 1 }, - { ahd_patch16_func, 543, 1, 2 }, - { ahd_patch0_func, 544, 1, 1 }, - { ahd_patch17_func, 547, 1, 1 }, - { ahd_patch16_func, 548, 1, 1 }, - { ahd_patch18_func, 559, 1, 2 }, - { ahd_patch0_func, 560, 1, 1 }, - { ahd_patch1_func, 579, 1, 2 }, - { ahd_patch0_func, 580, 1, 1 }, - { ahd_patch1_func, 583, 1, 2 }, - { ahd_patch0_func, 584, 1, 1 }, - { ahd_patch2_func, 589, 1, 2 }, + { ahd_patch1_func, 369, 1, 2 }, + { ahd_patch0_func, 370, 1, 1 }, + { ahd_patch1_func, 372, 1, 2 }, + { ahd_patch0_func, 373, 1, 1 }, + { ahd_patch10_func, 392, 1, 1 }, + { ahd_patch10_func, 395, 1, 1 }, + { ahd_patch10_func, 397, 1, 1 }, + { ahd_patch10_func, 409, 1, 1 }, + { ahd_patch1_func, 419, 1, 2 }, + { ahd_patch0_func, 420, 1, 1 }, + { ahd_patch1_func, 422, 1, 2 }, + { ahd_patch0_func, 423, 1, 1 }, + { ahd_patch1_func, 431, 1, 2 }, + { ahd_patch0_func, 432, 1, 1 }, + { ahd_patch2_func, 445, 1, 2 }, + { ahd_patch0_func, 446, 1, 1 }, + { ahd_patch11_func, 482, 1, 1 }, + { ahd_patch1_func, 490, 1, 2 }, + { ahd_patch0_func, 491, 1, 1 }, + { ahd_patch2_func, 503, 1, 2 }, + { ahd_patch0_func, 504, 1, 1 }, + { ahd_patch12_func, 507, 6, 2 }, + { ahd_patch0_func, 513, 1, 1 }, + { ahd_patch13_func, 534, 7, 1 }, + { ahd_patch14_func, 543, 1, 1 }, + { ahd_patch15_func, 552, 1, 1 }, + { ahd_patch16_func, 553, 1, 2 }, + { ahd_patch0_func, 554, 1, 1 }, + { ahd_patch17_func, 557, 1, 1 }, + { ahd_patch16_func, 558, 1, 1 }, + { ahd_patch18_func, 569, 1, 2 }, + { ahd_patch0_func, 570, 1, 1 }, + { ahd_patch1_func, 589, 1, 2 }, { ahd_patch0_func, 590, 1, 1 }, - { ahd_patch2_func, 594, 1, 2 }, - { ahd_patch0_func, 595, 1, 1 }, - { ahd_patch1_func, 596, 1, 2 }, - { ahd_patch0_func, 597, 1, 1 }, - { ahd_patch2_func, 608, 1, 2 }, - { ahd_patch0_func, 609, 1, 1 }, - { ahd_patch19_func, 613, 1, 1 }, - { ahd_patch20_func, 618, 1, 1 }, - { ahd_patch21_func, 619, 2, 1 }, - { ahd_patch20_func, 623, 1, 2 }, - { ahd_patch0_func, 624, 1, 1 }, - { ahd_patch2_func, 627, 1, 2 }, - { ahd_patch0_func, 628, 1, 1 }, - { ahd_patch2_func, 643, 1, 2 }, - { ahd_patch0_func, 644, 1, 1 }, - { ahd_patch13_func, 645, 14, 1 }, - { ahd_patch1_func, 663, 1, 2 }, - { ahd_patch0_func, 664, 1, 1 }, - { ahd_patch13_func, 665, 1, 1 }, - { ahd_patch1_func, 677, 1, 2 }, - { ahd_patch0_func, 678, 1, 1 }, - { ahd_patch1_func, 685, 1, 2 }, - { ahd_patch0_func, 686, 1, 1 }, - { ahd_patch19_func, 709, 1, 1 }, - { ahd_patch19_func, 747, 1, 1 }, - { ahd_patch1_func, 758, 1, 2 }, - { ahd_patch0_func, 759, 1, 1 }, - { ahd_patch1_func, 776, 1, 2 }, - { ahd_patch0_func, 777, 1, 1 }, - { ahd_patch1_func, 779, 1, 2 }, - { ahd_patch0_func, 780, 1, 1 }, - { ahd_patch1_func, 783, 1, 2 }, - { ahd_patch0_func, 784, 1, 1 }, - { ahd_patch22_func, 786, 1, 2 }, - { ahd_patch0_func, 787, 2, 1 }, - { ahd_patch23_func, 790, 4, 2 }, - { ahd_patch0_func, 794, 1, 1 }, - { ahd_patch23_func, 802, 11, 1 } + { ahd_patch1_func, 593, 1, 2 }, + { ahd_patch0_func, 594, 1, 1 }, + { ahd_patch2_func, 599, 1, 2 }, + { ahd_patch0_func, 600, 1, 1 }, + { ahd_patch2_func, 604, 1, 2 }, + { ahd_patch0_func, 605, 1, 1 }, + { ahd_patch1_func, 606, 1, 2 }, + { ahd_patch0_func, 607, 1, 1 }, + { ahd_patch2_func, 618, 1, 2 }, + { ahd_patch0_func, 619, 1, 1 }, + { ahd_patch19_func, 623, 1, 1 }, + { ahd_patch20_func, 628, 1, 1 }, + { ahd_patch21_func, 629, 2, 1 }, + { ahd_patch20_func, 633, 1, 2 }, + { ahd_patch0_func, 634, 1, 1 }, + { ahd_patch2_func, 637, 1, 2 }, + { ahd_patch0_func, 638, 1, 1 }, + { ahd_patch2_func, 653, 1, 2 }, + { ahd_patch0_func, 654, 1, 1 }, + { ahd_patch13_func, 655, 14, 1 }, + { ahd_patch1_func, 673, 1, 2 }, + { ahd_patch0_func, 674, 1, 1 }, + { ahd_patch13_func, 675, 1, 1 }, + { ahd_patch1_func, 687, 1, 2 }, + { ahd_patch0_func, 688, 1, 1 }, + { ahd_patch1_func, 695, 1, 2 }, + { ahd_patch0_func, 696, 1, 1 }, + { ahd_patch19_func, 719, 1, 1 }, + { ahd_patch19_func, 757, 1, 1 }, + { ahd_patch1_func, 768, 1, 2 }, + { ahd_patch0_func, 769, 1, 1 }, + { ahd_patch7_func, 785, 3, 1 }, + { ahd_patch1_func, 789, 1, 2 }, + { ahd_patch0_func, 790, 1, 1 }, + { ahd_patch1_func, 792, 1, 2 }, + { ahd_patch0_func, 793, 1, 1 }, + { ahd_patch1_func, 796, 1, 2 }, + { ahd_patch0_func, 797, 1, 1 }, + { ahd_patch22_func, 799, 1, 2 }, + { ahd_patch0_func, 800, 2, 1 }, + { ahd_patch23_func, 803, 4, 2 }, + { ahd_patch0_func, 807, 1, 1 }, + { ahd_patch23_func, 815, 11, 1 } }; static struct cs { uint16_t begin; uint16_t end; } critical_sections[] = { - { 17, 28 }, - { 29, 30 }, + { 17, 30 }, { 47, 58 }, { 61, 63 }, { 65, 66 }, { 72, 92 }, - { 110, 137 }, - { 138, 175 }, - { 180, 188 }, - { 213, 264 }, - { 425, 433 }, - { 443, 445 }, - { 448, 457 }, - { 709, 739 }, - { 749, 753 } + { 110, 142 }, + { 143, 180 }, + { 185, 193 }, + { 218, 274 }, + { 435, 443 }, + { 453, 455 }, + { 458, 467 }, + { 719, 749 }, + { 759, 763 } }; static const int num_critical_sections = sizeof(critical_sections) diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c index f936b691232f..924102720b14 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $ * * $FreeBSD$ */ @@ -609,10 +609,10 @@ output_listing(char *ifilename) while (line < cur_instr->srcline) { fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " \t%s", buf); line++; } - fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, + fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr, #ifdef __LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], @@ -624,14 +624,23 @@ output_listing(char *ifilename) cur_instr->format.bytes[1], cur_instr->format.bytes[0]); #endif - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t%s", buf); - line++; + /* + * Macro expansions can cause several instructions + * to be output for a single source line. Only + * advance the line once in these cases. + */ + if (line == cur_instr->srcline) { + fgets(buf, sizeof(buf), ifile); + fprintf(listfile, "\t%s", buf); + line++; + } else { + fprintf(listfile, "\n"); + } instrptr++; } /* Dump the remainder of the file */ while(fgets(buf, sizeof(buf), ifile) != NULL) - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " %s", buf); fclose(ifile); } diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y index 67e046d96625..c328596def3c 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $ * * $FreeBSD$ */ @@ -157,6 +157,8 @@ static int is_download_const(expression_t *immed); %token T_END_CS +%token T_PAD_PAGE + %token T_FIELD %token T_ENUM @@ -189,6 +191,10 @@ static int is_download_const(expression_t *immed); %token <value> T_OR +/* 16 bit extensions */ +%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16 +%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG + %token T_RET %token T_NOP @@ -207,7 +213,7 @@ static int is_download_const(expression_t *immed); %type <expression> expression immediate immediate_or_a -%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne +%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne %type <value> mode_value mode_list macro_arglist @@ -1304,6 +1310,15 @@ f2_opcode: | T_ROR { $$ = AIC_OP_ROR; } ; +f4_opcode: + T_OR16 { $$ = AIC_OP_OR16; } +| T_AND16 { $$ = AIC_OP_AND16; } +| T_XOR16 { $$ = AIC_OP_XOR16; } +| T_ADD16 { $$ = AIC_OP_ADD16; } +| T_ADC16 { $$ = AIC_OP_ADC16; } +| T_MVI16 { $$ = AIC_OP_MVI16; } +; + code: f2_opcode destination ',' expression opt_source ret ';' { diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h index e64f802bbaaa..9df9e2ce3538 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h @@ -37,13 +37,14 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#11 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $ * * $FreeBSD$ */ #include <asm/byteorder.h> +/* 8bit ALU logic operations */ struct ins_format1 { #ifdef __LITTLE_ENDIAN uint32_t immediate : 8, @@ -62,6 +63,7 @@ struct ins_format1 { #endif }; +/* 8bit ALU shift/rotate operations */ struct ins_format2 { #ifdef __LITTLE_ENDIAN uint32_t shift_control : 8, @@ -80,6 +82,7 @@ struct ins_format2 { #endif }; +/* 8bit branch control operations */ struct ins_format3 { #ifdef __LITTLE_ENDIAN uint32_t immediate : 8, @@ -96,10 +99,68 @@ struct ins_format3 { #endif }; +/* 16bit ALU logic operations */ +struct ins_format4 { +#ifdef __LITTLE_ENDIAN + uint32_t opcode_ext : 8, + source : 9, + destination : 9, + ret : 1, + opcode : 4, + parity : 1; +#else + uint32_t parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + opcode_ext : 8; +#endif +}; + +/* 16bit branch control operations */ +struct ins_format5 { +#ifdef __LITTLE_ENDIAN + uint32_t opcode_ext : 8, + source : 9, + address : 10, + opcode : 4, + parity : 1; +#else + uint32_t parity : 1, + opcode : 4, + address : 10, + source : 9, + opcode_ext : 8; +#endif +}; + +/* Far branch operations */ +struct ins_format6 { +#ifdef __LITTLE_ENDIAN + uint32_t page : 3, + opcode_ext : 5, + source : 9, + address : 10, + opcode : 4, + parity : 1; +#else + uint32_t parity : 1, + opcode : 4, + address : 10, + source : 9, + opcode_ext : 5, + page : 3; +#endif +}; + union ins_formats { struct ins_format1 format1; struct ins_format2 format2; struct ins_format3 format3; + struct ins_format4 format4; + struct ins_format5 format5; + struct ins_format6 format6; uint8_t bytes[4]; uint32_t integer; }; @@ -118,6 +179,8 @@ struct instruction { #define AIC_OP_ROL 0x5 #define AIC_OP_BMOV 0x6 +#define AIC_OP_MVI16 0x7 + #define AIC_OP_JMP 0x8 #define AIC_OP_JC 0x9 #define AIC_OP_JNC 0xa @@ -131,3 +194,26 @@ struct instruction { #define AIC_OP_SHL 0x10 #define AIC_OP_SHR 0x20 #define AIC_OP_ROR 0x30 + +/* 16bit Ops. Low byte main opcode. High byte extended opcode. */ +#define AIC_OP_OR16 0x8005 +#define AIC_OP_AND16 0x8105 +#define AIC_OP_XOR16 0x8205 +#define AIC_OP_ADD16 0x8305 +#define AIC_OP_ADC16 0x8405 +#define AIC_OP_JNE16 0x8805 +#define AIC_OP_JNZ16 0x8905 +#define AIC_OP_JE16 0x8C05 +#define AIC_OP_JZ16 0x8B05 +#define AIC_OP_JMP16 0x9005 +#define AIC_OP_JC16 0x9105 +#define AIC_OP_JNC16 0x9205 +#define AIC_OP_CALL16 0x9305 +#define AIC_OP_CALL16 0x9305 + +/* Page extension is low three bits of second opcode byte. */ +#define AIC_OP_JMPF 0xA005 +#define AIC_OP_CALLF 0xB005 +#define AIC_OP_JCF 0xC005 +#define AIC_OP_JNCF 0xD005 +#define AIC_OP_CMPXCHG 0xE005 diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l index 45c0b233d0bc..7c3983f868a9 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $ * * $FreeBSD$ */ @@ -132,7 +132,7 @@ if[ \t]*\( { *string_buf_ptr++ = *yptr++; } } - +else { return T_ELSE; } VERSION { return T_VERSION; } PREFIX { return T_PREFIX; } PATCH_ARG_LIST { return T_PATCH_ARG_LIST; } @@ -173,10 +173,6 @@ RW|RO|WO { yylval.value = WO; return T_MODE; } -BEGIN_CRITICAL { return T_BEGIN_CS; } -END_CRITICAL { return T_END_CS; } -SET_SRC_MODE { return T_SET_SRC_MODE; } -SET_DST_MODE { return T_SET_DST_MODE; } field { return T_FIELD; } enum { return T_ENUM; } mask { return T_MASK; } @@ -192,6 +188,13 @@ none { return T_NONE; } sindex { return T_SINDEX; } A { return T_A; } + /* Instruction Formatting */ +PAD_PAGE { return T_PAD_PAGE; } +BEGIN_CRITICAL { return T_BEGIN_CS; } +END_CRITICAL { return T_END_CS; } +SET_SRC_MODE { return T_SET_SRC_MODE; } +SET_DST_MODE { return T_SET_DST_MODE; } + /* Opcodes */ shl { return T_SHL; } shr { return T_SHR; } @@ -223,7 +226,17 @@ and { return T_AND; } or { return T_OR; } ret { return T_RET; } nop { return T_NOP; } -else { return T_ELSE; } + + /* ARP2 16bit extensions */ +or16 { return T_OR16; } +and16 { return T_AND16; } +xor16 { return T_XOR16; } +add16 { return T_ADD16; } +adc16 { return T_ADC16; } +mvi16 { return T_MVI16; } +test16 { return T_TEST16; } +cmp16 { return T_CMP16; } +cmpxchg { return T_CMPXCHG; } /* Allowed Symbols */ \<\< { return T_EXPR_LSHIFT; } diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index c8a32cf47d73..cbf825263f3b 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -246,6 +246,7 @@ struct ScsiReqBlk { * total_xfer_length in xferred. These values are restored in * pci_unmap_srb_sense. This is the only place xferred is used. */ + unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */ u32 xferred; /* Saved copy of total_xfer_length */ u16 state; @@ -2017,7 +2018,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) sg_verify_length(srb); /* we need the corresponding virtual address */ - if (!segment) { + if (!segment || (srb->flag & AUTO_REQSENSE)) { srb->virt_addr += xferred; return; } @@ -3318,6 +3319,7 @@ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; srb->segment_x[0].length = srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length; + srb->virt_addr = srb->virt_addr_req; } @@ -3711,6 +3713,8 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, srb->xferred = srb->total_xfer_length; /* srb->segment_x : a one entry of S/G list table */ srb->total_xfer_length = sizeof(cmd->sense_buffer); + srb->virt_addr_req = srb->virt_addr; + srb->virt_addr = cmd->sense_buffer; srb->segment_x[0].length = sizeof(cmd->sense_buffer); /* Map sense buffer */ srb->segment_x[0].address = diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 822b9fa706f3..eaefeddb2b4a 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -87,7 +87,7 @@ static int max_channel = 3; static int init_timeout = 5; static int max_requests = 50; -#define IBMVSCSI_VERSION "1.5.7" +#define IBMVSCSI_VERSION "1.5.8" MODULE_DESCRIPTION("IBM Virtual SCSI"); MODULE_AUTHOR("Dave Boutcher"); @@ -534,7 +534,6 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, struct ibmvscsi_host_data *hostdata) { - struct scsi_cmnd *cmnd; u64 *crq_as_u64 = (u64 *) &evt_struct->crq; int rc; @@ -544,19 +543,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, * can handle more requests (can_queue) when we actually can't */ if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) && - (atomic_dec_if_positive(&hostdata->request_limit) < 0)) { - /* See if the adapter is disabled */ - if (atomic_read(&hostdata->request_limit) < 0) - goto send_error; - - printk(KERN_WARNING - "ibmvscsi: Warning, request_limit exceeded\n"); - unmap_cmd_data(&evt_struct->iu.srp.cmd, - evt_struct, - hostdata->dev); - free_event_struct(&hostdata->pool, evt_struct); - return SCSI_MLQUEUE_HOST_BUSY; - } + (atomic_dec_if_positive(&hostdata->request_limit) < 0)) + goto send_error; /* Copy the IU into the transfer area */ *evt_struct->xfer_iu = evt_struct->iu; @@ -572,7 +560,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { list_del(&evt_struct->list); - printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n", + printk(KERN_ERR "ibmvscsi: send error %d\n", rc); goto send_error; } @@ -582,14 +570,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, send_error: unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); - if ((cmnd = evt_struct->cmnd) != NULL) { - cmnd->result = DID_ERROR << 16; - evt_struct->cmnd_done(cmnd); - } else if (evt_struct->done) - evt_struct->done(evt_struct); - free_event_struct(&hostdata->pool, evt_struct); - return 0; + return SCSI_MLQUEUE_HOST_BUSY; } /** @@ -802,7 +784,8 @@ static void login_rsp(struct srp_event_struct *evt_struct) case SRP_LOGIN_RSP_TYPE: /* it worked! */ break; case SRP_LOGIN_REJ_TYPE: /* refused! */ - printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n"); + printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n", + evt_struct->xfer_iu->srp.login_rej.reason); /* Login failed. */ atomic_set(&hostdata->request_limit, -1); return; @@ -834,6 +817,9 @@ static void login_rsp(struct srp_event_struct *evt_struct) return; } + /* If we had any pending I/Os, kick them */ + scsi_unblock_requests(hostdata->host); + send_mad_adapter_info(hostdata); return; } @@ -862,6 +848,7 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata) init_timeout * HZ); login = &evt_struct->iu.srp.login_req; + memset(login, 0x00, sizeof(struct srp_login_req)); login->type = SRP_LOGIN_REQ_TYPE; login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu); login->required_buffer_formats = 0x0006; @@ -1122,7 +1109,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) * purge_requests: Our virtual adapter just shut down. purge any sent requests * @hostdata: the adapter */ -static void purge_requests(struct ibmvscsi_host_data *hostdata) +static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) { struct srp_event_struct *tmp_evt, *pos; unsigned long flags; @@ -1131,7 +1118,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata) list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { list_del(&tmp_evt->list); if (tmp_evt->cmnd) { - tmp_evt->cmnd->result = (DID_ERROR << 16); + tmp_evt->cmnd->result = (error_code << 16); unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt, tmp_evt->hostdata->dev); @@ -1186,12 +1173,30 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, printk(KERN_ERR "ibmvscsi: unknown crq message type\n"); } return; - case 0xFF: /* Hypervisor telling us the connection is closed */ - printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n"); + case 0xFF: /* Hypervisor telling us the connection is closed */ + scsi_block_requests(hostdata->host); + if (crq->format == 0x06) { + /* We need to re-setup the interpartition connection */ + printk(KERN_INFO + "ibmvscsi: Re-enabling adapter!\n"); + purge_requests(hostdata, DID_REQUEUE); + if (ibmvscsi_reenable_crq_queue(&hostdata->queue, + hostdata) == 0) + if (ibmvscsi_send_crq(hostdata, + 0xC001000000000000LL, 0)) + printk(KERN_ERR + "ibmvscsi: transmit error after" + " enable\n"); + } else { + printk(KERN_INFO + "ibmvscsi: Virtual adapter failed rc %d!\n", + crq->format); - atomic_set(&hostdata->request_limit, -1); - purge_requests(hostdata); - ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata); + atomic_set(&hostdata->request_limit, -1); + purge_requests(hostdata, DID_ERROR); + ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata); + } + scsi_unblock_requests(hostdata->host); return; case 0x80: /* real payload */ break; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 5b0edd1f1921..4550d71e4744 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -103,6 +103,9 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue, int ibmvscsi_reset_crq_queue(struct crq_queue *queue, struct ibmvscsi_host_data *hostdata); +int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata); + void ibmvscsi_handle_crq(struct viosrp_crq *crq, struct ibmvscsi_host_data *hostdata); int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index ce15d9e39621..7eed0b098171 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -124,6 +124,19 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue, } /** + * reenable_crq_queue: - reenables a crq after a failure + * @queue: crq_queue to initialize and register + * @hostdata: ibmvscsi_host_data of host + * + * no-op for iSeries + */ +int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) +{ + return 0; +} + +/** * ibmvscsi_send_crq: - Send a CRQ * @hostdata: the adapter * @word1: the first 64 bits of the data diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 75db2f5c545e..f47dd87c05e7 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -281,6 +281,28 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, } /** + * reenable_crq_queue: - reenables a crq after + * @queue: crq_queue to initialize and register + * @hostdata: ibmvscsi_host_data of host + * + */ +int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) +{ + int rc; + struct vio_dev *vdev = to_vio_dev(hostdata->dev); + + /* Re-enable the CRQ */ + do { + rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); + } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc))); + + if (rc) + printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc); + return rc; +} + +/** * reset_crq_queue: - resets a crq after a failure * @queue: crq_queue to initialize and register * @hostdata: ibmvscsi_host_data of host diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 3c688ef54660..0cf0e4c7ac0c 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -751,9 +751,8 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) idescsi_add_settings(drive); } -static int ide_scsi_remove(struct device *dev) +static void ide_scsi_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct Scsi_Host *scsihost = drive->driver_data; struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; @@ -768,11 +767,9 @@ static int ide_scsi_remove(struct device *dev) scsi_remove_host(scsihost); ide_scsi_put(scsi); - - return 0; } -static int ide_scsi_probe(struct device *); +static int ide_scsi_probe(ide_drive_t *); #ifdef CONFIG_PROC_FS static ide_proc_entry_t idescsi_proc[] = { @@ -788,9 +785,9 @@ static ide_driver_t idescsi_driver = { .owner = THIS_MODULE, .name = "ide-scsi", .bus = &ide_bus_type, - .probe = ide_scsi_probe, - .remove = ide_scsi_remove, }, + .probe = ide_scsi_probe, + .remove = ide_scsi_remove, .version = IDESCSI_VERSION, .media = ide_scsi, .supports_dsc_overlap = 0, @@ -1119,9 +1116,8 @@ static struct scsi_host_template idescsi_template = { .proc_name = "ide-scsi", }; -static int ide_scsi_probe(struct device *dev) +static int ide_scsi_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idescsi_scsi_t *idescsi; struct Scsi_Host *host; struct gendisk *g; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index e5e1ca44e1ee..86c546164da9 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -3499,6 +3499,7 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp) int device_error; uint32_t transfer_len; IPS_DCDB_TABLE_TAPE *tapeDCDB; + IPS_SCSI_INQ_DATA inquiryData; METHOD_TRACE("ips_map_status", 1); @@ -3557,13 +3558,13 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp) errcode = DID_OK; /* Restrict access to physical DASD */ - if ((scb->scsi_cmd->cmnd[0] == INQUIRY) && - ((((char *) scb->scsi_cmd-> - buffer)[0] & 0x1f) == TYPE_DISK)) { - /* underflow -- no error */ - /* restrict access to physical DASD */ - errcode = DID_TIME_OUT; - break; + if (scb->scsi_cmd->cmnd[0] == INQUIRY) { + ips_scmd_buf_read(scb->scsi_cmd, + &inquiryData, sizeof (inquiryData)); + if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) { + errcode = DID_TIME_OUT; + break; + } } } else errcode = DID_ERROR; @@ -4135,6 +4136,7 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus) uint8_t basic_status; uint8_t ext_status; int errcode; + IPS_SCSI_INQ_DATA inquiryData; METHOD_TRACE("ips_chkstatus", 1); @@ -4255,11 +4257,11 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus) scb->scsi_cmd->result = errcode << 16; } else { /* bus == 0 */ /* restrict access to physical drives */ - if ((scb->scsi_cmd->cmnd[0] == INQUIRY) && - ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == - TYPE_DISK)) { - - scb->scsi_cmd->result = DID_TIME_OUT << 16; + if (scb->scsi_cmd->cmnd[0] == INQUIRY) { + ips_scmd_buf_read(scb->scsi_cmd, + &inquiryData, sizeof (inquiryData)); + if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) + scb->scsi_cmd->result = DID_TIME_OUT << 16; } } /* else */ } else { /* recovered error / success */ @@ -5012,7 +5014,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (j >= 45) @@ -5038,7 +5040,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (j >= 240) @@ -5056,7 +5058,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (i >= 240) @@ -5106,7 +5108,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (j >= 45) @@ -5132,7 +5134,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (j >= 240) @@ -5150,7 +5152,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (i >= 240) @@ -5202,7 +5204,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (i >= 45) { @@ -5228,7 +5230,7 @@ ips_init_morpheus(ips_ha_t * ha) if (Post != 0x4F00) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (i >= 120) { @@ -5258,7 +5260,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); } if (i >= 240) { @@ -5318,12 +5320,12 @@ ips_reset_copperhead(ips_ha_t * ha) outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); outb(0, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5363,12 +5365,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha) writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); writeb(0, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - MDELAY(IPS_ONE_SEC); + msleep(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5409,7 +5411,7 @@ ips_reset_morpheus(ips_ha_t * ha) writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR); /* Delay for 5 Seconds */ - MDELAY(5 * IPS_ONE_SEC); + msleep(5 * IPS_ONE_SEC); /* Do a PCI config read to wait for adapter */ pci_read_config_byte(ha->pcidev, 4, &junk); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index cfbceb504718..07b1e7cc61df 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1700,6 +1700,31 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) return sizeof(def_rw_recovery_mpage); } +/* + * We can turn this into a real blacklist if it's needed, for now just + * blacklist any Maxtor BANC1G10 revision firmware + */ +static int ata_dev_supports_fua(u16 *id) +{ + unsigned char model[41], fw[9]; + + if (!ata_id_has_fua(id)) + return 0; + + model[40] = '\0'; + fw[8] = '\0'; + + ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1); + ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1); + + if (strncmp(model, "Maxtor", 6)) + return 1; + if (strncmp(fw, "BANC1G10", 8)) + return 1; + + return 0; /* blacklisted */ +} + /** * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands * @args: device IDENTIFY data / SCSI command of interest. @@ -1797,7 +1822,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, return 0; dpofua = 0; - if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && + if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) dpofua = 1 << 4; diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 311a4122bd70..93edaa8696cf 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -537,9 +537,9 @@ static int mac53c94_remove(struct macio_dev *mdev) free_irq(fp->intr, fp); if (fp->regs) - iounmap((void *) fp->regs); + iounmap(fp->regs); if (fp->dma) - iounmap((void *) fp->dma); + iounmap(fp->dma); kfree(fp->dma_cmd_space); scsi_host_put(host); diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 511ed52a5807..a487f414960e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_sas.c - * Version : v00.00.02.00-rc4 + * Version : v00.00.02.02 * * Authors: * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> @@ -55,13 +55,13 @@ static struct pci_device_id megasas_pci_table[] = { { PCI_VENDOR_ID_LSI_LOGIC, - PCI_DEVICE_ID_LSI_SAS1064R, + PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_DELL, - PCI_DEVICE_ID_DELL_PERC5, + PCI_DEVICE_ID_DELL_PERC5, // xscale IOP PCI_ANY_ID, PCI_ANY_ID, }, @@ -119,12 +119,18 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); } + +/** +* The following functions are defined for xscale +* (deviceid : 1064R, PERC5) controllers +*/ + /** - * megasas_enable_intr - Enables interrupts + * megasas_enable_intr_xscale - Enables interrupts * @regs: MFI register set */ static inline void -megasas_enable_intr(struct megasas_register_set __iomem * regs) +megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) { writel(1, &(regs)->outbound_intr_mask); @@ -133,13 +139,73 @@ megasas_enable_intr(struct megasas_register_set __iomem * regs) } /** + * megasas_read_fw_status_reg_xscale - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_msg_0); +} +/** + * megasas_clear_interrupt_xscale - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_OB_INTR_STATUS_MASK)) { + return 1; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_intr_status); + + return 0; +} + +/** + * megasas_fire_cmd_xscale - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr >> 3)|(frame_count), + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_xscale = { + + .fire_cmd = megasas_fire_cmd_xscale, + .enable_intr = megasas_enable_intr_xscale, + .clear_intr = megasas_clear_intr_xscale, + .read_fw_status_reg = megasas_read_fw_status_reg_xscale, +}; + +/** +* This is the end of set of functions & definitions specific +* to xscale (deviceid : 1064R, PERC5) controllers +*/ + +/** * megasas_disable_intr - Disables interrupts * @regs: MFI register set */ static inline void megasas_disable_intr(struct megasas_register_set __iomem * regs) { - u32 mask = readl(®s->outbound_intr_mask) & (~0x00000001); + u32 mask = 0x1f; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -167,8 +233,7 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) /* * Issue the frame using inbound queue port */ - writel(cmd->frame_phys_addr >> 3, - &instance->reg_set->inbound_queue_port); + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); /* * Wait for cmd_status to change @@ -198,8 +263,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, { cmd->cmd_status = ENODATA; - writel(cmd->frame_phys_addr >> 3, - &instance->reg_set->inbound_queue_port); + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA)); @@ -242,8 +306,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, cmd->sync_cmd = 1; cmd->cmd_status = 0xFF; - writel(cmd->frame_phys_addr >> 3, - &instance->reg_set->inbound_queue_port); + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); /* * Wait for this cmd to complete @@ -558,112 +621,29 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, } /** - * megasas_build_cmd - Prepares a command packet - * @instance: Adapter soft state - * @scp: SCSI command - * @frame_count: [OUT] Number of frames used to prepare this command + * megasas_is_ldio - Checks if the cmd is for logical drive + * @scmd: SCSI command + * + * Called by megasas_queue_command to find out if the command to be queued + * is a logical drive command */ -static struct megasas_cmd *megasas_build_cmd(struct megasas_instance - *instance, - struct scsi_cmnd *scp, - int *frame_count) +static inline int megasas_is_ldio(struct scsi_cmnd *cmd) { - u32 logical_cmd; - struct megasas_cmd *cmd; - - /* - * Find out if this is logical or physical drive command. - */ - logical_cmd = MEGASAS_IS_LOGICAL(scp); - - /* - * Logical drive command - */ - if (logical_cmd) { - - if (scp->device->id >= MEGASAS_MAX_LD) { - scp->result = DID_BAD_TARGET << 16; - return NULL; - } - - switch (scp->cmnd[0]) { - - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - case READ_6: - case WRITE_6: - case READ_16: - case WRITE_16: - /* - * Fail for LUN > 0 - */ - if (scp->device->lun) { - scp->result = DID_BAD_TARGET << 16; - return NULL; - } - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - scp->result = DID_IMM_RETRY << 16; - return NULL; - } - - *frame_count = megasas_build_ldio(instance, scp, cmd); - - if (!(*frame_count)) { - megasas_return_cmd(instance, cmd); - return NULL; - } - - return cmd; - - default: - /* - * Fail for LUN > 0 - */ - if (scp->device->lun) { - scp->result = DID_BAD_TARGET << 16; - return NULL; - } - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - scp->result = DID_IMM_RETRY << 16; - return NULL; - } - - *frame_count = megasas_build_dcdb(instance, scp, cmd); - - if (!(*frame_count)) { - megasas_return_cmd(instance, cmd); - return NULL; - } - - return cmd; - } - } else { - cmd = megasas_get_cmd(instance); - - if (!cmd) { - scp->result = DID_IMM_RETRY << 16; - return NULL; - } - - *frame_count = megasas_build_dcdb(instance, scp, cmd); - - if (!(*frame_count)) { - megasas_return_cmd(instance, cmd); - return NULL; - } - - return cmd; + if (!MEGASAS_IS_LOGICAL(cmd)) + return 0; + switch (cmd->cmnd[0]) { + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + case READ_16: + case WRITE_16: + return 1; + default: + return 0; } - - return NULL; } /** @@ -684,13 +664,27 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) scmd->scsi_done = done; scmd->result = 0; - cmd = megasas_build_cmd(instance, scmd, &frame_count); - - if (!cmd) { - done(scmd); - return 0; + if (MEGASAS_IS_LOGICAL(scmd) && + (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) { + scmd->result = DID_BAD_TARGET << 16; + goto out_done; } + cmd = megasas_get_cmd(instance); + if (!cmd) + return SCSI_MLQUEUE_HOST_BUSY; + + /* + * Logical drive command + */ + if (megasas_is_ldio(scmd)) + frame_count = megasas_build_ldio(instance, scmd, cmd); + else + frame_count = megasas_build_dcdb(instance, scmd, cmd); + + if (!frame_count) + goto out_return_cmd; + cmd->scmd = scmd; scmd->SCp.ptr = (char *)cmd; scmd->SCp.sent_command = jiffies; @@ -702,10 +696,15 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) instance->fw_outstanding++; spin_unlock_irqrestore(&instance->instance_lock, flags); - writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)), - &instance->reg_set->inbound_queue_port); + instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); return 0; + + out_return_cmd: + megasas_return_cmd(instance, cmd); + out_done: + done(scmd); + return 0; } /** @@ -1108,7 +1107,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, static int megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) { - u32 status; u32 producer; u32 consumer; u32 context; @@ -1116,17 +1114,10 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) /* * Check if it is our interrupt + * Clear the interrupt */ - status = readl(&instance->reg_set->outbound_intr_status); - - if (!(status & MFI_OB_INTR_STATUS_MASK)) { + if(instance->instancet->clear_intr(instance->reg_set)) return IRQ_NONE; - } - - /* - * Clear the interrupt by writing back the same value - */ - writel(status, &instance->reg_set->outbound_intr_status); producer = *instance->producer; consumer = *instance->consumer; @@ -1160,7 +1151,7 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) /** * megasas_transition_to_ready - Move the FW to READY state - * @reg_set: MFI register set + * @instance: Adapter soft state * * During the initialization, FW passes can potentially be in any one of * several possible states. If the FW in operational, waiting-for-handshake @@ -1168,14 +1159,14 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) * has to wait for the ready state. */ static int -megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) +megasas_transition_to_ready(struct megasas_instance* instance) { int i; u8 max_wait; u32 fw_state; u32 cur_state; - fw_state = readl(®_set->outbound_msg_0) & MFI_STATE_MASK; + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; while (fw_state != MFI_STATE_READY) { @@ -1193,7 +1184,7 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) * Set the CLR bit in inbound doorbell */ writel(MFI_INIT_CLEAR_HANDSHAKE, - ®_set->inbound_doorbell); + &instance->reg_set->inbound_doorbell); max_wait = 2; cur_state = MFI_STATE_WAIT_HANDSHAKE; @@ -1203,8 +1194,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) /* * Bring it to READY state; assuming max wait 2 secs */ - megasas_disable_intr(reg_set); - writel(MFI_INIT_READY, ®_set->inbound_doorbell); + megasas_disable_intr(instance->reg_set); + writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell); max_wait = 10; cur_state = MFI_STATE_OPERATIONAL; @@ -1253,8 +1244,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) * The cur_state should not last for more than max_wait secs */ for (i = 0; i < (max_wait * 1000); i++) { - fw_state = MFI_STATE_MASK & - readl(®_set->outbound_msg_0); + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & + MFI_STATE_MASK ; if (fw_state == cur_state) { msleep(1); @@ -1616,18 +1607,20 @@ static int megasas_init_mfi(struct megasas_instance *instance) reg_set = instance->reg_set; + instance->instancet = &megasas_instance_template_xscale; + /* * We expect the FW state to be READY */ - if (megasas_transition_to_ready(instance->reg_set)) + if (megasas_transition_to_ready(instance)) goto fail_ready_state; /* * Get various operational parameters from status register */ - instance->max_fw_cmds = readl(®_set->outbound_msg_0) & 0x00FFFF; - instance->max_num_sge = (readl(®_set->outbound_msg_0) & 0xFF0000) >> - 0x10; + instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; + instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> + 0x10; /* * Create a pool of commands */ @@ -1936,8 +1929,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, /* * Issue the aen registration frame */ - writel(cmd->frame_phys_addr >> 3, - &instance->reg_set->inbound_queue_port); + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); return 0; } @@ -2126,7 +2118,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto fail_irq; } - megasas_enable_intr(instance->reg_set); + instance->instancet->enable_intr(instance->reg_set); /* * Store instance in PCI softstate @@ -2681,9 +2673,8 @@ megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { - case MEGASAS_IOC_FIRMWARE:{ - return megasas_mgmt_compat_ioctl_fw(file, arg); - } + case MEGASAS_IOC_FIRMWARE32: + return megasas_mgmt_compat_ioctl_fw(file, arg); case MEGASAS_IOC_GET_AEN: return megasas_mgmt_ioctl_aen(file, arg); } diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index eaec9d531424..d6d166c0663f 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -18,10 +18,9 @@ /** * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.02.00-rc4" -#define MEGASAS_RELDATE "Sep 16, 2005" -#define MEGASAS_EXT_VERSION "Fri Sep 16 12:37:08 EDT 2005" - +#define MEGASAS_VERSION "00.00.02.02" +#define MEGASAS_RELDATE "Jan 23, 2006" +#define MEGASAS_EXT_VERSION "Mon Jan 23 14:09:01 PST 2006" /* * ===================================== * MegaRAID SAS MFI firmware definitions @@ -1013,6 +1012,16 @@ struct megasas_evt_detail { } __attribute__ ((packed)); + struct megasas_instance_template { + void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *); + + void (*enable_intr)(struct megasas_register_set __iomem *) ; + + int (*clear_intr)(struct megasas_register_set __iomem *); + + u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *); + }; + struct megasas_instance { u32 *producer; @@ -1056,6 +1065,8 @@ struct megasas_instance { u32 fw_outstanding; u32 hw_crit_error; spinlock_t instance_lock; + + struct megasas_instance_template *instancet; }; #define MEGASAS_IS_LOGICAL(scp) \ @@ -1125,11 +1136,10 @@ struct compat_megasas_iocpacket { struct compat_iovec sgl[MAX_IOCTL_SGE]; } __attribute__ ((packed)); -#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct compat_megasas_iocpacket) -#else -#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket) #endif +#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket) +#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket) #define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen) struct megasas_mgmt_info { diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 0878f95b5449..e0230249fa0f 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -17,9 +17,11 @@ * General Public License for more details. * ******************************************************************************/ -#define QLA1280_VERSION "3.25" +#define QLA1280_VERSION "3.26" /***************************************************************************** Revision History: + Rev 3.26, January 16, 2006 Jes Sorensen + - Ditch all < 2.6 support Rev 3.25.1, February 10, 2005 Christoph Hellwig - use pci_map_single to map non-S/G requests - remove qla1280_proc_info @@ -356,25 +358,18 @@ #include <asm/types.h> #include <asm/system.h> -#if LINUX_VERSION_CODE >= 0x020545 #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> -#else -#include <linux/blk.h> -#include "scsi.h" -#include <scsi/scsi_host.h> -#include "sd.h" -#endif #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) #include <asm/sn/io.h> #endif -#if LINUX_VERSION_CODE < 0x020407 -#error "Kernels older than 2.4.7 are no longer supported" +#if LINUX_VERSION_CODE < 0x020600 +#error "Kernels older than 2.6.0 are no longer supported" #endif @@ -441,52 +436,6 @@ #define NVRAM_DELAY() udelay(500) /* 2 microseconds */ -#if LINUX_VERSION_CODE < 0x020500 -#define HOST_LOCK &io_request_lock -#define irqreturn_t void -#define IRQ_RETVAL(foo) -#define MSG_ORDERED_TAG 1 - -#define DMA_BIDIRECTIONAL SCSI_DATA_UNKNOWN -#define DMA_TO_DEVICE SCSI_DATA_WRITE -#define DMA_FROM_DEVICE SCSI_DATA_READ -#define DMA_NONE SCSI_DATA_NONE - -#ifndef HAVE_SECTOR_T -typedef unsigned int sector_t; -#endif - -static inline void -scsi_adjust_queue_depth(struct scsi_device *device, int tag, int depth) -{ - if (tag) { - device->tagged_queue = tag; - device->current_tag = 0; - } - device->queue_depth = depth; -} -static inline struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *t, size_t s) -{ - return scsi_register(t, s); -} -static inline void scsi_host_put(struct Scsi_Host *h) -{ - scsi_unregister(h); -} -#else -#define HOST_LOCK ha->host->host_lock -#endif -#if LINUX_VERSION_CODE < 0x020600 -#define DEV_SIMPLE_TAGS(device) device->tagged_queue -/* - * Hack around that qla1280_remove_one is called from - * qla1280_release in 2.4 - */ -#undef __devexit -#define __devexit -#else -#define DEV_SIMPLE_TAGS(device) device->simple_tags -#endif #if defined(__ia64__) && !defined(ia64_platform_is) #define ia64_platform_is(foo) (!strcmp(x, platform_name)) #endif @@ -506,9 +455,6 @@ static void qla1280_remove_one(struct pci_dev *); * QLogic Driver Support Function Prototypes. */ static void qla1280_done(struct scsi_qla_host *); -#if LINUX_VERSION_CODE < 0x020545 -static void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *); -#endif static int qla1280_get_token(char *); static int qla1280_setup(char *s) __init; @@ -610,11 +556,7 @@ __setup("qla1280=", qla1280_setup); #define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer) #define CMD_RESULT(Cmnd) Cmnd->result #define CMD_HANDLE(Cmnd) Cmnd->host_scribble -#if LINUX_VERSION_CODE < 0x020545 -#define CMD_REQUEST(Cmnd) Cmnd->request.cmd -#else #define CMD_REQUEST(Cmnd) Cmnd->request->cmd -#endif #define CMD_HOST(Cmnd) Cmnd->device->host #define SCSI_BUS_32(Cmnd) Cmnd->device->channel @@ -1064,10 +1006,10 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) add_timer(&timer); /* wait for the action to complete (or the timer to expire) */ - spin_unlock_irq(HOST_LOCK); + spin_unlock_irq(ha->host->host_lock); wait_for_completion(&wait); del_timer_sync(&timer); - spin_lock_irq(HOST_LOCK); + spin_lock_irq(ha->host->host_lock); sp->wait = NULL; /* the only action we might get a fail for is abort */ @@ -1173,96 +1115,6 @@ qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev, return 0; } -#if LINUX_VERSION_CODE < 0x020600 -static int -qla1280_detect(struct scsi_host_template *template) -{ - struct pci_device_id *id = &qla1280_pci_tbl[0]; - struct pci_dev *pdev = NULL; - int num_hosts = 0; - - if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { - printk(KERN_WARNING - "qla1280: struct srb too big, aborting\n"); - return 0; - } - - if ((DMA_BIDIRECTIONAL != PCI_DMA_BIDIRECTIONAL) || - (DMA_TO_DEVICE != PCI_DMA_TODEVICE) || - (DMA_FROM_DEVICE != PCI_DMA_FROMDEVICE) || - (DMA_NONE != PCI_DMA_NONE)) { - printk(KERN_WARNING - "qla1280: dma direction bits don't match\n"); - return 0; - } - -#ifdef MODULE - /* - * If we are called as a module, the qla1280 pointer may not be null - * and it would point to our bootup string, just like on the lilo - * command line. IF not NULL, then process this config string with - * qla1280_setup - * - * Boot time Options - * To add options at boot time add a line to your lilo.conf file like: - * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" - * which will result in the first four devices on the first two - * controllers being set to a tagged queue depth of 32. - */ - if (qla1280) - qla1280_setup(qla1280); -#endif - - /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */ - while ((pdev = pci_find_device(id->vendor, id->device, pdev))) { - if (pdev->bus->number == 1 && PCI_SLOT(pdev->devfn) == 2) { - if (!qla1280_probe_one(pdev, id)) - num_hosts++; - } - } - - pdev = NULL; - /* Try and find each different type of adapter we support */ - for (id = &qla1280_pci_tbl[0]; id->device; id++) { - while ((pdev = pci_find_device(id->vendor, id->device, pdev))) { - /* - * skip QLA12160 already initialized on - * PCI Bus 1 Dev 2 since we already initialized - * and presented it - */ - if (id->device == PCI_DEVICE_ID_QLOGIC_ISP12160 && - pdev->bus->number == 1 && - PCI_SLOT(pdev->devfn) == 2) - continue; - - if (!qla1280_probe_one(pdev, id)) - num_hosts++; - } - } - - return num_hosts; -} - -/* - * This looks a bit ugly as we could just pass down host to - * qla1280_remove_one, but I want to keep qla1280_release purely a wrapper - * around pci_driver::remove as used from 2.6 onwards. - */ -static int -qla1280_release(struct Scsi_Host *host) -{ - struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - - qla1280_remove_one(ha->pdev); - return 0; -} - -static int -qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[]) -{ - return qla1280_biosparam(disk->device, NULL, disk->capacity, geom); -} -#endif /* disable risc and host interrupts */ static inline void @@ -1295,7 +1147,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) ENTER_INTR ("qla1280_intr_handler"); ha = (struct scsi_qla_host *)dev_id; - spin_lock(HOST_LOCK); + spin_lock(ha->host->host_lock); ha->isr_count++; reg = ha->iobase; @@ -1311,7 +1163,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) if (!list_empty(&ha->done_q)) qla1280_done(ha); - spin_unlock(HOST_LOCK); + spin_unlock(ha->host->host_lock); qla1280_enable_intrs(ha); @@ -1411,11 +1263,9 @@ qla1280_slave_configure(struct scsi_device *device) scsi_adjust_queue_depth(device, 0, default_depth); } -#if LINUX_VERSION_CODE > 0x020500 nv->bus[bus].target[target].parameter.enable_sync = device->sdtr; nv->bus[bus].target[target].parameter.enable_wide = device->wdtr; nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; -#endif if (driver_setup.no_sync || (driver_setup.sync_mask && @@ -1432,38 +1282,14 @@ qla1280_slave_configure(struct scsi_device *device) nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; } - spin_lock_irqsave(HOST_LOCK, flags); + spin_lock_irqsave(ha->host->host_lock, flags); if (nv->bus[bus].target[target].parameter.enable_sync) status = qla1280_set_target_parameters(ha, bus, target); qla1280_get_target_parameters(ha, device); - spin_unlock_irqrestore(HOST_LOCK, flags); + spin_unlock_irqrestore(ha->host->host_lock, flags); return status; } -#if LINUX_VERSION_CODE < 0x020545 -/************************************************************************** - * qla1280_select_queue_depth - * - * Sets the queue depth for each SCSI device hanging off the input - * host adapter. We use a queue depth of 2 for devices that do not - * support tagged queueing. - **************************************************************************/ -static void -qla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q) -{ - struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; - struct scsi_device *sdev; - - ENTER("qla1280_select_queue_depth"); - for (sdev = sdev_q; sdev; sdev = sdev->next) - if (sdev->host == host) - qla1280_slave_configure(sdev); - - if (sdev_q) - qla1280_check_for_dead_scsi_bus(ha, sdev_q->channel); - LEAVE("qla1280_select_queue_depth"); -} -#endif /* * qla1280_done @@ -1523,10 +1349,6 @@ qla1280_done(struct scsi_qla_host *ha) CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; ha->actthreads--; -#if LINUX_VERSION_CODE < 0x020500 - if (cmd->cmnd[0] == INQUIRY) - qla1280_get_target_options(cmd, ha); -#endif (*(cmd)->scsi_done)(cmd); if(sp->wait != NULL) @@ -1655,9 +1477,7 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) struct device_reg __iomem *reg; int status; int bus; -#if LINUX_VERSION_CODE > 0x020500 unsigned long flags; -#endif ENTER("qla1280_initialize_adapter"); @@ -1695,15 +1515,12 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) "NVRAM\n"); } -#if LINUX_VERSION_CODE >= 0x020500 /* * It's necessary to grab the spin here as qla1280_mailbox_command * needs to be able to drop the lock unconditionally to wait * for completion. - * In 2.4 ->detect is called with the io_request_lock held. */ - spin_lock_irqsave(HOST_LOCK, flags); -#endif + spin_lock_irqsave(ha->host->host_lock, flags); status = qla1280_load_firmware(ha); if (status) { @@ -1735,9 +1552,8 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) ha->flags.online = 1; out: -#if LINUX_VERSION_CODE >= 0x020500 - spin_unlock_irqrestore(HOST_LOCK, flags); -#endif + spin_unlock_irqrestore(ha->host->host_lock, flags); + if (status) dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n"); @@ -2650,14 +2466,14 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) timer.function = qla1280_mailbox_timeout; add_timer(&timer); - spin_unlock_irq(HOST_LOCK); + spin_unlock_irq(ha->host->host_lock); WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); data = qla1280_debounce_register(®->istatus); wait_for_completion(&wait); del_timer_sync(&timer); - spin_lock_irq(HOST_LOCK); + spin_lock_irq(ha->host->host_lock); ha->mailbox_wait = NULL; @@ -2770,9 +2586,9 @@ qla1280_bus_reset(struct scsi_qla_host *ha, int bus) ha->bus_settings[bus].scsi_bus_dead = 1; ha->bus_settings[bus].failed_reset_count++; } else { - spin_unlock_irq(HOST_LOCK); + spin_unlock_irq(ha->host->host_lock); ssleep(reset_delay); - spin_lock_irq(HOST_LOCK); + spin_lock_irq(ha->host->host_lock); ha->bus_settings[bus].scsi_bus_dead = 0; ha->bus_settings[bus].failed_reset_count = 0; @@ -3078,7 +2894,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (DEV_SIMPLE_TAGS(cmd->device)) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -3377,7 +3193,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); /* Enable simple tag queuing if device supports it. */ - if (DEV_SIMPLE_TAGS(cmd->device)) + if (cmd->device->simple_tags) pkt->control_flags |= cpu_to_le16(BIT_3); /* Load SCSI command packet. */ @@ -3889,50 +3705,6 @@ qla1280_rst_aen(struct scsi_qla_host *ha) } -#if LINUX_VERSION_CODE < 0x020500 -/* - * - */ -static void -qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha) -{ - unsigned char *result; - struct nvram *n; - int bus, target, lun; - - bus = SCSI_BUS_32(cmd); - target = SCSI_TCN_32(cmd); - lun = SCSI_LUN_32(cmd); - - /* - * Make sure to not touch anything if someone is using the - * sg interface. - */ - if (cmd->use_sg || (CMD_RESULT(cmd) >> 16) != DID_OK || lun) - return; - - result = cmd->request_buffer; - n = &ha->nvram; - - n->bus[bus].target[target].parameter.enable_wide = 0; - n->bus[bus].target[target].parameter.enable_sync = 0; - n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; - - if (result[7] & 0x60) - n->bus[bus].target[target].parameter.enable_wide = 1; - if (result[7] & 0x10) - n->bus[bus].target[target].parameter.enable_sync = 1; - if ((result[2] >= 3) && (result[4] + 5 > 56) && - (result[56] & 0x4)) - n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; - - dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n", - n->bus[bus].target[target].parameter.enable_wide, - n->bus[bus].target[target].parameter.enable_sync, - n->bus[bus].target[target].ppr_1x160.flags.enable_ppr); -} -#endif - /* * qla1280_status_entry * Processes received ISP status entry. @@ -4271,7 +4043,7 @@ qla1280_get_target_parameters(struct scsi_qla_host *ha, } else printk(" Async"); - if (DEV_SIMPLE_TAGS(device)) + if (device->simple_tags) printk(", Tagged queuing: depth %d", device->queue_depth); printk("\n"); } @@ -4485,7 +4257,7 @@ qla1280_get_token(char *str) return ret; } -#if LINUX_VERSION_CODE >= 0x020600 + static struct scsi_host_template qla1280_driver_template = { .module = THIS_MODULE, .proc_name = "qla1280", @@ -4504,27 +4276,7 @@ static struct scsi_host_template qla1280_driver_template = { .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, }; -#else -static struct scsi_host_template qla1280_driver_template = { - .proc_name = "qla1280", - .name = "Qlogic ISP 1280/12160", - .detect = qla1280_detect, - .release = qla1280_release, - .info = qla1280_info, - .queuecommand = qla1280_queuecommand, - .eh_abort_handler = qla1280_eh_abort, - .eh_device_reset_handler= qla1280_eh_device_reset, - .eh_bus_reset_handler = qla1280_eh_bus_reset, - .eh_host_reset_handler = qla1280_eh_adapter_reset, - .bios_param = qla1280_biosparam_old, - .can_queue = 0xfffff, - .this_id = -1, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, - .use_new_eh_code = 1, -}; -#endif + static int __devinit qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) @@ -4615,10 +4367,6 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_sectors = 1024; host->unique_id = host->host_no; -#if LINUX_VERSION_CODE < 0x020545 - host->select_queue_depths = qla1280_select_queue_depth; -#endif - error = -ENODEV; #if MEMORY_MAPPED_IO @@ -4666,21 +4414,15 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, host); -#if LINUX_VERSION_CODE >= 0x020600 error = scsi_add_host(host, &pdev->dev); if (error) goto error_disable_adapter; scsi_scan_host(host); -#else - scsi_set_pci_device(host, pdev); -#endif return 0; -#if LINUX_VERSION_CODE >= 0x020600 error_disable_adapter: qla1280_disable_intrs(ha); -#endif error_free_irq: free_irq(pdev->irq, ha); error_release_region: @@ -4712,9 +4454,7 @@ qla1280_remove_one(struct pci_dev *pdev) struct Scsi_Host *host = pci_get_drvdata(pdev); struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; -#if LINUX_VERSION_CODE >= 0x020600 scsi_remove_host(host); -#endif qla1280_disable_intrs(ha); @@ -4738,7 +4478,6 @@ qla1280_remove_one(struct pci_dev *pdev) scsi_host_put(host); } -#if LINUX_VERSION_CODE >= 0x020600 static struct pci_driver qla1280_pci_driver = { .name = "qla1280", .id_table = qla1280_pci_tbl, @@ -4784,10 +4523,6 @@ qla1280_exit(void) module_init(qla1280_init); module_exit(qla1280_exit); -#else -# define driver_template qla1280_driver_template -# include "scsi_module.c" -#endif MODULE_AUTHOR("Qlogic & Jes Sorensen"); MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver"); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 79d8a914f9d0..bad066e5772a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1680,7 +1680,8 @@ typedef struct fc_port { uint8_t mp_byte; /* multi-path byte (not used) */ uint8_t cur_path; /* current path id */ - struct fc_rport *rport; + spinlock_t rport_lock; + struct fc_rport *rport, *drport; u32 supported_classes; struct work_struct rport_add_work; struct work_struct rport_del_work; @@ -2270,6 +2271,7 @@ typedef struct scsi_qla_host { #define LOOP_RESET_NEEDED 24 #define BEACON_BLINK_NEEDED 25 #define REGISTER_FDMI_NEEDED 26 +#define FCPORT_UPDATE_NEEDED 27 uint32_t device_flags; #define DFLG_LOCAL_DEVICES BIT_0 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 32be4c14cccb..35266bd5d538 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -47,9 +47,11 @@ extern int qla2x00_local_device_login(scsi_qla_host_t *, uint16_t); extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); extern void qla2x00_rescan_fcports(scsi_qla_host_t *); +extern void qla2x00_update_fcports(scsi_qla_host_t *); extern int qla2x00_abort_isp(scsi_qla_host_t *); +extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *); /* @@ -70,8 +72,8 @@ extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); extern void qla2x00_cmd_timeout(srb_t *); -extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int); -extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *); +extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); +extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); extern void qla2x00_blink_led(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a91fea69ad63..e67bb0997818 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -32,7 +32,6 @@ static int qla2x00_fw_ready(scsi_qla_host_t *); static int qla2x00_configure_hba(scsi_qla_host_t *); static int qla2x00_configure_loop(scsi_qla_host_t *); static int qla2x00_configure_local_loop(scsi_qla_host_t *); -static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); static int qla2x00_configure_fabric(scsi_qla_host_t *); static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *); static int qla2x00_device_resync(scsi_qla_host_t *); @@ -1688,10 +1687,16 @@ static void qla2x00_rport_del(void *data) { fc_port_t *fcport = data; + struct fc_rport *rport; + unsigned long flags; + + spin_lock_irqsave(&fcport->rport_lock, flags); + rport = fcport->drport; + fcport->drport = NULL; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + if (rport) + fc_remote_port_delete(rport); - if (fcport->rport) - fc_remote_port_delete(fcport->rport); - fcport->rport = NULL; } /** @@ -1719,6 +1724,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; + spin_lock_init(&fcport->rport_lock); INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); @@ -2008,7 +2014,7 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha) { fc_port_t *fcport; - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 0); list_for_each_entry(fcport, &ha->fcports, list) { if (fcport->port_type != FCT_TARGET) continue; @@ -2032,13 +2038,9 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha) * Context: * Kernel context. */ -static void +void qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) { - uint16_t index; - unsigned long flags; - srb_t *sp; - fcport->ha = ha; fcport->login_retry = 0; fcport->port_login_retry_count = ha->port_down_retry_count * @@ -2047,28 +2049,6 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; - /* - * Check for outstanding cmd on tape Bypass LUN discovery if active - * command on tape. - */ - if (fcport->flags & FCF_TAPE_PRESENT) { - spin_lock_irqsave(&ha->hardware_lock, flags); - for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { - fc_port_t *sfcp; - - if ((sp = ha->outstanding_cmds[index]) != 0) { - sfcp = sp->fcport; - if (sfcp == fcport) { - atomic_set(&fcport->state, FCS_ONLINE); - spin_unlock_irqrestore( - &ha->hardware_lock, flags); - return; - } - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - } - if (fcport->port_type == FCT_INITIATOR || fcport->port_type == FCT_BROADCAST) fcport->device_type = TYPE_PROCESSOR; @@ -2084,24 +2064,29 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) { struct fc_rport_identifiers rport_ids; struct fc_rport *rport; + unsigned long flags; - if (fcport->rport) { - fc_remote_port_delete(fcport->rport); - fcport->rport = NULL; - } + if (fcport->drport) + qla2x00_rport_del(fcport); + if (fcport->rport) + return; rport_ids.node_name = wwn_to_u64(fcport->node_name); rport_ids.port_name = wwn_to_u64(fcport->port_name); rport_ids.port_id = fcport->d_id.b.domain << 16 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); + rport = fc_remote_port_add(ha->host, 0, &rport_ids); if (!rport) { qla_printk(KERN_WARNING, ha, "Unable to allocate fc remote port!\n"); return; } + spin_lock_irqsave(&fcport->rport_lock, flags); + fcport->rport = rport; *((fc_port_t **)rport->dd_data) = fcport; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + rport->supported_classes = fcport->supported_classes; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; @@ -2217,12 +2202,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { qla2x00_mark_device_lost(ha, fcport, - ql2xplogiabsentdevice); + ql2xplogiabsentdevice, 0); if (fcport->loop_id != FC_NO_LOOP_ID && (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { - ha->isp_ops.fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, @@ -2694,7 +2678,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha) if (atomic_read(&fcport->state) == FCS_ONLINE) { if (format != 3 || fcport->port_type != FCT_INITIATOR) { - qla2x00_mark_device_lost(ha, fcport, 0); + qla2x00_mark_device_lost(ha, fcport, + 0, 0); } } fcport->flags &= ~FCF_FARP_DONE; @@ -2741,8 +2726,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, ha->isp_ops.fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - qla2x00_mark_device_lost(ha, fcport, 1); - + qla2x00_mark_device_lost(ha, fcport, 1, 0); } else { qla2x00_update_fcport(ha, fcport); } @@ -2855,7 +2839,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, ha->isp_ops.fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - qla2x00_mark_device_lost(ha, fcport, 1); + qla2x00_mark_device_lost(ha, fcport, 1, 0); rval = 1; break; @@ -2990,6 +2974,17 @@ qla2x00_rescan_fcports(scsi_qla_host_t *ha) qla2x00_probe_for_all_luns(ha); } +void +qla2x00_update_fcports(scsi_qla_host_t *ha) +{ + fc_port_t *fcport; + + /* Go with deferred removal of rport references. */ + list_for_each_entry(fcport, &ha->fcports, list) + if (fcport->drport) + qla2x00_rport_del(fcport); +} + /* * qla2x00_abort_isp * Resets ISP and aborts all outstanding commands. @@ -3019,7 +3014,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 0); } else { if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f63af081d4ff..71a46fcee8cc 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -389,7 +389,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); } set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); @@ -432,7 +432,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); ha->device_flags |= DFLG_NO_CABLE; - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); } ha->flags.management_server_logged_in = 0; @@ -453,7 +453,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); } set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -482,7 +482,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); } if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { @@ -506,7 +506,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); } set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); @@ -580,7 +580,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) */ atomic_set(&ha->loop_state, LOOP_UP); - qla2x00_mark_all_devices_lost(ha); + qla2x00_mark_all_devices_lost(ha, 1); ha->flags.rscn_queue_overflow = 1; @@ -1091,7 +1091,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) cp->result = DID_BUS_BUSY << 16; if (atomic_read(&fcport->state) == FCS_ONLINE) { - qla2x00_mark_device_lost(ha, fcport, 1); + qla2x00_mark_device_lost(ha, fcport, 1, 1); } break; @@ -1135,7 +1135,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) - qla2x00_mark_device_lost(ha, fcport, 1); + qla2x00_mark_device_lost(ha, fcport, 1, 1); break; case CS_QUEUE_FULL: diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 4916847d84ec..5866a7c706a8 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -756,7 +756,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) if (ret == SUCCESS) { if (fcport->flags & FC_FABRIC_DEVICE) { ha->isp_ops.fabric_logout(ha, fcport->loop_id); - qla2x00_mark_device_lost(ha, fcport); + qla2x00_mark_device_lost(ha, fcport, 0, 0); } } #endif @@ -1642,6 +1642,31 @@ qla2x00_free_device(scsi_qla_host_t *ha) pci_disable_device(ha->pdev); } +static inline void +qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, + int defer) +{ + unsigned long flags; + struct fc_rport *rport; + + if (!fcport->rport) + return; + + rport = fcport->rport; + if (defer) { + spin_lock_irqsave(&fcport->rport_lock, flags); + fcport->drport = rport; + fcport->rport = NULL; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); + } else { + spin_lock_irqsave(&fcport->rport_lock, flags); + fcport->rport = NULL; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + fc_remote_port_delete(rport); + } +} + /* * qla2x00_mark_device_lost Updates fcport state when device goes offline. * @@ -1652,10 +1677,10 @@ qla2x00_free_device(scsi_qla_host_t *ha) * Context: */ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, - int do_login) + int do_login, int defer) { - if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - schedule_work(&fcport->rport_del_work); + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_schedule_rport_del(ha, fcport, defer); /* * We may need to retry the login, so don't change the state of the @@ -1702,7 +1727,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, * Context: */ void -qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) +qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) { fc_port_t *fcport; @@ -1716,10 +1741,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) */ if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; - if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - schedule_work(&fcport->rport_del_work); + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_schedule_rport_del(ha, fcport, defer); atomic_set(&fcport->state, FCS_DEVICE_LOST); } + + if (defer && ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); } /* @@ -2161,6 +2189,9 @@ qla2x00_do_dpc(void *data) ha->host_no)); } + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) + qla2x00_update_fcports(ha); + if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", ha->host_no)); @@ -2219,13 +2250,8 @@ qla2x00_do_dpc(void *data) DEBUG(printk("scsi(%ld): port login OK: logged in ID 0x%x\n", ha->host_no, fcport->loop_id)); - fcport->port_login_retry_count = - ha->port_down_retry_count * PORT_RETRY_TIME; - atomic_set(&fcport->state, FCS_ONLINE); - atomic_set(&fcport->port_down_timer, - ha->port_down_retry_count * PORT_RETRY_TIME); - - fcport->login_retry = 0; + qla2x00_update_fcport(ha, + fcport); } else if (status == 1) { set_bit(RELOGIN_NEEDED, &ha->dpc_flags); /* retry the login again */ @@ -2469,6 +2495,7 @@ qla2x00_timer(scsi_qla_host_t *ha) if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || + test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) || start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index cd54244058b5..6fddf17a3b70 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -510,6 +510,12 @@ static const struct mv_hw_ops mv6xxx_ops = { }; /* + * module options + */ +static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ + + +/* * Functions */ @@ -2191,7 +2197,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Enable interrupts */ - if (pci_enable_msi(pdev) == 0) { + if (msi && pci_enable_msi(pdev) == 0) { hpriv->hp_flags |= MV_HP_FLAG_MSI; } else { pci_intx(pdev, 1); @@ -2246,5 +2252,8 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); +module_param(msi, int, 0444); +MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); + module_init(mv_init); module_exit(mv_exit); diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index b017f85e6d6a..17f74d3c10e7 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -231,6 +231,10 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil_pci_tbl); MODULE_VERSION(DRV_VERSION); +static int slow_down = 0; +module_param(slow_down, int, 0444); +MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); + static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) { @@ -354,8 +358,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) } /* limit requests to 15 sectors */ - if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) { - printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n", + if (slow_down || + ((ap->flags & SIL_FLAG_MOD15WRITE) && + (quirks & SIL_QUIRK_MOD15WRITE))) { + printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", ap->id, dev->devno); ap->host->max_sectors = 15; ap->host->hostt->max_sectors = 15; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 245ca99a641e..c551bb84dbfb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1245,7 +1245,7 @@ static int __init init_scsi(void) if (error) goto cleanup_sysctl; - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); devfs_mk_dir("scsi"); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a2333d2c7af0..5cc97b721661 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1350,7 +1350,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) cmnd[4] = SCSI_REMOVAL_PREVENT; cmnd[5] = 0; - scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ, + scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ, 5, NULL, NULL, GFP_KERNEL); } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3574ba935af8..4a602853a98e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -436,6 +436,7 @@ free_bios: * scsi_execute_async - insert request * @sdev: scsi device * @cmd: scsi command + * @cmd_len: length of scsi cdb * @data_direction: data direction * @buffer: data buffer (this can be a kernel buffer or scatterlist) * @bufflen: len of buffer @@ -445,7 +446,7 @@ free_bios: * @flags: or into request flags **/ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, - int data_direction, void *buffer, unsigned bufflen, + int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, int timeout, int retries, void *privdata, void (*done)(void *, char *, int, int), gfp_t gfp) { @@ -472,7 +473,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, if (err) goto free_req; - req->cmd_len = COMMAND_SIZE(cmd[0]); + req->cmd_len = cmd_len; memcpy(req->cmd, cmd, req->cmd_len); req->sense = sioc->sense; req->sense_len = 0; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 59a1c9d9d3bd..723f7acbeb12 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -463,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb) } static void* -mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data) +mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) { struct mempool_zone *zone = pool_data; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index a3e0b7bc2d7b..210dab5879fa 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -377,7 +377,7 @@ static void sas_phy_release(struct device *dev) /** * sas_phy_alloc -- allocates and initialize a SAS PHY structure * @parent: Parent device - * @number: Port number + * @number: Phy index * * Allocates an SAS PHY structure. It will be added in the device tree * below the device specified by @parent, which has to be either a Scsi_Host @@ -595,8 +595,8 @@ struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) device_initialize(&rphy->dev); rphy->dev.parent = get_device(&parent->dev); rphy->dev.release = sas_rphy_release; - sprintf(rphy->dev.bus_id, "rphy-%d:%d", - shost->host_no, parent->number); + sprintf(rphy->dev.bus_id, "rphy-%d:%d-%d", + shost->host_no, parent->port_identifier, parent->number); transport_setup_device(&rphy->dev); return rphy; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 78aad9582bcf..2a547538d444 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -741,7 +741,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->duration = jiffies_to_msecs(jiffies); /* Now send everything of to mid-level. The next time we hear about this packet is when sg_cmd_done() is called (i.e. a callback). */ - if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer, + if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, hp->dxfer_len, srp->data.k_use_sg, timeout, SG_DEFAULT_RETRIES, srp, sg_cmd_done, GFP_ATOMIC)) { @@ -1679,7 +1679,7 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) { int sg_bufflen = tablesize * sizeof(struct scatterlist); - unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN; + gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN; /* * TODO: test without low_dma, we should not need it since diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 13b1d3aac265..7f96f33c1bb1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -508,7 +508,7 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd STp->buffer->cmdstat.have_sense = 0; STp->buffer->syscall_result = 0; - if (scsi_execute_async(STp->device, cmd, direction, + if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) { /* could not allocate the buffer or request was too large */ diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 221999bcf8fe..8c5c276c5577 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -362,11 +362,11 @@ static struct uart_ops serial21285_ops = { static struct uart_port serial21285_port = { .mapbase = 0x42000160, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = NO_IRQ, .fifosize = 16, .ops = &serial21285_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, }; static void serial21285_setup_ports(void) diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 8cbf0fc5a225..7f0f35a05dca 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -332,7 +332,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg * Make sure that we do not overflow the buffer */ if (tty_request_buffer_room(tty, 1) == 0) { - schedule_work(&tty->flip.work); + tty_schedule_flip(tty); return; } @@ -353,7 +353,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg } while((rx = uart->urx.w) & URX_DATA_READY); #endif - schedule_work(&tty->flip.work); + tty_schedule_flip(tty); clear_and_exit: return; diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 60f5a5dc17f1..9843ae3d420e 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -509,7 +509,7 @@ static _INLINE_ void receive_chars(ser_info_t *info) info->rx_cur = (QUICC_BD *)bdp; - schedule_work(&tty->flip.work); + tty_schedule_flip(tty); } static _INLINE_ void receive_break(ser_info_t *info) @@ -521,7 +521,7 @@ static _INLINE_ void receive_break(ser_info_t *info) * the break. If not, we exit now, losing the break. FIXME */ tty_insert_flip_char(tty, 0, TTY_BREAK); - schedule_work(&tty->flip.work); + tty_schedule_flip(tty); } static _INLINE_ void transmit_chars(ser_info_t *info) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d9ce8c549416..b1fc97d5f643 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -31,7 +31,6 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> -#include <linux/mca.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/tty.h> @@ -2027,12 +2026,6 @@ static void serial8250_config_port(struct uart_port *port, int flags) int ret; /* - * Don't probe for MCA ports on non-MCA machines. - */ - if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus) - return; - - /* * Find the region that we can probe for. This in turn * tells us whether we can probe for the type of port. */ @@ -2164,7 +2157,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) /* * Wait for transmitter & holding register to empty */ -static inline void wait_for_xmitr(struct uart_8250_port *up) +static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) { unsigned int status, tmout = 10000; @@ -2178,7 +2171,7 @@ static inline void wait_for_xmitr(struct uart_8250_port *up) if (--tmout == 0) break; udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + } while ((status & bits) != bits); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { @@ -2218,7 +2211,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) * Now, do each character */ for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); + wait_for_xmitr(up, UART_LSR_THRE); /* * Send the character out. @@ -2226,7 +2219,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) */ serial_out(up, UART_TX, *s); if (*s == 10) { - wait_for_xmitr(up); + wait_for_xmitr(up, UART_LSR_THRE); serial_out(up, UART_TX, 13); } } @@ -2235,8 +2228,9 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore the IER */ - wait_for_xmitr(up); - serial_out(up, UART_IER, ier); + wait_for_xmitr(up, BOTH_EMPTY); + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, ier | UART_IER_THRI); } static int serial8250_console_setup(struct console *co, char *options) @@ -2595,15 +2589,11 @@ static int __init serial8250_init(void) if (ret) goto out; - ret = platform_driver_register(&serial8250_isa_driver); - if (ret) - goto unreg_uart_drv; - serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY); if (!serial8250_isa_devs) { ret = -ENOMEM; - goto unreg_plat_drv; + goto unreg_uart_drv; } ret = platform_device_add(serial8250_isa_devs); @@ -2612,12 +2602,13 @@ static int __init serial8250_init(void) serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); - goto out; + ret = platform_driver_register(&serial8250_isa_driver); + if (ret == 0) + goto out; + platform_device_del(serial8250_isa_devs); put_dev: platform_device_put(serial8250_isa_devs); - unreg_plat_drv: - platform_driver_unregister(&serial8250_isa_driver); unreg_uart_drv: uart_unregister_driver(&serial8250_reg); out: diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c index a802bdce6e5d..809f89ab965c 100644 --- a/drivers/serial/8250_acpi.c +++ b/drivers/serial/8250_acpi.c @@ -27,7 +27,7 @@ struct serial_private { static acpi_status acpi_serial_mmio(struct uart_port *port, struct acpi_resource_address64 *addr) { - port->mapbase = addr->min_address_range; + port->mapbase = addr->minimum; port->iotype = UPIO_MEM; port->flags |= UPF_IOREMAP; return AE_OK; @@ -36,8 +36,8 @@ static acpi_status acpi_serial_mmio(struct uart_port *port, static acpi_status acpi_serial_port(struct uart_port *port, struct acpi_resource_io *io) { - if (io->range_length) { - port->iobase = io->min_base_address; + if (io->address_length) { + port->iobase = io->minimum; port->iotype = UPIO_PORT; } else printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__); @@ -45,13 +45,13 @@ static acpi_status acpi_serial_port(struct uart_port *port, } static acpi_status acpi_serial_ext_irq(struct uart_port *port, - struct acpi_resource_ext_irq *ext_irq) + struct acpi_resource_extended_irq *ext_irq) { int rc; - if (ext_irq->number_of_interrupts > 0) { + if (ext_irq->interrupt_count > 0) { rc = acpi_register_gsi(ext_irq->interrupts[0], - ext_irq->edge_level, ext_irq->active_high_low); + ext_irq->triggering, ext_irq->polarity); if (rc < 0) return AE_ERROR; port->irq = rc; @@ -64,9 +64,9 @@ static acpi_status acpi_serial_irq(struct uart_port *port, { int rc; - if (irq->number_of_interrupts > 0) { + if (irq->interrupt_count > 0) { rc = acpi_register_gsi(irq->interrupts[0], - irq->edge_level, irq->active_high_low); + irq->triggering, irq->polarity); if (rc < 0) return AE_ERROR; port->irq = rc; @@ -83,11 +83,11 @@ static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data) status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) return acpi_serial_mmio(port, &addr); - else if (res->id == ACPI_RSTYPE_IO) + else if (res->type == ACPI_RESOURCE_TYPE_IO) return acpi_serial_port(port, &res->data.io); - else if (res->id == ACPI_RSTYPE_EXT_IRQ) + else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) return acpi_serial_ext_irq(port, &res->data.extended_irq); - else if (res->id == ACPI_RSTYPE_IRQ) + else if (res->type == ACPI_RESOURCE_TYPE_IRQ) return acpi_serial_irq(port, &res->data.irq); return AE_OK; } diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c index 06ae8fbcc947..8d8d7a70d03e 100644 --- a/drivers/serial/8250_au1x00.c +++ b/drivers/serial/8250_au1x00.c @@ -56,7 +56,6 @@ static struct plat_serial8250_port au1x00_data[] = { #elif defined(CONFIG_SOC_AU1550) PORT(UART0_ADDR, AU1550_UART0_INT), PORT(UART1_ADDR, AU1550_UART1_INT), - PORT(UART2_ADDR, AU1550_UART2_INT), PORT(UART3_ADDR, AU1550_UART3_INT), #elif defined(CONFIG_SOC_AU1200) PORT(UART0_ADDR, AU1200_UART0_INT), diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 589fb076654a..94886c000d2a 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -439,6 +439,20 @@ static int pci_siig_init(struct pci_dev *dev) return -ENODEV; } +static int pci_siig_setup(struct serial_private *priv, + struct pciserial_board *board, + struct uart_port *port, int idx) +{ + unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; + + if (idx > 3) { + bar = 4; + offset = (idx - 4) * 8; + } + + return setup_port(priv, port, bar, offset, 0); +} + /* * Timedia has an explosion of boards, and to avoid the PCI table from * growing *huge*, we use this function to collapse some 70 entries @@ -748,7 +762,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .init = pci_siig_init, - .setup = pci_default_setup, + .setup = pci_siig_setup, }, /* * Titan cards @@ -940,6 +954,7 @@ enum pci_board_num_t { pbn_b2_bt_2_921600, pbn_b2_bt_4_921600, + pbn_b3_2_115200, pbn_b3_4_115200, pbn_b3_8_115200, @@ -1311,6 +1326,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b3_2_115200] = { + .flags = FL_BASE3, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, [pbn_b3_4_115200] = { .flags = FL_BASE3, .num_ports = 4, @@ -1861,6 +1882,10 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0, pbn_b0_4_1843200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_AFAVLAB, + PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0, + pbn_b0_4_1152000 }, { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0, @@ -2134,6 +2159,15 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, /* * Computone devices submitted by Doug McNash dmcnash@computone.com @@ -2272,6 +2306,9 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_nec_nile4 }, + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b3_2_115200 }, { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_4_115200 }, diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 5e7199f7b59c..0f4361c8466b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -23,7 +23,7 @@ config SERIAL_8250 work.) To compile this driver as a module, choose M here: the - module will be called serial. + module will be called 8250. [WARNING: Do not compile this driver as a module if you are using non-standard serial ports, since the configuration information will be lost when the driver is unloaded. This limitation may be lifted @@ -98,6 +98,7 @@ config SERIAL_8250_NR_UARTS config SERIAL_8250_RUNTIME_UARTS int "Number of 8250/16550 serial ports to register at runtime" depends on SERIAL_8250 + range 0 SERIAL_8250_NR_UARTS default "4" help Set this to the maximum number of serial ports you want @@ -301,7 +302,7 @@ config SERIAL_AT91_TTYAT depends on SERIAL_AT91=y help Say Y here if you wish to have the five internal AT91RM9200 UARTs - appear as /dev/ttyAT0-4 (major 240, minor 0-4) instead of the + appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if you also want other UARTs, such as external 8250/16C550 compatible UARTs. @@ -892,20 +893,20 @@ config SERIAL_VR41XX_CONSOLE a console on a serial port, say Y. Otherwise, say N. config SERIAL_JSM - tristate "Digi International NEO PCI Support" - depends on PCI && BROKEN - select SERIAL_CORE - help - This is a driver for Digi International's Neo series - of cards which provide multiple serial ports. You would need - something like this to connect more than two modems to your Linux - box, for instance in order to become a dial-in server. This driver - supports PCI boards only. - If you have a card like this, say Y here and read the file - <file:Documentation/jsm.txt>. - - To compile this driver as a module, choose M here: the - module will be called jsm. + tristate "Digi International NEO PCI Support" + depends on PCI + select SERIAL_CORE + help + This is a driver for Digi International's Neo series + of cards which provide multiple serial ports. You would need + something like this to connect more than two modems to your Linux + box, for instance in order to become a dial-in server. This driver + supports PCI boards only. + If you have a card like this, say Y here and read the file + <file:Documentation/jsm.txt>. + + To compile this driver as a module, choose M here: the + module will be called jsm. config SERIAL_SGI_IOC4 tristate "SGI IOC4 controller serial support" diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 3490022e9fdc..321a3b3a5728 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -561,12 +561,12 @@ static struct uart_amba_port amba_ports[UART_NR] = { .port = { .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), .mapbase = INTEGRATOR_UART0_BASE, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = IRQ_UARTINT0, .uartclk = 14745600, .fifosize = 16, .ops = &amba_pl010_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .dtr_mask = 1 << 5, @@ -576,12 +576,12 @@ static struct uart_amba_port amba_ports[UART_NR] = { .port = { .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), .mapbase = INTEGRATOR_UART1_BASE, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = IRQ_UARTINT1, .uartclk = 14745600, .fifosize = 16, .ops = &amba_pl010_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .dtr_mask = 1 << 7, diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 0e206063d685..2113feb75c39 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -222,8 +222,6 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) while (status & (AT91_US_RXRDY)) { ch = UART_GET_CHAR(port); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; port->icount.rx++; flg = TTY_NORMAL; diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index ceb5d7f37bbd..344022fe53ef 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -892,7 +892,7 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res int ret = 0; switch (up->port.iotype) { - case SERIAL_IO_MEM: + case UPIO_MEM: if (up->port.mapbase) { *res = request_mem_region(up->port.mapbase, size, "serial"); if (!*res) @@ -900,8 +900,8 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res } break; - case SERIAL_IO_HUB6: - case SERIAL_IO_PORT: + case UPIO_HUB6: + case UPIO_PORT: *res = request_region(up->port.iobase, size, "serial"); if (!*res) ret = -EBUSY; @@ -919,7 +919,7 @@ static void serial8250_release_port(struct uart_port *port) size <<= up->port.regshift; switch (up->port.iotype) { - case SERIAL_IO_MEM: + case UPIO_MEM: if (up->port.mapbase) { /* * Unmap the area. @@ -935,8 +935,8 @@ static void serial8250_release_port(struct uart_port *port) } break; - case SERIAL_IO_HUB6: - case SERIAL_IO_PORT: + case UPIO_HUB6: + case UPIO_PORT: start = up->port.iobase; if (size) diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 8ef999481f93..ce7b2e4ecd17 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -410,7 +410,7 @@ static struct uart_port clps711x_ports[UART_NR] = { .fifosize = 16, .ops = &clps711x_pops, .line = 0, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, }, { .iobase = SYSCON2, @@ -419,7 +419,7 @@ static struct uart_port clps711x_ports[UART_NR] = { .fifosize = 16, .ops = &clps711x_pops, .line = 1, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, } }; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 16af5626c243..b7bf4c698a47 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -252,12 +252,9 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) /* If we have not enough room in tty flip buffer, then we try * later, which will be the next rx-interrupt or a timeout */ - if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void *)tty); - if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - return; - } + if(tty_buffer_request_room(tty, i) < i) { + printk(KERN_WARNING "No room in flip buffer\n"); + return; } /* get pointer */ @@ -276,9 +273,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) continue; error_return: - *tty->flip.char_buf_ptr++ = ch; - *tty->flip.flag_buf_ptr++ = flg; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flg); } /* End while (i--) */ @@ -908,7 +903,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SMC1_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .flags = FLAG_SMC, @@ -922,7 +917,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SMC2_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .flags = FLAG_SMC, @@ -939,7 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SCC1_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .tx_nrfifos = TX_NUM_FIFO, @@ -953,7 +948,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SCC2_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .tx_nrfifos = TX_NUM_FIFO, @@ -967,7 +962,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SCC3_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .tx_nrfifos = TX_NUM_FIFO, @@ -981,7 +976,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .port = { .irq = SCC4_IRQ, .ops = &cpm_uart_pops, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .lock = SPIN_LOCK_UNLOCKED, }, .tx_nrfifos = TX_NUM_FIFO, diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index a64ba26a94e8..ba5541de673b 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -262,6 +262,7 @@ static inline void dz_receive_chars(struct dz_port *dport) } tty_insert_flip_char(tty, ch, flag); ignore_char: + ; } while (status & DZ_DVAL); if (tty) @@ -650,7 +651,7 @@ static void __init dz_init_ports(void) for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { spin_lock_init(&dport->port.lock); dport->port.membase = (char *) base; - dport->port.iotype = SERIAL_IO_PORT; + dport->port.iotype = UPIO_PORT; dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; dport->port.line = i; dport->port.fifosize = 1; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 587cc6a95114..4d53fb5ca87b 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -402,10 +402,10 @@ static int imx_startup(struct uart_port *port) DRIVER_NAME, sport); if (retval) goto error_out2; - retval = request_irq(sport->rtsirq, imx_rtsint, 0, + retval = request_irq(sport->rtsirq, imx_rtsint, + SA_TRIGGER_FALLING | SA_TRIGGER_RISING, DRIVER_NAME, sport); if (retval) goto error_out3; - set_irq_type(sport->rtsirq, IRQT_BOTHEDGE); /* * Finally, clear and enable interrupts @@ -668,13 +668,13 @@ static struct imx_port imx_ports[] = { .rtsirq = UART1_MINT_RTS, .port = { .type = PORT_IMX, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void *)IMX_UART1_BASE, .mapbase = IMX_UART1_BASE, /* FIXME */ .irq = UART1_MINT_RX, .uartclk = 16000000, .fifosize = 8, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .ops = &imx_pops, .line = 0, }, @@ -684,13 +684,13 @@ static struct imx_port imx_ports[] = { .rtsirq = UART2_MINT_RTS, .port = { .type = PORT_IMX, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void *)IMX_UART2_BASE, .mapbase = IMX_UART2_BASE, /* FIXME */ .irq = UART2_MINT_RX, .uartclk = 16000000, .fifosize = 8, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .ops = &imx_pops, .line = 1, }, diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 1d85533d46d2..f3763d2ccb86 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1717,11 +1717,9 @@ ioc4_change_speed(struct uart_port *the_port, } if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; port->ip_sscr |= IOC4_SSCR_HFC_EN; } else { - info->flags &= ~ASYNC_CTS_FLOW; port->ip_sscr &= ~IOC4_SSCR_HFC_EN; } writel(port->ip_sscr, &port->ip_serial_regs->sscr); @@ -1760,18 +1758,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) info = the_port->info; - if (info->tty) { - set_bit(TTY_IO_ERROR, &info->tty->flags); - clear_bit(TTY_IO_ERROR, &info->tty->flags); - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } local_open(port); /* set the speed of the serial port */ diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 66f117d15065..419dd3cd7862 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -215,7 +215,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) /* Lower and upper byte of baud rate generator divisor. */ write_zsreg(channel, R12, regs[R12]); write_zsreg(channel, R13, regs[R13]); - + /* Now rewrite R14, with BRENAB (if set). */ write_zsreg(channel, R14, regs[R14]); @@ -571,7 +571,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) else clear_bits |= DTR; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ up->curregs[R5] |= set_bits; up->curregs[R5] &= ~clear_bits; write_zsreg(channel, R5, up->curregs[R5]); @@ -654,7 +654,7 @@ static void ip22zilog_enable_ms(struct uart_port *port) if (new_reg != up->curregs[R15]) { up->curregs[R15] = new_reg; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R15, up->curregs[R15]); } } @@ -680,7 +680,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) if (new_reg != up->curregs[R5]) { up->curregs[R5] = new_reg; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R5, up->curregs[R5]); } diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 18753193f59b..dfc1e86d3aa1 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -380,7 +380,6 @@ struct neo_uart_struct { extern struct uart_driver jsm_uart_driver; extern struct board_ops jsm_neo_ops; extern int jsm_debug; -extern int jsm_rawreadok; /************************************************************************* * diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 7e56c7824194..b1b66e71d281 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -49,11 +49,8 @@ struct uart_driver jsm_uart_driver = { }; int jsm_debug; -int jsm_rawreadok; module_param(jsm_debug, int, 0); -module_param(jsm_rawreadok, int, 0); MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); -MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input"); static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index 6f22b42d9337..87e4e2cf8ce7 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -965,56 +965,47 @@ static void neo_param(struct jsm_channel *ch) baud = ch->ch_custom_speed; if (ch->ch_flags & CH_BAUD0) ch->ch_flags &= ~(CH_BAUD0); - } else { - int iindex = 0; - int jindex = 0; - - const u64 bauds[4][16] = { - { - 0, 50, 75, 110, - 134, 150, 200, 300, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { - 0, 57600, 76800, 115200, - 131657, 153600, 230400, 460800, - 921600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 } - }; - - baud = C_BAUD(ch->uart_port.info->tty) & 0xff; - - if (ch->ch_c_cflag & CBAUDEX) - iindex = 1; - - jindex = baud; - - if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) - baud = bauds[iindex][jindex]; - else { - jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev, - "baud indices were out of range (%d)(%d)", - iindex, jindex); - baud = 0; + } else { + int i; + unsigned int cflag; + static struct { + unsigned int rate; + unsigned int cflag; + } baud_rates[] = { + { 921600, B921600 }, + { 460800, B460800 }, + { 230400, B230400 }, + { 115200, B115200 }, + { 57600, B57600 }, + { 38400, B38400 }, + { 19200, B19200 }, + { 9600, B9600 }, + { 4800, B4800 }, + { 2400, B2400 }, + { 1200, B1200 }, + { 600, B600 }, + { 300, B300 }, + { 200, B200 }, + { 150, B150 }, + { 134, B134 }, + { 110, B110 }, + { 75, B75 }, + { 50, B50 }, + }; + + cflag = C_BAUD(ch->uart_port.info->tty); + baud = 9600; + for (i = 0; i < ARRAY_SIZE(baud_rates); i++) { + if (baud_rates[i].cflag == cflag) { + baud = baud_rates[i].rate; + break; } - - if (baud == 0) - baud = 9600; - - if (ch->ch_flags & CH_BAUD0) - ch->ch_flags &= ~(CH_BAUD0); } + if (ch->ch_flags & CH_BAUD0) + ch->ch_flags &= ~(CH_BAUD0); + } + if (ch->ch_c_cflag & PARENB) lcr |= UART_LCR_PARITY; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 6fa0d62d6f68..4d48b625cd3d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -20,8 +20,10 @@ * * Contact Information: * Scott H Kilau <Scott_Kilau@digi.com> - * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> - * + * Ananda Venkatarman <mansarov@us.ibm.com> + * Modifications: + * 01/19/06: changed jsm_input routine to use the dynamically allocated + * tty_buffer changes. Contributors: Scott Kilau and Ananda V. ***********************************************************************/ #include <linux/tty.h> #include <linux/tty_flip.h> @@ -497,16 +499,15 @@ void jsm_input(struct jsm_channel *ch) { struct jsm_board *bd; struct tty_struct *tp; + struct tty_ldisc *ld; u32 rmask; u16 head; u16 tail; int data_len; unsigned long lock_flags; - int flip_len; + int flip_len = 0; int len = 0; int n = 0; - char *buf = NULL; - char *buf2 = NULL; int s = 0; int i = 0; @@ -574,56 +575,50 @@ void jsm_input(struct jsm_channel *ch) /* * If the rxbuf is empty and we are not throttled, put as much - * as we can directly into the linux TTY flip buffer. - * The jsm_rawreadok case takes advantage of carnal knowledge that - * the char_buf and the flag_buf are next to each other and - * are each of (2 * TTY_FLIPBUF_SIZE) size. + * as we can directly into the linux TTY buffer. * - * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf - *actually still uses the flag buffer, so you can't - *use it for input data */ - if (jsm_rawreadok) { - if (tp->real_raw) - flip_len = MYFLIPLEN; - else - flip_len = 2 * TTY_FLIPBUF_SIZE; - } else - flip_len = TTY_FLIPBUF_SIZE - tp->flip.count; + flip_len = TTY_FLIPBUF_SIZE; len = min(data_len, flip_len); len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); + ld = tty_ldisc_ref(tp); - if (len <= 0) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); - return; - } + /* + * If the DONT_FLIP flag is on, don't flush our buffer, and act + * like the ld doesn't have any space to put the data right now. + */ + if (test_bit(TTY_DONT_FLIP, &tp->flags)) + len = 0; /* - * If we're bypassing flip buffers on rx, we can blast it - * right into the beginning of the buffer. + * If we were unable to get a reference to the ld, + * don't flush our buffer, and act like the ld doesn't + * have any space to put the data right now. */ - if (jsm_rawreadok) { - if (tp->real_raw) { - if (ch->ch_flags & CH_FLIPBUF_IN_USE) { - jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, - "JSM - FLIPBUF in use. delaying input\n"); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - return; - } - ch->ch_flags |= CH_FLIPBUF_IN_USE; - buf = ch->ch_bd->flipbuf; - buf2 = NULL; - } else { - buf = tp->flip.char_buf; - buf2 = tp->flip.flag_buf; - } + if (!ld) { + len = 0; } else { - buf = tp->flip.char_buf_ptr; - buf2 = tp->flip.flag_buf_ptr; + /* + * If ld doesn't have a pointer to a receive_buf function, + * flush the data, then act like the ld doesn't have any + * space to put the data right now. + */ + if (!ld->receive_buf) { + ch->ch_r_head = ch->ch_r_tail; + len = 0; + } } + if (len <= 0) { + spin_unlock_irqrestore(&ch->ch_lock, lock_flags); + jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); + if (ld) + tty_ldisc_deref(ld); + return; + } + + len = tty_buffer_request_room(tp, len); n = len; /* @@ -638,121 +633,47 @@ void jsm_input(struct jsm_channel *ch) if (s <= 0) break; - memcpy(buf, ch->ch_rqueue + tail, s); - - /* buf2 is only set when port isn't raw */ - if (buf2) - memcpy(buf2, ch->ch_equeue + tail, s); - - tail += s; - buf += s; - if (buf2) - buf2 += s; - n -= s; - /* Flip queue if needed */ - tail &= rmask; - } + /* + * If conditions are such that ld needs to see all + * UART errors, we will have to walk each character + * and error byte and send them to the buffer one at + * a time. + */ - /* - * In high performance mode, we don't have to update - * flag_buf or any of the counts or pointers into flip buf. - */ - if (!jsm_rawreadok) { if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { - for (i = 0; i < len; i++) { + for (i = 0; i < s; i++) { /* * Give the Linux ld the flags in the * format it likes. */ - if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) - tp->flip.flag_buf_ptr[i] = TTY_BREAK; - else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) - tp->flip.flag_buf_ptr[i] = TTY_PARITY; - else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) - tp->flip.flag_buf_ptr[i] = TTY_FRAME; + if (*(ch->ch_equeue +tail +i) & UART_LSR_BI) + tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK); + else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE) + tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY); + else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE) + tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME); else - tp->flip.flag_buf_ptr[i] = TTY_NORMAL; + tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL); } } else { - memset(tp->flip.flag_buf_ptr, 0, len); + tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ; } - - tp->flip.char_buf_ptr += len; - tp->flip.flag_buf_ptr += len; - tp->flip.count += len; - } - else if (!tp->real_raw) { - if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { - for (i = 0; i < len; i++) { - /* - * Give the Linux ld the flags in the - * format it likes. - */ - if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) - tp->flip.flag_buf_ptr[i] = TTY_BREAK; - else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) - tp->flip.flag_buf_ptr[i] = TTY_PARITY; - else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) - tp->flip.flag_buf_ptr[i] = TTY_FRAME; - else - tp->flip.flag_buf_ptr[i] = TTY_NORMAL; - } - } else - memset(tp->flip.flag_buf, 0, len); + tail += s; + n -= s; + /* Flip queue if needed */ + tail &= rmask; } - /* - * If we're doing raw reads, jam it right into the - * line disc bypassing the flip buffers. - */ - if (jsm_rawreadok) { - if (tp->real_raw) { - ch->ch_r_tail = tail & rmask; - ch->ch_e_tail = tail & rmask; - - jsm_check_queue_flow_control(ch); - - /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ + ch->ch_r_tail = tail & rmask; + ch->ch_e_tail = tail & rmask; + jsm_check_queue_flow_control(ch); + spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); + /* Tell the tty layer its okay to "eat" the data now */ + tty_flip_buffer_push(tp); - jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, - "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n", - __LINE__, len, ch->ch_bd->boardnum); - tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); - - /* Allow use of channel flip buffer again */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - ch->ch_flags &= ~CH_FLIPBUF_IN_USE; - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - } else { - ch->ch_r_tail = tail & rmask; - ch->ch_e_tail = tail & rmask; - - jsm_check_queue_flow_control(ch); - - /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, - "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n", - __LINE__, len, ch->ch_bd->boardnum); - - tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len); - } - } else { - ch->ch_r_tail = tail & rmask; - ch->ch_e_tail = tail & rmask; - - jsm_check_queue_flow_control(ch); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, - "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__); - tty_schedule_flip(tp); - } + if (ld) + tty_ldisc_deref(ld); jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); } diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index b48066a64a7d..242a04104393 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -80,7 +80,7 @@ #include <asm/serial.h> /* Standard COM flags */ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) /* * SERIAL_PORT_DFNS tells us about built-in ports that have no diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h index 07d0dd80aa3d..7c3ec24f7e50 100644 --- a/drivers/serial/m32r_sio.h +++ b/drivers/serial/m32r_sio.h @@ -37,7 +37,7 @@ struct old_serial_port { unsigned int irq; unsigned int flags; unsigned char io_type; - unsigned char *iomem_base; + unsigned char __iomem *iomem_base; unsigned short iomem_reg_shift; }; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index d957a3a9edf1..8cbbb954df2c 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -57,20 +57,16 @@ struct timer_list mcfrs_timer_struct; * keep going. Perhaps one day the cflag settings for the * console can be used instead. */ -#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ - defined(CONFIG_senTec) || defined(CONFIG_SNEHA) -#define CONSOLE_BAUD_RATE 19200 -#define DEFAULT_CBAUD B19200 -#endif - #if defined(CONFIG_HW_FEITH) #define CONSOLE_BAUD_RATE 38400 #define DEFAULT_CBAUD B38400 -#endif - -#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) +#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 +#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ + defined(CONFIG_senTec) || defined(CONFIG_SNEHA) +#define CONSOLE_BAUD_RATE 19200 +#define DEFAULT_CBAUD B19200 #endif #ifndef CONSOLE_BAUD_RATE @@ -350,8 +346,7 @@ static inline void receive_chars(struct mcf_serial *info) } tty_insert_flip_char(tty, ch, flag); } - - schedule_work(&tty->flip.work); + tty_schedule_flip(tty); return; } diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 4e49168c3176..868eaf4a1a68 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -462,7 +462,7 @@ static int __init mux_probe(struct parisc_device *dev) port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); - port->iotype = SERIAL_IO_MEM; + port->iotype = UPIO_MEM; port->type = PORT_MUX; port->irq = NO_IRQ; port->uartclk = 0; diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 4e03a87f3fb4..9b7ed58cb53b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1492,7 +1492,7 @@ no_dma: /* * Init remaining bits of "port" structure */ - uap->port.iotype = SERIAL_IO_MEM; + uap->port.iotype = UPIO_MEM; uap->port.irq = np->intrs[0].line; uap->port.uartclk = ZS_CLOCK; uap->port.fifosize = 1; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index eb4883efb7c6..7410e093a6b9 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -161,7 +161,11 @@ s3c24xx_serial_dbg(const char *fmt, ...) /* we can support 3 uarts, but not always use them */ +#ifdef CONFIG_CPU_S3C2400 +#define NR_PORTS (2) +#else #define NR_PORTS (3) +#endif /* port irq numbers */ @@ -1060,7 +1064,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); port->mapbase = res->start; - port->membase = S3C24XX_VA_UART + (res->start - S3C2410_PA_UART); + port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); port->irq = platform_get_irq(platdev, 0); ourport->clk = clk_get(&platdev->dev, "uart"); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 1bd93168f504..2c00b8625852 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -628,7 +628,7 @@ static void __init sa1100_init_ports(void) sa1100_ports[i].port.ops = &sa1100_pops; sa1100_ports[i].port.fifosize = 8; sa1100_ports[i].port.line = i; - sa1100_ports[i].port.iotype = SERIAL_IO_MEM; + sa1100_ports[i].port.iotype = UPIO_MEM; init_timer(&sa1100_ports[i].timer); sa1100_ports[i].timer.function = sa1100_timeout; sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i]; @@ -665,21 +665,21 @@ void __init sa1100_register_uart(int idx, int port) sa1100_ports[idx].port.membase = (void __iomem *)&Ser1UTCR0; sa1100_ports[idx].port.mapbase = _Ser1UTCR0; sa1100_ports[idx].port.irq = IRQ_Ser1UART; - sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF; break; case 2: sa1100_ports[idx].port.membase = (void __iomem *)&Ser2UTCR0; sa1100_ports[idx].port.mapbase = _Ser2UTCR0; sa1100_ports[idx].port.irq = IRQ_Ser2ICP; - sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF; break; case 3: sa1100_ports[idx].port.membase = (void __iomem *)&Ser3UTCR0; sa1100_ports[idx].port.mapbase = _Ser3UTCR0; sa1100_ports[idx].port.irq = IRQ_Ser3UART; - sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + sa1100_ports[idx].port.flags = UPF_BOOT_AUTOCONF; break; default: diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 943770470b9d..95fb4939c675 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -332,7 +332,7 @@ uart_get_baud_rate(struct uart_port *port, struct termios *termios, struct termios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; - unsigned int flags = port->flags & UPF_SPD_MASK; + upf_t flags = port->flags & UPF_SPD_MASK; if (flags == UPF_SPD_HI) altbaud = 57600; @@ -615,8 +615,9 @@ static int uart_set_info(struct uart_state *state, struct serial_struct new_serial; struct uart_port *port = state->port; unsigned long new_port; - unsigned int change_irq, change_port, old_flags, closing_wait; + unsigned int change_irq, change_port, closing_wait; unsigned int old_custom_divisor, close_delay; + upf_t old_flags, new_flags; int retval = 0; if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) @@ -655,6 +656,7 @@ static int uart_set_info(struct uart_state *state, new_serial.type != port->type; old_flags = port->flags; + new_flags = new_serial.flags; old_custom_divisor = port->custom_divisor; if (!capable(CAP_SYS_ADMIN)) { @@ -664,10 +666,10 @@ static int uart_set_info(struct uart_state *state, (close_delay != state->close_delay) || (closing_wait != state->closing_wait) || (new_serial.xmit_fifo_size != port->fifosize) || - (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) + (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0)) goto exit; port->flags = ((port->flags & ~UPF_USR_MASK) | - (new_serial.flags & UPF_USR_MASK)); + (new_flags & UPF_USR_MASK)); port->custom_divisor = new_serial.custom_divisor; goto check_and_exit; } @@ -764,7 +766,7 @@ static int uart_set_info(struct uart_state *state, port->irq = new_serial.irq; port->uartclk = new_serial.baud_base * 16; port->flags = (port->flags & ~UPF_CHANGE_MASK) | - (new_serial.flags & UPF_CHANGE_MASK); + (new_flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; state->close_delay = close_delay; state->closing_wait = closing_wait; @@ -1870,7 +1872,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) mutex_lock(&state->mutex); if (state->info && state->info->flags & UIF_INITIALIZED) { - struct uart_ops *ops = port->ops; + const struct uart_ops *ops = port->ops; spin_lock_irq(&port->lock); ops->stop_tx(port); @@ -1932,7 +1934,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } if (state->info && state->info->flags & UIF_INITIALIZED) { - struct uart_ops *ops = port->ops; + const struct uart_ops *ops = port->ops; int ret; ops->set_mctrl(port, 0); @@ -2235,7 +2237,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) * If this port is a console, then the spinlock is already * initialised. */ - if (!uart_console(port)) + if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) spin_lock_init(&port->lock); uart_configure_port(drv, state, port); diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index d4a1f0e798c1..04186eaae227 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -501,12 +501,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { .port = { .membase = (void*) io_p2v (UART1_PHYS), .mapbase = UART1_PHYS, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = IRQ_UART1INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, }, @@ -514,12 +514,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { .port = { .membase = (void*) io_p2v (UART2_PHYS), .mapbase = UART2_PHYS, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = IRQ_UART2INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, }, @@ -527,12 +527,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { .port = { .membase = (void*) io_p2v (UART3_PHYS), .mapbase = UART3_PHYS, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = IRQ_UART3INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 2, }, }, diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index a9e070759628..44f6bf79bbe1 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -42,6 +42,7 @@ #include <linux/delay.h> #include <linux/console.h> #include <linux/bitops.h> +#include <linux/generic_serial.h> #ifdef CONFIG_CPU_FREQ #include <linux/notifier.h> @@ -53,7 +54,9 @@ #include <asm/irq.h> #include <asm/uaccess.h> -#include <linux/generic_serial.h> +#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) +#include <asm/clock.h> +#endif #ifdef CONFIG_SH_STANDARD_BIOS #include <asm/sh_bios.h> @@ -86,9 +89,11 @@ static void sci_stop_rx(struct uart_port *port); static int sci_request_irq(struct sci_port *port); static void sci_free_irq(struct sci_port *port); -static struct sci_port sci_ports[SCI_NPORTS]; +static struct sci_port sci_ports[]; static struct uart_driver sci_uart_driver; +#define SCI_NPORTS sci_uart_driver.nr + #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) static void handle_error(struct uart_port *port) @@ -168,7 +173,7 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count) int usegdb=0; #ifdef CONFIG_SH_STANDARD_BIOS - /* This call only does a trap the first time it is + /* This call only does a trap the first time it is * called, and so is safe to do here unconditionally */ usegdb |= sh_bios_in_gdb_mode(); @@ -324,47 +329,46 @@ static void sci_init_pins_sci(struct uart_port* port, unsigned int cflag) /* tx mark output*/ H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx; } -#else -static void sci_init_pins_sci(struct uart_port *port, unsigned int cflag) -{ -} #endif #endif #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) -#if defined(CONFIG_CPU_SH3) -/* For SH7705, SH7707, SH7709, SH7709A, SH7729, SH7300*/ +#if defined(CONFIG_CPU_SUBTYPE_SH7300) +/* SH7300 doesn't use RTS/CTS */ +static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) +{ + sci_out(port, SCFCR, 0); +} +#elif defined(CONFIG_CPU_SH3) +/* For SH7705, SH7707, SH7709, SH7709A, SH7729 */ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) { unsigned int fcr_val = 0; -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) /* SH7300 doesn't use RTS/CTS */ - { - unsigned short data; + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ + ctrl_outw(data & 0x0fcf, SCPCR); - /* We need to set SCPCR to enable RTS/CTS */ - data = ctrl_inw(SCPCR); - /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ - ctrl_outw(data&0x0fcf, SCPCR); - } if (cflag & CRTSCTS) fcr_val |= SCFCR_MCE; else { - unsigned short data; - /* We need to set SCPCR to enable RTS/CTS */ data = ctrl_inw(SCPCR); /* Clear out SCP7MD1,0, SCP4MD1,0, Set SCP6MD1,0 = {01} (output) */ - ctrl_outw((data&0x0fcf)|0x1000, SCPCR); + ctrl_outw((data & 0x0fcf) | 0x1000, SCPCR); data = ctrl_inb(SCPDR); /* Set /RTS2 (bit6) = 0 */ - ctrl_outb(data&0xbf, SCPDR); + ctrl_outb(data & 0xbf, SCPDR); } -#endif + sci_out(port, SCFCR, fcr_val); } +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag) { unsigned int fcr_val = 0; @@ -374,7 +378,7 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag) sci_out(port, SCFCR, fcr_val); } - +#endif #else /* For SH7750 */ @@ -385,7 +389,11 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } else { +#ifdef CONFIG_CPU_SUBTYPE_SH7780 + ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ +#else ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ +#endif } sci_out(port, SCFCR, fcr_val); } @@ -422,7 +430,11 @@ static void sci_transmit_chars(struct uart_port *port) #if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { +#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) + txroom = SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f); +#else txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8); +#endif } else { txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0; } @@ -491,7 +503,11 @@ static inline void sci_receive_chars(struct uart_port *port, while (1) { #if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { +#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) + count = sci_in(port, SCRFDR) & 0x7f; +#else count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ; +#endif } else { count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0; } @@ -652,7 +668,7 @@ static inline int sci_handle_breaks(struct uart_port *port) struct tty_struct *tty = port->info->tty; struct sci_port *s = &sci_ports[port->line]; - if (!s->break_flag && status & SCxSR_BRK(port)) + if (!s->break_flag && status & SCxSR_BRK(port)) { #if defined(CONFIG_CPU_SH3) /* Debounce break */ s->break_flag = 1; @@ -783,6 +799,7 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void * (phase == CPUFREQ_RESUMECHANGE)){ for (i = 0; i < SCI_NPORTS; i++) { struct uart_port *port = &sci_ports[i].port; + struct clk *clk; /* * Update the uartclk per-port if frequency has @@ -795,7 +812,9 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void * * * Clean this up later.. */ - port->uartclk = current_cpu_data.module_clock * 16; + clk = clk_get("module_clk"); + port->uartclk = clk_get_rate(clk) * 16; + clk_put(clk); } printk("%s: got a postchange notification for cpu %d (old %d, new %d)\n", @@ -1008,15 +1027,20 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios, sci_out(port, SCSMR, smr_val); switch (baud) { - case 0: t = -1; break; - case 2400: t = BPS_2400; break; - case 4800: t = BPS_4800; break; - case 9600: t = BPS_9600; break; - case 19200: t = BPS_19200; break; - case 38400: t = BPS_38400; break; - case 57600: t = BPS_57600; break; - case 115200: t = BPS_115200; break; - default: t = SCBRR_VALUE(baud); break; + case 0: + t = -1; + break; + default: + { +#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) + struct clk *clk = clk_get("module_clk"); + t = SCBRR_VALUE(baud, clk_get_rate(clk)); + clk_put(clk); +#else + t = SCBRR_VALUE(baud); +#endif + } + break; } if (t > 0) { @@ -1030,7 +1054,9 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios, udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ } - s->init_pins(port, termios->c_cflag); + if (likely(s->init_pins)) + s->init_pins(port, termios->c_cflag); + sci_out(port, SCSCR, SCSCR_INIT(port)); if ((termios->c_cflag & CREAD) != 0) @@ -1107,31 +1133,30 @@ static struct uart_ops sci_uart_ops = { .verify_port = sci_verify_port, }; -static struct sci_port sci_ports[SCI_NPORTS] = { +static struct sci_port sci_ports[] = { #if defined(CONFIG_CPU_SUBTYPE_SH7708) { .port = { .membase = (void *)0xfffffe80, .mapbase = 0xfffffe80, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 25, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCI, .irqs = SCI_IRQS, - .init_pins = sci_init_pins_sci, }, #elif defined(CONFIG_CPU_SUBTYPE_SH7705) { .port = { .membase = (void *)SCIF0, .mapbase = SCIF0, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 55, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1142,10 +1167,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)SCIF2, .mapbase = SCIF2, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 59, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCIF, @@ -1157,24 +1182,23 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xfffffe80, .mapbase = 0xfffffe80, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 25, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCI, .irqs = SCI_IRQS, - .init_pins = sci_init_pins_sci, }, { .port = { .membase = (void *)0xa4000150, .mapbase = 0xa4000150, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 59, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCIF, @@ -1185,10 +1209,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xa4000140, .mapbase = 0xa4000140, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 55, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 2, }, .type = PORT_IRDA, @@ -1200,10 +1224,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xA4430000, .mapbase = 0xA4430000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 25, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1215,25 +1239,25 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xffe00000, .mapbase = 0xffe00000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 25, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, .irqs = SH73180_SCIF_IRQS, .init_pins = sci_init_pins_scif, }, -#elif defined(CONFIG_SH_RTS7751R2D) +#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) { .port = { .membase = (void *)0xffe80000, .mapbase = 0xffe80000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 43, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1245,24 +1269,23 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xffe00000, .mapbase = 0xffe00000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 25, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCI, .irqs = SCI_IRQS, - .init_pins = sci_init_pins_sci, }, { .port = { .membase = (void *)0xffe80000, .mapbase = 0xffe80000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 43, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCIF, @@ -1274,10 +1297,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xfe600000, .mapbase = 0xfe600000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 55, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1288,10 +1311,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xfe610000, .mapbase = 0xfe610000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 75, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCIF, @@ -1302,40 +1325,25 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xfe620000, .mapbase = 0xfe620000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 79, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 2, }, .type = PORT_SCIF, .irqs = SH7760_SCIF2_IRQS, .init_pins = sci_init_pins_scif, }, -#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) - { - .port = { - .membase = (void *)0xffe80000, - .mapbase = 0xffe80000, - .iotype = SERIAL_IO_MEM, - .irq = 43, - .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, - .line = 0, - }, - .type = PORT_SCIF, - .irqs = SH4_SCIF_IRQS, - .init_pins = sci_init_pins_scif, - }, #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) { .port = { .membase = (void *)0xffe00000, .mapbase = 0xffe00000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 26, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1346,10 +1354,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0xffe80000, .mapbase = 0xffe80000, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 43, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCIF, @@ -1359,10 +1367,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) { .port = { - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 42, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCIF, @@ -1374,10 +1382,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffffb0, .mapbase = 0x00ffffb0, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 54, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCI, @@ -1388,10 +1396,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffffb8, .mapbase = 0x00ffffb8, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 58, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCI, @@ -1402,10 +1410,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffffc0, .mapbase = 0x00ffffc0, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 62, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 2, }, .type = PORT_SCI, @@ -1417,10 +1425,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffff78, .mapbase = 0x00ffff78, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 90, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, }, .type = PORT_SCI, @@ -1431,10 +1439,10 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffff80, .mapbase = 0x00ffff80, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 94, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 1, }, .type = PORT_SCI, @@ -1445,16 +1453,88 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .port = { .membase = (void *)0x00ffff88, .mapbase = 0x00ffff88, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .irq = 98, .ops = &sci_uart_ops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 2, }, .type = PORT_SCI, .irqs = H8S_SCI_IRQS2, .init_pins = sci_init_pins_sci, }, +#elif defined(CONFIG_CPU_SUBTYPE_SH7770) + { + .port = { + .membase = (void *)0xff923000, + .mapbase = 0xff923000, + .iotype = UPIO_MEM, + .irq = 61, + .ops = &sci_uart_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + .type = PORT_SCIF, + .irqs = SH7770_SCIF0_IRQS, + .init_pins = sci_init_pins_scif, + }, + { + .port = { + .membase = (void *)0xff924000, + .mapbase = 0xff924000, + .iotype = UPIO_MEM, + .irq = 62, + .ops = &sci_uart_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + .type = PORT_SCIF, + .irqs = SH7770_SCIF1_IRQS, + .init_pins = sci_init_pins_scif, + }, + { + .port = { + .membase = (void *)0xff925000, + .mapbase = 0xff925000, + .iotype = UPIO_MEM, + .irq = 63, + .ops = &sci_uart_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 2, + }, + .type = PORT_SCIF, + .irqs = SH7770_SCIF2_IRQS, + .init_pins = sci_init_pins_scif, + }, +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) + { + .port = { + .membase = (void *)0xffe00000, + .mapbase = 0xffe00000, + .iotype = UPIO_MEM, + .irq = 43, + .ops = &sci_uart_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + }, + .type = PORT_SCIF, + .irqs = SH7780_SCIF0_IRQS, + .init_pins = sci_init_pins_scif, + }, + { + .port = { + .membase = (void *)0xffe10000, + .mapbase = 0xffe10000, + .iotype = UPIO_MEM, + .irq = 79, + .ops = &sci_uart_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + }, + .type = PORT_SCIF, + .irqs = SH7780_SCIF1_IRQS, + .init_pins = sci_init_pins_scif, + }, #else #error "CPU subtype not defined" #endif @@ -1480,9 +1560,6 @@ static int __init serial_console_setup(struct console *co, char *options) int flow = 'n'; int ret; - if (co->index >= SCI_NPORTS) - co->index = 0; - serial_console_port = &sci_ports[co->index]; port = &serial_console_port->port; port->type = serial_console_port->type; @@ -1496,14 +1573,21 @@ static int __init serial_console_setup(struct console *co, char *options) * We need to set the initial uartclk here, since otherwise it will * only ever be setup at sci_init() time. */ -#if !defined(__H8300H__) && !defined(__H8300S__) - port->uartclk = current_cpu_data.module_clock * 16; -#else +#if defined(__H8300H__) || defined(__H8300S__) port->uartclk = CONFIG_CPU_CLOCK; -#endif + #if defined(__H8300S__) h8300_sci_enable(port, sci_enable); #endif +#elif defined(CONFIG_SUPERH64) + port->uartclk = current_cpu_info.module_clock * 16; +#else + { + struct clk *clk = clk_get("module_clk"); + port->uartclk = clk_get_rate(clk) * 16; + clk_put(clk); + } +#endif if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1566,7 +1650,7 @@ int __init kgdb_console_setup(struct console *co, char *options) int parity = 'n'; int flow = 'n'; - if (co->index >= SCI_NPORTS || co->index != kgdb_portnum) + if (co->index != kgdb_portnum) co->index = kgdb_portnum; if (options) @@ -1606,7 +1690,7 @@ console_initcall(kgdb_console_init); #elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE) #define SCI_CONSOLE &serial_console #else -#define SCI_CONSOLE 0 +#define SCI_CONSOLE 0 #endif static char banner[] __initdata = @@ -1621,7 +1705,6 @@ static struct uart_driver sci_uart_driver = { .dev_name = "ttySC", .major = SCI_MAJOR, .minor = SCI_MINOR_START, - .nr = SCI_NPORTS, .cons = SCI_CONSOLE, }; @@ -1631,15 +1714,21 @@ static int __init sci_init(void) printk("%s", banner); + sci_uart_driver.nr = ARRAY_SIZE(sci_ports); + ret = uart_register_driver(&sci_uart_driver); if (ret == 0) { for (chan = 0; chan < SCI_NPORTS; chan++) { struct sci_port *sciport = &sci_ports[chan]; -#if !defined(__H8300H__) && !defined(__H8300S__) - sciport->port.uartclk = (current_cpu_data.module_clock * 16); -#else +#if defined(__H8300H__) || defined(__H8300S__) sciport->port.uartclk = CONFIG_CPU_CLOCK; +#elif defined(CONFIG_SUPERH64) + sciport->port.uartclk = current_cpu_info.module_clock * 16; +#else + struct clk *clk = clk_get("module_clk"); + sciport->port.uartclk = clk_get_rate(clk) * 16; + clk_put(clk); #endif uart_add_one_port(&sci_uart_driver, &sciport->port); sciport->break_timer.data = (unsigned long)sciport; diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 2892169eff05..1f14bb4382f6 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -46,14 +46,17 @@ #define H8S_SCI_IRQS1 {92, 93, 94, 0 } #define H8S_SCI_IRQS2 {96, 97, 98, 0 } #define SH5_SCIF_IRQS {39, 40, 42, 0 } +#define SH7770_SCIF0_IRQS {61, 61, 61, 61 } +#define SH7770_SCIF1_IRQS {62, 62, 62, 62 } +#define SH7770_SCIF2_IRQS {63, 63, 63, 63 } +#define SH7780_SCIF0_IRQS {40, 41, 43, 42 } +#define SH7780_SCIF1_IRQS {76, 77, 79, 78 } #if defined(CONFIG_CPU_SUBTYPE_SH7708) -# define SCI_NPORTS 1 # define SCSPTR 0xffffff7c /* 8 bit */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) -# define SCI_NPORTS 3 # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ @@ -61,9 +64,8 @@ #elif defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCIF0 0xA4400000 # define SCIF2 0xA4410000 -# define SCSMR_Ir 0xA44A0000 -# define IRDA_SCIF SCIF0 -# define SCI_NPORTS 2 +# define SCSMR_Ir 0xA44A0000 +# define IRDA_SCIF SCIF0 # define SCPCR 0xA4000116 # define SCPDR 0xA4000136 @@ -74,14 +76,11 @@ # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 # define SCIF_ONLY #elif defined(CONFIG_SH_RTS7751R2D) -# define SCI_NPORTS 1 -# define SCSPTR1 0xffe0001c /* 8 bit SCI */ # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) -# define SCI_NPORTS 2 # define SCSPTR1 0xffe0001c /* 8 bit SCI */ # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ @@ -90,34 +89,29 @@ 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) # define SCI_AND_SCIF #elif defined(CONFIG_CPU_SUBTYPE_SH7760) -# define SCI_NPORTS 3 -# define SCSPTR0 0xfe600000 /* 16 bit SCIF */ -# define SCSPTR1 0xfe610000 /* 16 bit SCIF */ -# define SCSPTR2 0xfe620000 /* 16 bit SCIF */ +# define SCSPTR0 0xfe600024 /* 16 bit SCIF */ +# define SCSPTR1 0xfe610024 /* 16 bit SCIF */ +# define SCSPTR2 0xfe620024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7300) -# define SCI_NPORTS 1 # define SCPCR 0xA4050116 /* 16 bit SCIF */ # define SCPDR 0xA4050136 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH73180) -# define SCI_NPORTS 1 # define SCPDR 0xA4050138 /* 16 bit SCIF */ # define SCSPTR2 SCPDR # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) -# define SCI_NPORTS 1 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -# define SCI_NPORTS 2 # define SCSPTR1 0xffe00020 /* 16 bit SCIF */ # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ @@ -129,26 +123,32 @@ # define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR # define SCIF_PTR2_OFFS 0x0000020 # define SCIF_LSR2_OFFS 0x0000024 -# define SCI_NPORTS 1 -# define SCI_INIT { \ - { {}, PORT_SCIF, 0, \ - SH5_SCIF_IRQS, sci_init_pins_scif } \ -} # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ # define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) -# define SCI_NPORTS 3 # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_ONLY # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #elif defined(CONFIG_H8S2678) -# define SCI_NPORTS 3 # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_ONLY # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) +#elif defined(CONFIG_CPU_SUBTYPE_SH7770) +# define SCSPTR0 0xff923020 /* 16 bit SCIF */ +# define SCSPTR1 0xff924020 /* 16 bit SCIF */ +# define SCSPTR2 0xff925020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +# define SCSPTR0 0xffe00024 /* 16 bit SCIF */ +# define SCSPTR1 0xffe10024 /* 16 bit SCIF */ +# define SCIF_OPER 0x0001 /* Overrun error bit */ +# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -158,7 +158,7 @@ #define SCI_CTRL_FLAGS_RIE 0x40 /* all */ #define SCI_CTRL_FLAGS_TE 0x20 /* all */ #define SCI_CTRL_FLAGS_RE 0x10 /* all */ -#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) +#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_SH7780) #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ #else #define SCI_CTRL_FLAGS_REIE 0 @@ -213,7 +213,7 @@ # define SCxSR_RDxF_CLEAR(port) 0xbc # define SCxSR_ERROR_CLEAR(port) 0xc4 # define SCxSR_TDxE_CLEAR(port) 0x78 -# define SCxSR_BREAK_CLEAR(port) 0xc4 +# define SCxSR_BREAK_CLEAR(port) 0xc4 #elif defined(SCIF_ONLY) # define SCxSR_TEND(port) SCIF_TEND # define SCxSR_ERRORS(port) SCIF_ERRORS @@ -237,7 +237,7 @@ # define SCxSR_RDxF_CLEAR(port) 0x00fc # define SCxSR_ERROR_CLEAR(port) 0x0073 # define SCxSR_TDxE_CLEAR(port) 0x00df -# define SCxSR_BREAK_CLEAR(port) 0x00e3 +# define SCxSR_BREAK_CLEAR(port) 0x00e3 #endif #else # define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) @@ -285,14 +285,14 @@ struct sci_port { #define SCI_IN(size, offset) \ unsigned int addr = port->mapbase + (offset); \ - if ((size) == 8) { \ + if ((size) == 8) { \ return ctrl_inb(addr); \ - } else { \ + } else { \ return ctrl_inw(addr); \ } #define SCI_OUT(size, offset, value) \ unsigned int addr = port->mapbase + (offset); \ - if ((size) == 8) { \ + if ((size) == 8) { \ ctrl_outb(value, addr); \ } else { \ ctrl_outw(value, addr); \ @@ -301,10 +301,10 @@ struct sci_port { #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - if (port->type == PORT_SCI) { \ + if (port->type == PORT_SCI) { \ SCI_IN(sci_size, sci_offset) \ } else { \ - SCI_IN(scif_size, scif_offset); \ + SCI_IN(scif_size, scif_offset); \ } \ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ @@ -319,7 +319,7 @@ struct sci_port { #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - SCI_IN(scif_size, scif_offset); \ + SCI_IN(scif_size, scif_offset); \ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ { \ @@ -329,7 +329,7 @@ struct sci_port { #define CPU_SCI_FNS(name, sci_offset, sci_size) \ static inline unsigned int sci_##name##_in(struct uart_port* port) \ { \ - SCI_IN(sci_size, sci_offset); \ + SCI_IN(sci_size, sci_offset); \ } \ static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \ { \ @@ -385,10 +385,17 @@ SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8) SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) +#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) +SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) +SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) +SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) +SCIF_FNS(SCLSR, 0, 0, 0x28, 16) +#else SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCSPTR, 0, 0, 0x20, 16) SCIF_FNS(SCLSR, 0, 0, 0x24, 16) #endif +#endif #define sci_in(port, reg) sci_##reg##_in(port) #define sci_out(port, reg, value) sci_##reg##_out(port, value) @@ -518,6 +525,24 @@ static inline int sci_rxd_in(struct uart_port *port) int ch = (port->mapbase - SMR0) >> 3; return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0; } +#elif defined(CONFIG_CPU_SUBTYPE_SH7770) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xff923000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xff924000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xff925000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xffe00000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xffe10000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ +} #endif /* @@ -552,22 +577,15 @@ static inline int sci_rxd_in(struct uart_port *port) * -- Mitch Davis - 15 Jul 2000 */ -#define PCLK (current_cpu_data.module_clock) - -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(16*bps)-1) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7780) +#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) -#define SCBRR_VALUE(bps) (((PCLK*2)+16*bps)/(32*bps)-1) -#elif !defined(__H8300H__) && !defined(__H8300S__) -#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1) -#else +#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) +#elif defined(__H8300H__) || defined(__H8300S__) #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1) +#elif defined(CONFIG_SUPERH64) +#define SCBRR_VALUE(bps) ((current_cpu_data.module_clock+16*bps)/(32*bps)-1) +#else /* Generic SH */ +#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) #endif -#define BPS_2400 SCBRR_VALUE(2400) -#define BPS_4800 SCBRR_VALUE(4800) -#define BPS_9600 SCBRR_VALUE(9600) -#define BPS_19200 SCBRR_VALUE(19200) -#define BPS_38400 SCBRR_VALUE(38400) -#define BPS_57600 SCBRR_VALUE(57600) -#define BPS_115200 SCBRR_VALUE(115200) diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 5468e5a767e2..43e67d6c29d4 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -6,7 +6,7 @@ * driver for that. * * - * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -829,8 +829,8 @@ static int __init sn_sal_module_init(void) misc.name = DEVICE_NAME_DYNAMIC; retval = misc_register(&misc); if (retval != 0) { - printk - ("Failed to register console device using misc_register.\n"); + printk(KERN_WARNING "Failed to register console " + "device using misc_register.\n"); return -ENODEV; } sal_console_uart.major = MISC_MAJOR; @@ -942,88 +942,75 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) { unsigned long flags = 0; struct sn_cons_port *port = &sal_console_port; -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) static int stole_lock = 0; -#endif BUG_ON(!port->sc_is_asynch); /* We can't look at the xmit buffer if we're not registered with serial core * yet. So only do the fancy recovery after registering */ - if (port->sc_port.info) { - - /* somebody really wants this output, might be an - * oops, kdb, panic, etc. make sure they get it. */ -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) - if (spin_is_locked(&port->sc_port.lock)) { - int lhead = port->sc_port.info->xmit.head; - int ltail = port->sc_port.info->xmit.tail; - int counter, got_lock = 0; + if (!port->sc_port.info) { + /* Not yet registered with serial core - simple case */ + puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); + return; + } - /* - * We attempt to determine if someone has died with the - * lock. We wait ~20 secs after the head and tail ptrs - * stop moving and assume the lock holder is not functional - * and plow ahead. If the lock is freed within the time out - * period we re-get the lock and go ahead normally. We also - * remember if we have plowed ahead so that we don't have - * to wait out the time out period again - the asumption - * is that we will time out again. - */ + /* somebody really wants this output, might be an + * oops, kdb, panic, etc. make sure they get it. */ + if (spin_is_locked(&port->sc_port.lock)) { + int lhead = port->sc_port.info->xmit.head; + int ltail = port->sc_port.info->xmit.tail; + int counter, got_lock = 0; + + /* + * We attempt to determine if someone has died with the + * lock. We wait ~20 secs after the head and tail ptrs + * stop moving and assume the lock holder is not functional + * and plow ahead. If the lock is freed within the time out + * period we re-get the lock and go ahead normally. We also + * remember if we have plowed ahead so that we don't have + * to wait out the time out period again - the asumption + * is that we will time out again. + */ - for (counter = 0; counter < 150; mdelay(125), counter++) { - if (!spin_is_locked(&port->sc_port.lock) - || stole_lock) { - if (!stole_lock) { - spin_lock_irqsave(&port-> - sc_port.lock, - flags); - got_lock = 1; - } - break; - } else { - /* still locked */ - if ((lhead != - port->sc_port.info->xmit.head) - || (ltail != - port->sc_port.info->xmit. - tail)) { - lhead = - port->sc_port.info->xmit. - head; - ltail = - port->sc_port.info->xmit. - tail; - counter = 0; - } + for (counter = 0; counter < 150; mdelay(125), counter++) { + if (!spin_is_locked(&port->sc_port.lock) + || stole_lock) { + if (!stole_lock) { + spin_lock_irqsave(&port->sc_port.lock, + flags); + got_lock = 1; } - } - /* flush anything in the serial core xmit buffer, raw */ - sn_transmit_chars(port, 1); - if (got_lock) { - spin_unlock_irqrestore(&port->sc_port.lock, - flags); - stole_lock = 0; + break; } else { - /* fell thru */ - stole_lock = 1; + /* still locked */ + if ((lhead != port->sc_port.info->xmit.head) + || (ltail != + port->sc_port.info->xmit.tail)) { + lhead = + port->sc_port.info->xmit.head; + ltail = + port->sc_port.info->xmit.tail; + counter = 0; + } } - puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); - } else { - stole_lock = 0; -#endif - spin_lock_irqsave(&port->sc_port.lock, flags); - sn_transmit_chars(port, 1); + } + /* flush anything in the serial core xmit buffer, raw */ + sn_transmit_chars(port, 1); + if (got_lock) { spin_unlock_irqrestore(&port->sc_port.lock, flags); - - puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) + stole_lock = 0; + } else { + /* fell thru */ + stole_lock = 1; } -#endif - } - else { - /* Not yet registered with serial core - simple case */ + puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); + } else { + stole_lock = 0; + spin_lock_irqsave(&port->sc_port.lock, flags); + sn_transmit_chars(port, 1); + spin_unlock_irqrestore(&port->sc_port.lock, flags); + puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); } } diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c index 5fc4a62173d9..fa4ae94243c2 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c @@ -34,6 +34,7 @@ sunserial_console_termios(struct console *con) char *mode_prop = "ttyX-mode"; char *cd_prop = "ttyX-ignore-cd"; char *dtr_prop = "ttyX-rts-dtr-off"; + char *ssp_console_modes_prop = "ssp-console-modes"; int baud, bits, stop, cflag; char parity; int carrier = 0; @@ -43,14 +44,39 @@ sunserial_console_termios(struct console *con) if (!serial_console) return; - if (serial_console == 1) { + switch (serial_console) { + case PROMDEV_OTTYA: mode_prop[3] = 'a'; cd_prop[3] = 'a'; dtr_prop[3] = 'a'; - } else { + break; + + case PROMDEV_OTTYB: mode_prop[3] = 'b'; cd_prop[3] = 'b'; dtr_prop[3] = 'b'; + break; + + case PROMDEV_ORSC: + + nd = prom_pathtoinode("rsc"); + if (!nd) { + strcpy(mode, "115200,8,n,1,-"); + goto no_options; + } + + if (!prom_node_has_property(nd, ssp_console_modes_prop)) { + strcpy(mode, "115200,8,n,1,-"); + goto no_options; + } + + memset(mode, 0, sizeof(mode)); + prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode)); + goto no_options; + + default: + strcpy(mode, "9600,8,n,1,-"); + goto no_options; } topnd = prom_getchild(prom_root_node); @@ -110,6 +136,10 @@ no_options: case 9600: cflag |= B9600; break; case 19200: cflag |= B19200; break; case 38400: cflag |= B38400; break; + case 57600: cflag |= B57600; break; + case 115200: cflag |= B115200; break; + case 230400: cflag |= B230400; break; + case 460800: cflag |= B460800; break; default: baud = 9600; cflag |= B9600; break; } diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 7e773ff76c61..85664228a0b6 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -897,9 +897,6 @@ static int sunsab_console_setup(struct console *con, char *options) sunserial_console_termios(con); - /* Firmware console speed is limited to 150-->38400 baud so - * this hackish cflag thing is OK. - */ switch (con->cflag & CBAUD) { case B150: baud = 150; break; case B300: baud = 300; break; @@ -910,6 +907,10 @@ static int sunsab_console_setup(struct console *con, char *options) default: case B9600: baud = 9600; break; case B19200: baud = 19200; break; case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B230400: baud = 230400; break; + case B460800: baud = 460800; break; }; /* @@ -1035,7 +1036,7 @@ static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg up->port.irq = edev->irqs[0]; up->port.fifosize = SAB82532_XMIT_FIFO_SIZE; up->port.mapbase = (unsigned long)up->regs; - up->port.iotype = SERIAL_IO_MEM; + up->port.iotype = UPIO_MEM; writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 9a3665b34d97..308704566948 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -109,11 +109,11 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) offset <<= up->port.regshift; switch (up->port.iotype) { - case SERIAL_IO_HUB6: + case UPIO_HUB6: outb(up->port.hub6 - 1 + offset, up->port.iobase); return inb(up->port.iobase + 1); - case SERIAL_IO_MEM: + case UPIO_MEM: return readb(up->port.membase + offset); default: @@ -139,12 +139,12 @@ serial_out(struct uart_sunsu_port *up, int offset, int value) offset <<= up->port.regshift; switch (up->port.iotype) { - case SERIAL_IO_HUB6: + case UPIO_HUB6: outb(up->port.hub6 - 1 + offset, up->port.iobase); outb(value, up->port.iobase + 1); break; - case SERIAL_IO_MEM: + case UPIO_MEM: writeb(value, up->port.membase + offset); break; @@ -669,7 +669,7 @@ static int sunsu_startup(struct uart_port *port) * if it is, then bail out, because there's likely no UART * here. */ - if (!(up->port.flags & ASYNC_BUGGY_UART) && + if (!(up->port.flags & UPF_BUGGY_UART) && (serial_inp(up, UART_LSR) == 0xff)) { printk("ttyS%d: LSR safety check engaged!\n", up->port.line); return -ENODEV; @@ -707,7 +707,7 @@ static int sunsu_startup(struct uart_port *port) up->ier = UART_IER_RLSI | UART_IER_RDI; serial_outp(up, UART_IER, up->ier); - if (up->port.flags & ASYNC_FOURPORT) { + if (up->port.flags & UPF_FOURPORT) { unsigned int icp; /* * Enable interrupts on the AST Fourport board @@ -740,7 +740,7 @@ static void sunsu_shutdown(struct uart_port *port) serial_outp(up, UART_IER, 0); spin_lock_irqsave(&up->port.lock, flags); - if (up->port.flags & ASYNC_FOURPORT) { + if (up->port.flags & UPF_FOURPORT) { /* reset interrupts on the AST Fourport board */ inb((up->port.iobase & 0xfe0) | 0x1f); up->port.mctrl |= TIOCM_OUT1; @@ -1052,7 +1052,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) return; up->type_probed = PORT_UNKNOWN; - up->port.iotype = SERIAL_IO_MEM; + up->port.iotype = UPIO_MEM; /* * First we look for Ebus-bases su's @@ -1132,7 +1132,7 @@ ebus_done: spin_lock_irqsave(&up->port.lock, flags); - if (!(up->port.flags & ASYNC_BUGGY_UART)) { + if (!(up->port.flags & UPF_BUGGY_UART)) { /* * Do a simple existence test first; if we fail this, there's * no point trying anything else. @@ -1170,7 +1170,7 @@ ebus_done: * manufacturer would be stupid enough to design a board * that conflicts with COM 1-4 --- we hope! */ - if (!(up->port.flags & ASYNC_SKIP_TEST)) { + if (!(up->port.flags & UPF_SKIP_TEST)) { serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); status1 = serial_inp(up, UART_MSR) & 0xF0; serial_outp(up, UART_MCR, save_mcr); @@ -1371,7 +1371,7 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) } while ((status & BOTH_EMPTY) != BOTH_EMPTY); /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & ASYNC_CONS_FLOW) { + if (up->port.flags & UPF_CONS_FLOW) { tmout = 1000000; while (--tmout && ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) @@ -1513,7 +1513,7 @@ static int __init sunsu_serial_init(void) up->su_type == SU_PORT_KBD) continue; - up->port.flags |= ASYNC_BOOT_AUTOCONF; + up->port.flags |= UPF_BOOT_AUTOCONF; up->port.type = PORT_UNKNOWN; up->port.uartclk = (SU_BASE_BAUD * 16); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 3c72484adea7..5cc4d4c2935c 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1487,7 +1487,7 @@ static void __init sunzilog_prepare(void) up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB; /* Channel A */ - up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM; + up[(chip * 2) + 0].port.iotype = UPIO_MEM; up[(chip * 2) + 0].port.irq = zilog_irq; up[(chip * 2) + 0].port.uartclk = ZS_CLOCK; up[(chip * 2) + 0].port.fifosize = 1; @@ -1498,7 +1498,7 @@ static void __init sunzilog_prepare(void) up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; /* Channel B */ - up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM; + up[(chip * 2) + 1].port.iotype = UPIO_MEM; up[(chip * 2) + 1].port.irq = zilog_irq; up[(chip * 2) + 1].port.uartclk = ZS_CLOCK; up[(chip * 2) + 1].port.fifosize = 1; diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index 9378895a8d56..df705fda4243 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -496,7 +496,7 @@ static int __init v850e_uart_init (void) port->ops = &v850e_uart_ops; port->line = chan; - port->iotype = SERIAL_IO_MEM; + port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; /* We actually use multiple IRQs, but the serial diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index aaa009f4a7bf..12357e1fa558 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c @@ -38,10 +38,10 @@ static inline unsigned mcr_pack(unsigned pulse, unsigned sample) static int nic_wait(struct ioc3_driver_data *idd) { - volatile unsigned mcr; + unsigned mcr; do { - mcr = (volatile unsigned)idd->vma->mcr; + mcr = readl(&idd->vma->mcr); } while (!(mcr & 2)); return mcr & 1; @@ -53,7 +53,7 @@ static int nic_reset(struct ioc3_driver_data *idd) unsigned long flags; local_irq_save(flags); - idd->vma->mcr = mcr_pack(500, 65); + writel(mcr_pack(500, 65), &idd->vma->mcr); presence = nic_wait(idd); local_irq_restore(flags); @@ -68,7 +68,7 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd) unsigned long flags; local_irq_save(flags); - idd->vma->mcr = mcr_pack(6, 13); + writel(mcr_pack(6, 13), &idd->vma->mcr); result = nic_wait(idd); local_irq_restore(flags); @@ -80,9 +80,9 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd) static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) { if (bit) - idd->vma->mcr = mcr_pack(6, 110); + writel(mcr_pack(6, 110), &idd->vma->mcr); else - idd->vma->mcr = mcr_pack(80, 30); + writel(mcr_pack(80, 30), &idd->vma->mcr); nic_wait(idd); } @@ -337,7 +337,7 @@ static void probe_nic(struct ioc3_driver_data *idd) int save = 0, loops = 3; unsigned long first, addr; - idd->vma->gpcr_s = GPCR_MLAN_EN; + writel(GPCR_MLAN_EN, &idd->vma->gpcr_s); while(loops>0) { idd->nic_part[0] = 0; @@ -408,7 +408,7 @@ static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs) read_lock_irqsave(&ioc3_submodules_lock, flags); - if(idd->dual_irq && idd->vma->eisr) { + if(idd->dual_irq && readb(&idd->vma->eisr)) { /* send Ethernet IRQ to the driver */ if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && ioc3_ethernet->intr) { @@ -682,7 +682,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) idd->id = ioc3_counter++; up_write(&ioc3_devices_rwsem); - idd->gpdr_shadow = idd->vma->gpdr; + idd->gpdr_shadow = readl(&idd->vma->gpdr); /* Read IOC3 NIC contents */ probe_nic(idd); @@ -843,9 +843,9 @@ MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>"); MODULE_DESCRIPTION("PCI driver for SGI IOC3"); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(ioc3_register_submodule); -EXPORT_SYMBOL(ioc3_unregister_submodule); -EXPORT_SYMBOL(ioc3_ack); -EXPORT_SYMBOL(ioc3_gpcr_set); -EXPORT_SYMBOL(ioc3_disable); -EXPORT_SYMBOL(ioc3_enable); +EXPORT_SYMBOL_GPL(ioc3_register_submodule); +EXPORT_SYMBOL_GPL(ioc3_unregister_submodule); +EXPORT_SYMBOL_GPL(ioc3_ack); +EXPORT_SYMBOL_GPL(ioc3_gpcr_set); +EXPORT_SYMBOL_GPL(ioc3_disable); +EXPORT_SYMBOL_GPL(ioc3_enable); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b77dbd63e596..7a75faeb0526 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,16 +75,6 @@ config SPI_BUTTERFLY inexpensive battery powered microcontroller evaluation board. This same cable can be used to flash new firmware. -config SPI_BUTTERFLY - tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" - depends on SPI_MASTER && PARPORT && EXPERIMENTAL - select SPI_BITBANG - help - This uses a custom parallel port cable to connect to an AVR - Butterfly <http://www.atmel.com/products/avr/butterfly>, an - inexpensive battery powered microcontroller evaluation board. - This same cable can be used to flash new firmware. - # # Add new SPI master controllers in alphabetical order above this line # diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index 79a3c59615ab..ff9e5faa4dc9 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c @@ -163,21 +163,20 @@ static void butterfly_chipselect(struct spi_device *spi, int value) struct butterfly *pp = spidev_to_pp(spi); /* set default clock polarity */ - if (value) + if (value != BITBANG_CS_INACTIVE) setsck(spi, spi->mode & SPI_CPOL); /* no chipselect on this USI link config */ if (is_usidev(spi)) return; - /* here, value == "activate or not" */ - - /* most PARPORT_CONTROL_* bits are negated */ + /* here, value == "activate or not"; + * most PARPORT_CONTROL_* bits are negated, so we must + * morph it to value == "bit value to write in control register" + */ if (spi_cs_bit == PARPORT_CONTROL_INIT) value = !value; - /* here, value == "bit value to write in control register" */ - parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); } @@ -202,7 +201,9 @@ butterfly_txrx_word_mode0(struct spi_device *spi, /* override default partitioning with cmdlinepart */ static struct mtd_partition partitions[] = { { - /* JFFS2 wants partitions of 4*N blocks for this device ... */ + /* JFFS2 wants partitions of 4*N blocks for this device, + * so sectors 0 and 1 can't be partitions by themselves. + */ /* sector 0 = 8 pages * 264 bytes/page (1 block) * sector 1 = 248 pages * 264 bytes/page @@ -316,8 +317,9 @@ static void butterfly_attach(struct parport *p) if (status < 0) goto clean2; - /* Bus 1 lets us talk to at45db041b (firmware disables AVR) - * or AVR (firmware resets at45, acts as spi slave) + /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR + * (firmware resets at45, acts as spi slave) or neither (we ignore + * both, AVR uses AT45). Here we expect firmware for the first option. */ pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); @@ -330,7 +332,9 @@ static void butterfly_attach(struct parport *p) pp->dataflash->dev.bus_id); #ifdef HAVE_USI - /* even more custom AVR firmware */ + /* Bus 2 is only for talking to the AVR, and it can work no + * matter who masters bus 1; needs appropriate AVR firmware. + */ pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; strcpy(pp->info[1].modalias, "butterfly"); // pp->info[1].platform_data = ... TBD ... ; @@ -378,13 +382,8 @@ static void butterfly_detach(struct parport *p) pp = butterfly; butterfly = NULL; -#ifdef HAVE_USI - spi_unregister_device(pp->butterfly); - pp->butterfly = NULL; -#endif - spi_unregister_device(pp->dataflash); - pp->dataflash = NULL; - + /* stop() unregisters child devices too */ + pdev = to_platform_device(pp->bitbang.master->cdev.dev); status = spi_bitbang_stop(&pp->bitbang); /* turn off VCC */ @@ -394,8 +393,6 @@ static void butterfly_detach(struct parport *p) parport_release(pp->pd); parport_unregister_device(pp->pd); - pdev = to_platform_device(pp->bitbang.master->cdev.dev); - (void) spi_master_put(pp->bitbang.master); platform_device_unregister(pdev); @@ -420,4 +417,5 @@ static void __exit butterfly_exit(void) } module_exit(butterfly_exit); +MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly"); MODULE_LICENSE("GPL"); diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index a0e5af638e0e..4a51e56f85b6 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -17,7 +17,6 @@ #include <linux/types.h> #include <asm/addrspace.h> -#include <asm/bug.h> #include <asm/errno.h> #include <asm/io.h> #include <asm/paccess.h> diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index f6704688ee8c..5578a9dd04e8 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -3558,10 +3558,16 @@ static void ixj_write_frame(IXJ *j) } /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { - if(j->write_buffer_rp + cnt == 0 && j->write_buffer_rp + cnt + 1 == 0 && j->write_buffer_rp + cnt + 2 == 0 && - j->write_buffer_rp + cnt + 3 == 0 && j->write_buffer_rp + cnt + 4 == 0 && j->write_buffer_rp + cnt + 5 == 0 && - j->write_buffer_rp + cnt + 6 == 0 && j->write_buffer_rp + cnt + 7 == 0 && j->write_buffer_rp + cnt + 8 == 0 && - j->write_buffer_rp + cnt + 9 == 0) { + if (j->write_buffer_rp[cnt] == 0 && + j->write_buffer_rp[cnt + 1] == 0 && + j->write_buffer_rp[cnt + 2] == 0 && + j->write_buffer_rp[cnt + 3] == 0 && + j->write_buffer_rp[cnt + 4] == 0 && + j->write_buffer_rp[cnt + 5] == 0 && + j->write_buffer_rp[cnt + 6] == 0 && + j->write_buffer_rp[cnt + 7] == 0 && + j->write_buffer_rp[cnt + 8] == 0 && + j->write_buffer_rp[cnt + 9] == 0) { /* someone is trying to write silence lets make this a type 0 frame. */ outb_p(0x00, j->DSPbase + 0x0C); outb_p(0x00, j->DSPbase + 0x0D); diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 3639c3f8d357..36e476dd9123 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_USB_XPAD) += input/ obj-$(CONFIG_USB_DABUSB) += media/ obj-$(CONFIG_USB_DSBR) += media/ +obj-$(CONFIG_USB_ET61X251) += media/ obj-$(CONFIG_USB_IBMCAM) += media/ obj-$(CONFIG_USB_KONICAWC) += media/ obj-$(CONFIG_USB_OV511) += media/ diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index af0a41e7870e..04631dcbabbc 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -36,6 +36,7 @@ #include <linux/init.h> #include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */ #include <linux/firmware.h> +#include <linux/mutex.h> #include "usbatm.h" @@ -160,7 +161,7 @@ struct cxacru_data { struct work_struct poll_work; /* contol handles */ - struct semaphore cm_serialize; + struct mutex cm_serialize; u8 *rcv_buf; u8 *snd_buf; struct urb *rcv_urb; @@ -219,7 +220,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, goto fail; } - down(&instance->cm_serialize); + mutex_lock(&instance->cm_serialize); /* submit reading urb before the writing one */ init_completion(&instance->rcv_done); @@ -288,7 +289,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, ret = offd; dbg("cm %#x", cm); fail: - up(&instance->cm_serialize); + mutex_unlock(&instance->cm_serialize); return ret; } @@ -352,7 +353,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, struct atm_dev *atm_dev) { struct cxacru_data *instance = usbatm_instance->driver_data; - struct device *dev = &usbatm_instance->usb_intf->dev; /* struct atm_dev *atm_dev = usbatm_instance->atm_dev; */ @@ -364,14 +364,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0, atm_dev->esi, sizeof(atm_dev->esi)); if (ret < 0) { - dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret); + atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret); return ret; } /* start ADSL */ ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); if (ret < 0) { - dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); + atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); return ret; } @@ -383,13 +383,13 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, static void cxacru_poll_status(struct cxacru_data *instance) { u32 buf[CXINF_MAX] = {}; - struct device *dev = &instance->usbatm->usb_intf->dev; - struct atm_dev *atm_dev = instance->usbatm->atm_dev; + struct usbatm_data *usbatm = instance->usbatm; + struct atm_dev *atm_dev = usbatm->atm_dev; int ret; ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX); if (ret < 0) { - dev_warn(dev, "poll status: error %d\n", ret); + atm_warn(usbatm, "poll status: error %d\n", ret); goto reschedule; } @@ -400,50 +400,50 @@ static void cxacru_poll_status(struct cxacru_data *instance) switch (instance->line_status) { case 0: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: down\n"); + atm_info(usbatm, "ADSL line: down\n"); break; case 1: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: attemtping to activate\n"); + atm_info(usbatm, "ADSL line: attempting to activate\n"); break; case 2: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: training\n"); + atm_info(usbatm, "ADSL line: training\n"); break; case 3: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: channel analysis\n"); + atm_info(usbatm, "ADSL line: channel analysis\n"); break; case 4: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: exchange\n"); + atm_info(usbatm, "ADSL line: exchange\n"); break; case 5: atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424; atm_dev->signal = ATM_PHY_SIG_FOUND; - dev_info(dev, "ADSL line: up (%d kb/s down | %d kb/s up)\n", + atm_info(usbatm, "ADSL line: up (%d kb/s down | %d kb/s up)\n", buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]); break; case 6: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: waiting\n"); + atm_info(usbatm, "ADSL line: waiting\n"); break; case 7: atm_dev->signal = ATM_PHY_SIG_LOST; - dev_info(dev, "ADSL line: initializing\n"); + atm_info(usbatm, "ADSL line: initializing\n"); break; default: atm_dev->signal = ATM_PHY_SIG_UNKNOWN; - dev_info(dev, "Unknown line state %02x\n", instance->line_status); + atm_info(usbatm, "Unknown line state %02x\n", instance->line_status); break; } reschedule: @@ -504,8 +504,8 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, { int ret; int off; - struct usb_device *usb_dev = instance->usbatm->usb_dev; - struct device *dev = &instance->usbatm->usb_intf->dev; + struct usbatm_data *usbatm = instance->usbatm; + struct usb_device *usb_dev = usbatm->usb_dev; u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct }; u32 val; @@ -515,7 +515,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, val = cpu_to_le32(instance->modem_type->pll_f_clk); ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); if (ret) { - dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret); + usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret); return; } @@ -523,7 +523,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, val = cpu_to_le32(instance->modem_type->pll_b_clk); ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); if (ret) { - dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret); + usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret); return; } @@ -531,14 +531,14 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, val = cpu_to_le32(SDRAM_ENA); ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); if (ret) { - dev_err(dev, "Enable SDRAM failed: %d\n", ret); + usb_err(usbatm, "Enable SDRAM failed: %d\n", ret); return; } /* Firmware */ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); if (ret) { - dev_err(dev, "Firmware upload failed: %d\n", ret); + usb_err(usbatm, "Firmware upload failed: %d\n", ret); return; } @@ -546,7 +546,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, if (instance->modem_type->boot_rom_patch) { ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); if (ret) { - dev_err(dev, "Boot ROM patching failed: %d\n", ret); + usb_err(usbatm, "Boot ROM patching failed: %d\n", ret); return; } } @@ -554,7 +554,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, /* Signature */ ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); if (ret) { - dev_err(dev, "Signature storing failed: %d\n", ret); + usb_err(usbatm, "Signature storing failed: %d\n", ret); return; } @@ -566,7 +566,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); } if (ret) { - dev_err(dev, "Passing control to firmware failed: %d\n", ret); + usb_err(usbatm, "Passing control to firmware failed: %d\n", ret); return; } @@ -580,7 +580,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); if (ret < 0) { - dev_err(dev, "modem failed to initialize: %d\n", ret); + usb_err(usbatm, "modem failed to initialize: %d\n", ret); return; } @@ -597,7 +597,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET, (u8 *) buf, len, NULL, 0); if (ret < 0) { - dev_err(dev, "load config data failed: %d\n", ret); + usb_err(usbatm, "load config data failed: %d\n", ret); return; } } @@ -608,18 +608,19 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, static int cxacru_find_firmware(struct cxacru_data *instance, char* phase, const struct firmware **fw_p) { - struct device *dev = &instance->usbatm->usb_intf->dev; + struct usbatm_data *usbatm = instance->usbatm; + struct device *dev = &usbatm->usb_intf->dev; char buf[16]; sprintf(buf, "cxacru-%s.bin", phase); dbg("cxacru_find_firmware: looking for %s", buf); if (request_firmware(fw_p, buf, dev)) { - dev_dbg(dev, "no stage %s firmware found\n", phase); + usb_dbg(usbatm, "no stage %s firmware found\n", phase); return -ENOENT; } - dev_info(dev, "found firmware %s\n", buf); + usb_info(usbatm, "found firmware %s\n", buf); return 0; } @@ -627,20 +628,19 @@ static int cxacru_find_firmware(struct cxacru_data *instance, static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, struct usb_interface *usb_intf) { - struct device *dev = &usbatm_instance->usb_intf->dev; const struct firmware *fw, *bp, *cf; struct cxacru_data *instance = usbatm_instance->driver_data; int ret = cxacru_find_firmware(instance, "fw", &fw); if (ret) { - dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n"); + usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); return ret; } if (instance->modem_type->boot_rom_patch) { ret = cxacru_find_firmware(instance, "bp", &bp); if (ret) { - dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n"); + usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n"); release_firmware(fw); return ret; } @@ -667,22 +667,19 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, } static int cxacru_bind(struct usbatm_data *usbatm_instance, - struct usb_interface *intf, const struct usb_device_id *id, - int *need_heavy_init) + struct usb_interface *intf, const struct usb_device_id *id) { struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); int ret; /* instance init */ - instance = kmalloc(sizeof(*instance), GFP_KERNEL); + instance = kzalloc(sizeof(*instance), GFP_KERNEL); if (!instance) { dbg("cxacru_bind: no memory for instance data"); return -ENOMEM; } - memset(instance, 0, sizeof(*instance)); - instance->usbatm = usbatm_instance; instance->modem_type = (struct cxacru_modem_type *) id->driver_info; @@ -721,13 +718,13 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); - init_MUTEX(&instance->cm_serialize); + mutex_init(&instance->cm_serialize); INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); usbatm_instance->driver_data = instance; - *need_heavy_init = cxacru_card_status(instance); + usbatm_instance->flags = (cxacru_card_status(instance) ? 0 : UDSL_SKIP_HEAVY_INIT); return 0; @@ -787,12 +784,12 @@ static const struct usb_device_id cxacru_usb_ids[] = { { /* V = Conexant P = ADSL modem (Hasbani project) */ USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00 }, - { /* V = Conexant P = ADSL modem (Well PTI-800 */ - USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00 - }, { /* V = Conexant P = ADSL modem */ USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 }, + { /* V = Conexant P = ADSL modem (Well PTI-800) */ + USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00 + }, { /* V = Conexant P = ADSL modem */ USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00 }, @@ -835,14 +832,13 @@ static const struct usb_device_id cxacru_usb_ids[] = { MODULE_DEVICE_TABLE(usb, cxacru_usb_ids); static struct usbatm_driver cxacru_driver = { - .owner = THIS_MODULE, .driver_name = cxacru_driver_name, .bind = cxacru_bind, .heavy_init = cxacru_heavy_init, .unbind = cxacru_unbind, .atm_start = cxacru_atm_start, - .in = CXACRU_EP_DATA, - .out = CXACRU_EP_DATA, + .bulk_in = CXACRU_EP_DATA, + .bulk_out = CXACRU_EP_DATA, .rx_padding = 3, .tx_padding = 11, }; diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c1b47d74e206..7860c8a5800d 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -35,12 +35,14 @@ #include <linux/slab.h> #include <linux/stat.h> #include <linux/timer.h> +#include <linux/types.h> +#include <linux/usb_ch9.h> #include <linux/workqueue.h> #include "usbatm.h" #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" -#define DRIVER_VERSION "1.9" +#define DRIVER_VERSION "1.10" #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION static const char speedtch_driver_name[] = "speedtch"; @@ -66,31 +68,42 @@ static const char speedtch_driver_name[] = "speedtch"; #define RESUBMIT_DELAY 1000 /* milliseconds */ -#define DEFAULT_ALTSETTING 1 +#define DEFAULT_BULK_ALTSETTING 1 +#define DEFAULT_ISOC_ALTSETTING 2 #define DEFAULT_DL_512_FIRST 0 +#define DEFAULT_ENABLE_ISOC 0 #define DEFAULT_SW_BUFFERING 0 -static int altsetting = DEFAULT_ALTSETTING; +static unsigned int altsetting = 0; /* zero means: use the default */ static int dl_512_first = DEFAULT_DL_512_FIRST; +static int enable_isoc = DEFAULT_ENABLE_ISOC; static int sw_buffering = DEFAULT_SW_BUFFERING; -module_param(altsetting, int, S_IRUGO | S_IWUSR); +module_param(altsetting, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(altsetting, - "Alternative setting for data interface (default: " - __MODULE_STRING(DEFAULT_ALTSETTING) ")"); + "Alternative setting for data interface (bulk_default: " + __MODULE_STRING(DEFAULT_BULK_ALTSETTING) "; isoc_default: " + __MODULE_STRING(DEFAULT_ISOC_ALTSETTING) ")"); module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dl_512_first, "Read 512 bytes before sending firmware (default: " __MODULE_STRING(DEFAULT_DL_512_FIRST) ")"); +module_param(enable_isoc, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_isoc, + "Use isochronous transfers if available (default: " + __MODULE_STRING(DEFAULT_ENABLE_ISOC) ")"); + module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(sw_buffering, "Enable software buffering (default: " __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); +#define INTERFACE_DATA 1 #define ENDPOINT_INT 0x81 -#define ENDPOINT_DATA 0x07 +#define ENDPOINT_BULK_DATA 0x07 +#define ENDPOINT_ISOC_DATA 0x07 #define ENDPOINT_FIRMWARE 0x05 #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) @@ -98,6 +111,8 @@ MODULE_PARM_DESC(sw_buffering, struct speedtch_instance_data { struct usbatm_data *usbatm; + unsigned int altsetting; + struct work_struct status_checker; unsigned char last_status; @@ -205,7 +220,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, buffer, 0x200, &actual_length, 2000); if (ret < 0 && ret != -ETIMEDOUT) - usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); + usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); else usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret); } @@ -219,7 +234,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, buffer, thislen, &actual_length, DATA_TIMEOUT); if (ret < 0) { - usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); + usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); goto out_free; } usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size); @@ -232,7 +247,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, buffer, 0x200, &actual_length, DATA_TIMEOUT); if (ret < 0) { - usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); + usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); goto out_free; } usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length); @@ -246,7 +261,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, buffer, thislen, &actual_length, DATA_TIMEOUT); if (ret < 0) { - usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); + usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); goto out_free; } } @@ -259,7 +274,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, buffer, 0x200, &actual_length, DATA_TIMEOUT); if (ret < 0) { - usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); + usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); goto out_free; } @@ -270,6 +285,11 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, because we're in our own kernel thread anyway. */ msleep_interruptible(1000); + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { + usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret); + goto out_free; + } + /* Enable software buffering, if requested */ if (sw_buffering) speedtch_set_swbuff(instance, 1); @@ -285,8 +305,8 @@ out: return ret; } -static int speedtch_find_firmware(struct usb_interface *intf, int phase, - const struct firmware **fw_p) +static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf, + int phase, const struct firmware **fw_p) { struct device *dev = &intf->dev; const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice); @@ -295,24 +315,24 @@ static int speedtch_find_firmware(struct usb_interface *intf, int phase, char buf[24]; sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); - dev_dbg(dev, "%s: looking for %s\n", __func__, buf); + usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); if (request_firmware(fw_p, buf, dev)) { sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); - dev_dbg(dev, "%s: looking for %s\n", __func__, buf); + usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); if (request_firmware(fw_p, buf, dev)) { sprintf(buf, "speedtch-%d.bin", phase); - dev_dbg(dev, "%s: looking for %s\n", __func__, buf); + usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf); if (request_firmware(fw_p, buf, dev)) { - dev_warn(dev, "no stage %d firmware found!\n", phase); + usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase); return -ENOENT; } } } - dev_info(dev, "found stage %d firmware %s\n", phase, buf); + usb_info(usbatm, "found stage %d firmware %s\n", phase, buf); return 0; } @@ -323,15 +343,16 @@ static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface struct speedtch_instance_data *instance = usbatm->driver_data; int ret; - if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0) - return ret; + if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0) + return ret; - if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) { + if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) { release_firmware(fw1); return ret; } - ret = speedtch_upload_firmware(instance, fw1, fw2); + if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0) + usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret); release_firmware(fw2); release_firmware(fw1); @@ -428,7 +449,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) int down_speed, up_speed, ret; unsigned char status; +#ifdef VERBOSE_DEBUG atm_dbg(usbatm, "%s entered\n", __func__); +#endif ret = speedtch_read_status(instance); if (ret < 0) { @@ -441,9 +464,9 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) status = buf[OFFSET_7]; - atm_dbg(usbatm, "%s: line state %02x\n", __func__, status); - if ((status != instance->last_status) || !status) { + atm_dbg(usbatm, "%s: line state 0x%02x\n", __func__, status); + switch (status) { case 0: atm_dev->signal = ATM_PHY_SIG_LOST; @@ -484,7 +507,7 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) default: atm_dev->signal = ATM_PHY_SIG_UNKNOWN; - atm_info(usbatm, "Unknown line state %02x\n", status); + atm_info(usbatm, "unknown line state %02x\n", status); break; } @@ -583,11 +606,6 @@ static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_de atm_dbg(usbatm, "%s entered\n", __func__); - if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) { - atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret); - return ret; - } - /* Set MAC address, it is stored in the serial number */ memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { @@ -678,20 +696,27 @@ static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_inte static int speedtch_bind(struct usbatm_data *usbatm, struct usb_interface *intf, - const struct usb_device_id *id, - int *need_heavy_init) + const struct usb_device_id *id) { struct usb_device *usb_dev = interface_to_usbdev(intf); - struct usb_interface *cur_intf; + struct usb_interface *cur_intf, *data_intf; struct speedtch_instance_data *instance; int ifnum = intf->altsetting->desc.bInterfaceNumber; int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; int i, ret; + int use_isoc; usb_dbg(usbatm, "%s entered\n", __func__); + /* sanity checks */ + if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { - usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); + usb_err(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); + return -ENODEV; + } + + if (!(data_intf = usb_ifnum_to_if(usb_dev, INTERFACE_DATA))) { + usb_err(usbatm, "%s: data interface not found!\n", __func__); return -ENODEV; } @@ -704,25 +729,71 @@ static int speedtch_bind(struct usbatm_data *usbatm, ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm); if (ret < 0) { - usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret); + usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, i, ret); speedtch_release_interfaces(usb_dev, i); return ret; } } } - instance = kmalloc(sizeof(*instance), GFP_KERNEL); + instance = kzalloc(sizeof(*instance), GFP_KERNEL); if (!instance) { - usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__); + usb_err(usbatm, "%s: no memory for instance data!\n", __func__); ret = -ENOMEM; goto fail_release; } - memset(instance, 0, sizeof(struct speedtch_instance_data)); - instance->usbatm = usbatm; + /* altsetting and enable_isoc may change at any moment, so take a snapshot */ + instance->altsetting = altsetting; + use_isoc = enable_isoc; + + if (instance->altsetting) + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { + usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret); + instance->altsetting = 0; /* fall back to default */ + } + + if (!instance->altsetting && use_isoc) + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) { + usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret); + use_isoc = 0; /* fall back to bulk */ + } + + if (use_isoc) { + const struct usb_host_interface *desc = data_intf->cur_altsetting; + const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in; + int i; + + use_isoc = 0; /* fall back to bulk if endpoint not found */ + + for (i=0; i<desc->desc.bNumEndpoints; i++) { + const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; + + if ((endpoint_desc->bEndpointAddress == target_address)) { + use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC; + break; + } + } + + if (!use_isoc) + usb_info(usbatm, "isochronous transfer not supported - using bulk\n"); + } + + if (!use_isoc && !instance->altsetting) + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) { + usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret); + goto fail_free; + } + + if (!instance->altsetting) + instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING; + + usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); + INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); instance->status_checker.timer.function = speedtch_status_poll; @@ -749,13 +820,15 @@ static int speedtch_bind(struct usbatm_data *usbatm, 0x12, 0xc0, 0x07, 0x00, instance->scratch_buffer + OFFSET_7, SIZE_7, 500); - *need_heavy_init = (ret != SIZE_7); + usbatm->flags |= (ret == SIZE_7 ? UDSL_SKIP_HEAVY_INIT : 0); - usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already"); + usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, usbatm->flags & UDSL_SKIP_HEAVY_INIT ? "already" : "not"); - if (*need_heavy_init) - if ((ret = usb_reset_device(usb_dev)) < 0) + if (!(usbatm->flags & UDSL_SKIP_HEAVY_INIT)) + if ((ret = usb_reset_device(usb_dev)) < 0) { + usb_err(usbatm, "%s: device reset failed (%d)!\n", __func__, ret); goto fail_free; + } usbatm->driver_data = instance; @@ -787,15 +860,15 @@ static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *in ***********/ static struct usbatm_driver speedtch_usbatm_driver = { - .owner = THIS_MODULE, .driver_name = speedtch_driver_name, .bind = speedtch_bind, .heavy_init = speedtch_heavy_init, .unbind = speedtch_unbind, .atm_start = speedtch_atm_start, .atm_stop = speedtch_atm_stop, - .in = ENDPOINT_DATA, - .out = ENDPOINT_DATA + .bulk_in = ENDPOINT_BULK_DATA, + .bulk_out = ENDPOINT_BULK_DATA, + .isoc_in = ENDPOINT_ISOC_DATA }; static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 7d2a679989ed..830d2c982670 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -63,11 +63,12 @@ #include <linux/ctype.h> #include <linux/kthread.h> #include <linux/version.h> +#include <linux/mutex.h> #include <asm/unaligned.h> #include "usbatm.h" -#define EAGLEUSBVERSION "ueagle 1.1" +#define EAGLEUSBVERSION "ueagle 1.2" /* @@ -358,16 +359,19 @@ struct intr_pkt { #define INTR_PKT_SIZE 28 static struct usb_driver uea_driver; -static DECLARE_MUTEX(uea_semaphore); +static DEFINE_MUTEX(uea_mutex); static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"}; static int modem_index; static unsigned int debug; +static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1}; static int sync_wait[NB_MODEM]; static char *cmv_file[NB_MODEM]; module_param(debug, uint, 0644); MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)"); +module_param_array(use_iso, bool, NULL, 0644); +MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic"); module_param_array(sync_wait, bool, NULL, 0644); MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM"); module_param_array(cmv_file, charp, NULL, 0644); @@ -628,8 +632,7 @@ static int request_dsp(struct uea_softc *sc) dsp_name = FW_DIR "DSPep.bin"; } - ret = request_firmware(&sc->dsp_firm, - dsp_name, &sc->usb_dev->dev); + ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev); if (ret < 0) { uea_err(INS_TO_USBDEV(sc), "requesting firmware %s failed with error %d\n", @@ -744,7 +747,6 @@ static inline int wait_cmv_ack(struct uea_softc *sc) return ret; return (ret == 0) ? -ETIMEDOUT : 0; - } #define UCDC_SEND_ENCAPSULATED_COMMAND 0x00 @@ -935,6 +937,7 @@ static int uea_stat(struct uea_softc *sc) * ADI930 don't support it (-EPIPE error). */ if (UEA_CHIP_VERSION(sc) != ADI930 + && !use_iso[sc->modem_index] && sc->stats.phy.dsrate != (data >> 16) * 32) { /* Original timming from ADI(used in windows driver) * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits @@ -1010,7 +1013,7 @@ static int request_cmvs(struct uea_softc *sc, int ret, size; u8 *data; char *file; - static char cmv_name[256] = FW_DIR; + char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ if (cmv_file[sc->modem_index] == NULL) { if (UEA_CHIP_VERSION(sc) == ADI930) @@ -1184,8 +1187,7 @@ static int load_XILINX_firmware(struct uea_softc *sc) } } - /* finish to send the fpga - */ + /* finish to send the fpga */ ret = uea_request(sc, 0xe, 1, 0, NULL); if (ret < 0) { uea_err(INS_TO_USBDEV(sc), @@ -1193,9 +1195,7 @@ static int load_XILINX_firmware(struct uea_softc *sc) goto err1; } - /* - * Tell the modem we finish : de-assert reset - */ + /* Tell the modem we finish : de-assert reset */ value = 0; ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value); if (ret < 0) @@ -1209,6 +1209,7 @@ err0: return ret; } +/* The modem send us an ack. First with check if it right */ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) { uea_enters(INS_TO_USBDEV(sc)); @@ -1268,23 +1269,19 @@ bad1: */ static void uea_intr(struct urb *urb, struct pt_regs *regs) { - struct uea_softc *sc = (struct uea_softc *)urb->context; - struct intr_pkt *intr; + struct uea_softc *sc = urb->context; + struct intr_pkt *intr = urb->transfer_buffer; uea_enters(INS_TO_USBDEV(sc)); - if (urb->status < 0) { + if (unlikely(urb->status < 0)) { uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n", urb->status); return; } - intr = (struct intr_pkt *) urb->transfer_buffer; - /* device-to-host interrupt */ if (intr->bType != 0x08 || sc->booting) { - uea_err(INS_TO_USBDEV(sc), "wrong intr\n"); - // rebooting ? - // sc->reset = 1; + uea_err(INS_TO_USBDEV(sc), "wrong interrupt\n"); goto resubmit; } @@ -1300,7 +1297,7 @@ static void uea_intr(struct urb *urb, struct pt_regs *regs) break; default: - uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n", + uea_err(INS_TO_USBDEV(sc), "unknown interrupt %u\n", le16_to_cpu(intr->wInterrupt)); } @@ -1379,7 +1376,7 @@ static void uea_stop(struct uea_softc *sc) int ret; uea_enters(INS_TO_USBDEV(sc)); ret = kthread_stop(sc->kthread); - uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); + uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); /* stop any pending boot process */ flush_scheduled_work(); @@ -1418,13 +1415,13 @@ static ssize_t read_status(struct device *dev, struct device_attribute *attr, int ret = -ENODEV; struct uea_softc *sc; - down(&uea_semaphore); + mutex_lock(&uea_mutex); sc = dev_to_uea(dev); if (!sc) goto out; ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state); out: - up(&uea_semaphore); + mutex_unlock(&uea_mutex); return ret; } @@ -1434,14 +1431,14 @@ static ssize_t reboot(struct device *dev, struct device_attribute *attr, int ret = -ENODEV; struct uea_softc *sc; - down(&uea_semaphore); + mutex_lock(&uea_mutex); sc = dev_to_uea(dev); if (!sc) goto out; sc->reset = 1; ret = count; out: - up(&uea_semaphore); + mutex_unlock(&uea_mutex); return ret; } @@ -1453,7 +1450,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at int ret = -ENODEV; struct uea_softc *sc; - down(&uea_semaphore); + mutex_lock(&uea_mutex); sc = dev_to_uea(dev); if (!sc) goto out; @@ -1473,7 +1470,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at break; } out: - up(&uea_semaphore); + mutex_unlock(&uea_mutex); return ret; } @@ -1485,7 +1482,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr, int ret = -ENODEV; struct uea_softc *sc; - down(&uea_semaphore); + mutex_lock(&uea_mutex); sc = dev_to_uea(dev); if (!sc) goto out; @@ -1497,7 +1494,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr, else ret = sprintf(buf, "GOOD\n"); out: - up(&uea_semaphore); + mutex_unlock(&uea_mutex); return ret; } @@ -1511,7 +1508,7 @@ static ssize_t read_##name(struct device *dev, \ int ret = -ENODEV; \ struct uea_softc *sc; \ \ - down(&uea_semaphore); \ + mutex_lock(&uea_mutex); \ sc = dev_to_uea(dev); \ if (!sc) \ goto out; \ @@ -1519,7 +1516,7 @@ static ssize_t read_##name(struct device *dev, \ if (reset) \ sc->stats.phy.name = 0; \ out: \ - up(&uea_semaphore); \ + mutex_unlock(&uea_mutex); \ return ret; \ } \ \ @@ -1617,7 +1614,7 @@ static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf) } static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, - const struct usb_device_id *id, int *heavy) + const struct usb_device_id *id) { struct usb_device *usb = interface_to_usbdev(intf); struct uea_softc *sc; @@ -1629,16 +1626,14 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, if (ifnum != UEA_INTR_IFACE_NO) return -ENODEV; - *heavy = sync_wait[modem_index]; + usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT); /* interface 1 is for outbound traffic */ ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO); if (ret < 0) return ret; - /* ADI930 has only 2 interfaces and inbound traffic - * is on interface 1 - */ + /* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */ if (UEA_CHIP_VERSION(id) != ADI930) { /* interface 2 is for inbound traffic */ ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO); @@ -1658,6 +1653,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0; sc->driver_info = id->driver_info; + /* ADI930 don't support iso */ + if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) { + int i; + + /* try set fastest alternate for inbound traffic interface */ + for (i = FASTEST_ISO_INTF; i > 0; i--) + if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0) + break; + + if (i > 0) { + uea_dbg(usb, "set alternate %d for 2 interface\n", i); + uea_info(usb, "using iso mode\n"); + usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ; + } else { + uea_err(usb, "setting any alternate failed for " + "2 interface, using bulk mode\n"); + } + } + ret = uea_boot(sc); if (ret < 0) { kfree(sc); @@ -1701,13 +1715,13 @@ static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) static struct usbatm_driver uea_usbatm_driver = { .driver_name = "ueagle-atm", - .owner = THIS_MODULE, .bind = uea_bind, .atm_start = uea_atm_open, .unbind = uea_unbind, .heavy_init = uea_heavy, - .in = UEA_BULK_DATA_PIPE, - .out = UEA_BULK_DATA_PIPE, + .bulk_in = UEA_BULK_DATA_PIPE, + .bulk_out = UEA_BULK_DATA_PIPE, + .isoc_in = UEA_ISO_DATA_PIPE, }; static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1738,9 +1752,9 @@ static void uea_disconnect(struct usb_interface *intf) * Pre-firmware device has one interface */ if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) { - down(&uea_semaphore); + mutex_lock(&uea_mutex); usbatm_usb_disconnect(intf); - up(&uea_semaphore); + mutex_unlock(&uea_mutex); uea_info(usb, "ADSL device removed\n"); } diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 7af1883d4bf9..c1211fc037d9 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -72,6 +72,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/netdevice.h> #include <linux/proc_fs.h> #include <linux/sched.h> #include <linux/signal.h> @@ -91,19 +92,18 @@ static int usbatm_print_packet(const unsigned char *data, int len); #endif #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" -#define DRIVER_VERSION "1.9" +#define DRIVER_VERSION "1.10" #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION static const char usbatm_driver_name[] = "usbatm"; #define UDSL_MAX_RCV_URBS 16 #define UDSL_MAX_SND_URBS 16 -#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ -#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ +#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */ #define UDSL_DEFAULT_RCV_URBS 4 #define UDSL_DEFAULT_SND_URBS 4 -#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ -#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ +#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ +#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) @@ -111,8 +111,8 @@ static const char usbatm_driver_name[] = "usbatm"; static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; -static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; -static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; +static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE; +static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE; module_param(num_rcv_urbs, uint, S_IRUGO); MODULE_PARM_DESC(num_rcv_urbs, @@ -126,15 +126,15 @@ MODULE_PARM_DESC(num_snd_urbs, __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); -module_param(rcv_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(rcv_buf_size, - "Size of the buffers used for reception in ATM cells (range: 1-" - __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " +module_param(rcv_buf_bytes, uint, S_IRUGO); +MODULE_PARM_DESC(rcv_buf_bytes, + "Size of the buffers used for reception, in bytes (range: 1-" + __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: " __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); -module_param(snd_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(snd_buf_size, - "Size of the buffers used for transmission in ATM cells (range: 1-" +module_param(snd_buf_bytes, uint, S_IRUGO); +MODULE_PARM_DESC(snd_buf_bytes, + "Size of the buffers used for transmission, in bytes (range: 1-" __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); @@ -166,10 +166,10 @@ struct usbatm_control { /* ATM */ -static void usbatm_atm_dev_close(struct atm_dev *dev); +static void usbatm_atm_dev_close(struct atm_dev *atm_dev); static int usbatm_atm_open(struct atm_vcc *vcc); static void usbatm_atm_close(struct atm_vcc *vcc); -static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); +static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg); static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); @@ -199,7 +199,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) if (vcc->pop) vcc->pop(vcc, skb); else - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } @@ -234,8 +234,9 @@ static int usbatm_submit_urb(struct urb *urb) ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { - atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n", - __func__, urb, ret); + if (printk_ratelimit()) + atm_warn(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n", + __func__, urb, ret); /* consider all errors transient and return the buffer back to the queue */ urb->status = -EAGAIN; @@ -269,10 +270,16 @@ static void usbatm_complete(struct urb *urb, struct pt_regs *regs) spin_unlock_irqrestore(&channel->lock, flags); - if (unlikely(urb->status)) + if (unlikely(urb->status) && + (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || + urb->status != -EILSEQ )) + { + if (printk_ratelimit()) + atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n", + __func__, urb, urb->status); /* throttle processing in case of an error */ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); - else + } else tasklet_schedule(&channel->tasklet); } @@ -284,129 +291,167 @@ static void usbatm_complete(struct urb *urb, struct pt_regs *regs) static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance, short vpi, int vci) { - struct usbatm_vcc_data *vcc; + struct usbatm_vcc_data *vcc_data; - list_for_each_entry(vcc, &instance->vcc_list, list) - if ((vcc->vci == vci) && (vcc->vpi == vpi)) - return vcc; + list_for_each_entry(vcc_data, &instance->vcc_list, list) + if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi)) + return vcc_data; return NULL; } -static void usbatm_extract_cells(struct usbatm_data *instance, - unsigned char *source, unsigned int avail_data) +static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char *source) { - struct usbatm_vcc_data *cached_vcc = NULL; struct atm_vcc *vcc; struct sk_buff *sarb; - unsigned int stride = instance->rx_channel.stride; - int vci, cached_vci = 0; - short vpi, cached_vpi = 0; - u8 pti; + short vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); + int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); + u8 pti = ((source[3] & 0xe) >> 1); - for (; avail_data >= stride; avail_data -= stride, source += stride) { - vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); - vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); - pti = ((source[3] & 0xe) >> 1); + vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); - vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); + if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) { + instance->cached_vpi = vpi; + instance->cached_vci = vci; - if ((vci != cached_vci) || (vpi != cached_vpi)) { - cached_vpi = vpi; - cached_vci = vci; + instance->cached_vcc = usbatm_find_vcc(instance, vpi, vci); - cached_vcc = usbatm_find_vcc(instance, vpi, vci); + if (!instance->cached_vcc) + atm_rldbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci); + } - if (!cached_vcc) - atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci); - } + if (!instance->cached_vcc) + return; - if (!cached_vcc) - continue; + vcc = instance->cached_vcc->vcc; - vcc = cached_vcc->vcc; + /* OAM F5 end-to-end */ + if (pti == ATM_PTI_E2EF5) { + if (printk_ratelimit()) + atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", + __func__, vpi, vci); + atomic_inc(&vcc->stats->rx_err); + return; + } - /* OAM F5 end-to-end */ - if (pti == ATM_PTI_E2EF5) { - atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci); - atomic_inc(&vcc->stats->rx_err); - continue; - } + sarb = instance->cached_vcc->sarb; - sarb = cached_vcc->sarb; + if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { + atm_rldbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n", + __func__, sarb->len, vcc); + /* discard cells already received */ + skb_trim(sarb, 0); + UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); + } - if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { - atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n", - __func__, sarb->len, vcc); - /* discard cells already received */ - skb_trim(sarb, 0); - UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); - } + memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); + __skb_put(sarb, ATM_CELL_PAYLOAD); - memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); - __skb_put(sarb, ATM_CELL_PAYLOAD); + if (pti & 1) { + struct sk_buff *skb; + unsigned int length; + unsigned int pdu_length; - if (pti & 1) { - struct sk_buff *skb; - unsigned int length; - unsigned int pdu_length; + length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; - length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; + /* guard against overflow */ + if (length > ATM_MAX_AAL5_PDU) { + atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n", + __func__, length, vcc); + atomic_inc(&vcc->stats->rx_err); + goto out; + } - /* guard against overflow */ - if (length > ATM_MAX_AAL5_PDU) { - atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n", - __func__, length, vcc); - atomic_inc(&vcc->stats->rx_err); - goto out; - } + pdu_length = usbatm_pdu_length(length); - pdu_length = usbatm_pdu_length(length); + if (sarb->len < pdu_length) { + atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n", + __func__, pdu_length, sarb->len, vcc); + atomic_inc(&vcc->stats->rx_err); + goto out; + } - if (sarb->len < pdu_length) { - atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n", - __func__, pdu_length, sarb->len, vcc); - atomic_inc(&vcc->stats->rx_err); - goto out; - } + if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { + atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", + __func__, vcc); + atomic_inc(&vcc->stats->rx_err); + goto out; + } - if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { - atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", - __func__, vcc); - atomic_inc(&vcc->stats->rx_err); - goto out; - } + vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc); - vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc); + if (!(skb = dev_alloc_skb(length))) { + if (printk_ratelimit()) + atm_err(instance, "%s: no memory for skb (length: %u)!\n", + __func__, length); + atomic_inc(&vcc->stats->rx_drop); + goto out; + } - if (!(skb = dev_alloc_skb(length))) { - atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length); - atomic_inc(&vcc->stats->rx_drop); - goto out; - } + vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize); - vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize); + if (!atm_charge(vcc, skb->truesize)) { + atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", + __func__, skb->truesize); + dev_kfree_skb_any(skb); + goto out; /* atm_charge increments rx_drop */ + } - if (!atm_charge(vcc, skb->truesize)) { - atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize); - dev_kfree_skb(skb); - goto out; /* atm_charge increments rx_drop */ - } + memcpy(skb->data, sarb->tail - pdu_length, length); + __skb_put(skb, length); - memcpy(skb->data, sarb->tail - pdu_length, length); - __skb_put(skb, length); + vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", + __func__, skb, skb->len, skb->truesize); - vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", - __func__, skb, skb->len, skb->truesize); + PACKETDEBUG(skb->data, skb->len); - PACKETDEBUG(skb->data, skb->len); + vcc->push(vcc, skb); - vcc->push(vcc, skb); + atomic_inc(&vcc->stats->rx); + out: + skb_trim(sarb, 0); + } +} - atomic_inc(&vcc->stats->rx); - out: - skb_trim(sarb, 0); +static void usbatm_extract_cells(struct usbatm_data *instance, + unsigned char *source, unsigned int avail_data) +{ + unsigned int stride = instance->rx_channel.stride; + unsigned int buf_usage = instance->buf_usage; + + /* extract cells from incoming data, taking into account that + * the length of avail data may not be a multiple of stride */ + + if (buf_usage > 0) { + /* we have a partially received atm cell */ + unsigned char *cell_buf = instance->cell_buf; + unsigned int space_left = stride - buf_usage; + + UDSL_ASSERT(buf_usage <= stride); + + if (avail_data >= space_left) { + /* add new data and process cell */ + memcpy(cell_buf + buf_usage, source, space_left); + source += space_left; + avail_data -= space_left; + usbatm_extract_one_cell(instance, cell_buf); + instance->buf_usage = 0; + } else { + /* not enough data to fill the cell */ + memcpy(cell_buf + buf_usage, source, avail_data); + instance->buf_usage = buf_usage + avail_data; + return; } } + + for (; avail_data >= stride; avail_data -= stride, source += stride) + usbatm_extract_one_cell(instance, source); + + if (avail_data > 0) { + /* length was not a multiple of stride - + * save remaining data for next call */ + memcpy(instance->cell_buf, source, avail_data); + instance->buf_usage = avail_data; + } } @@ -420,14 +465,14 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, { struct usbatm_control *ctrl = UDSL_SKB(skb); struct atm_vcc *vcc = ctrl->atm.vcc; - unsigned int num_written; + unsigned int bytes_written; unsigned int stride = instance->tx_channel.stride; vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); UDSL_ASSERT(!(avail_space % stride)); - for (num_written = 0; num_written < avail_space && ctrl->len; - num_written += stride, target += stride) { + for (bytes_written = 0; bytes_written < avail_space && ctrl->len; + bytes_written += stride, target += stride) { unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); unsigned int left = ATM_CELL_PAYLOAD - data_len; u8 *ptr = target; @@ -470,7 +515,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, ctrl->crc = crc32_be(ctrl->crc, ptr, left); } - return num_written; + return bytes_written; } @@ -487,16 +532,40 @@ static void usbatm_rx_process(unsigned long data) vdbg("%s: processing urb 0x%p", __func__, urb); if (usb_pipeisoc(urb->pipe)) { + unsigned char *merge_start = NULL; + unsigned int merge_length = 0; + const unsigned int packet_size = instance->rx_channel.packet_size; int i; - for (i = 0; i < urb->number_of_packets; i++) - if (!urb->iso_frame_desc[i].status) - usbatm_extract_cells(instance, - (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset, - urb->iso_frame_desc[i].actual_length); - } - else + + for (i = 0; i < urb->number_of_packets; i++) { + if (!urb->iso_frame_desc[i].status) { + unsigned int actual_length = urb->iso_frame_desc[i].actual_length; + + UDSL_ASSERT(actual_length <= packet_size); + + if (!merge_length) + merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; + merge_length += actual_length; + if (merge_length && (actual_length < packet_size)) { + usbatm_extract_cells(instance, merge_start, merge_length); + merge_length = 0; + } + } else { + atm_rldbg(instance, "%s: status %d in frame %d!\n", __func__, urb->status, i); + if (merge_length) + usbatm_extract_cells(instance, merge_start, merge_length); + merge_length = 0; + instance->buf_usage = 0; + } + } + + if (merge_length) + usbatm_extract_cells(instance, merge_start, merge_length); + } else if (!urb->status) usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length); + else + instance->buf_usage = 0; if (usbatm_submit_urb(urb)) return; @@ -514,7 +583,7 @@ static void usbatm_tx_process(unsigned long data) struct sk_buff *skb = instance->current_skb; struct urb *urb = NULL; const unsigned int buf_size = instance->tx_channel.buf_size; - unsigned int num_written = 0; + unsigned int bytes_written = 0; u8 *buffer = NULL; if (!skb) @@ -526,16 +595,16 @@ static void usbatm_tx_process(unsigned long data) if (!urb) break; /* no more senders */ buffer = urb->transfer_buffer; - num_written = (urb->status == -EAGAIN) ? + bytes_written = (urb->status == -EAGAIN) ? urb->transfer_buffer_length : 0; } - num_written += usbatm_write_cells(instance, skb, - buffer + num_written, - buf_size - num_written); + bytes_written += usbatm_write_cells(instance, skb, + buffer + bytes_written, + buf_size - bytes_written); vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", - __func__, num_written, skb, urb); + __func__, bytes_written, skb, urb); if (!UDSL_SKB(skb)->len) { struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; @@ -546,8 +615,8 @@ static void usbatm_tx_process(unsigned long data) skb = skb_dequeue(&instance->sndqueue); } - if (num_written == buf_size || (!skb && num_written)) { - urb->transfer_buffer_length = num_written; + if (bytes_written == buf_size || (!skb && bytes_written)) { + urb->transfer_buffer_length = bytes_written; if (usbatm_submit_urb(urb)) break; @@ -593,20 +662,24 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len); - if (!instance) { - dbg("%s: NULL data!", __func__); + /* racy disconnection check - fine */ + if (!instance || instance->disconnected) { +#ifdef DEBUG + if (printk_ratelimit()) + printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance"); +#endif err = -ENODEV; goto fail; } if (vcc->qos.aal != ATM_AAL5) { - atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); + atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); err = -EINVAL; goto fail; } if (skb->len > ATM_MAX_AAL5_PDU) { - atm_dbg(instance, "%s: packet too long (%d vs %d)!\n", + atm_rldbg(instance, "%s: packet too long (%d vs %d)!\n", __func__, skb->len, ATM_MAX_AAL5_PDU); err = -EINVAL; goto fail; @@ -665,16 +738,16 @@ static void usbatm_put_instance(struct usbatm_data *instance) ** ATM ** **********/ -static void usbatm_atm_dev_close(struct atm_dev *dev) +static void usbatm_atm_dev_close(struct atm_dev *atm_dev) { - struct usbatm_data *instance = dev->dev_data; + struct usbatm_data *instance = atm_dev->dev_data; dbg("%s", __func__); if (!instance) return; - dev->dev_data = NULL; + atm_dev->dev_data = NULL; /* catch bugs */ usbatm_put_instance(instance); /* taken in usbatm_atm_init */ } @@ -706,15 +779,19 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag atomic_read(&atm_dev->stats.aal5.rx_err), atomic_read(&atm_dev->stats.aal5.rx_drop)); - if (!left--) - switch (atm_dev->signal) { - case ATM_PHY_SIG_FOUND: - return sprintf(page, "Line up\n"); - case ATM_PHY_SIG_LOST: - return sprintf(page, "Line down\n"); - default: - return sprintf(page, "Line state unknown\n"); - } + if (!left--) { + if (instance->disconnected) + return sprintf(page, "Disconnected\n"); + else + switch (atm_dev->signal) { + case ATM_PHY_SIG_FOUND: + return sprintf(page, "Line up\n"); + case ATM_PHY_SIG_LOST: + return sprintf(page, "Line down\n"); + default: + return sprintf(page, "Line state unknown\n"); + } + } return 0; } @@ -735,13 +812,24 @@ static int usbatm_atm_open(struct atm_vcc *vcc) atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci); /* only support AAL5 */ - if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) - || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { - atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); + if ((vcc->qos.aal != ATM_AAL5)) { + atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); + return -EINVAL; + } + + /* sanity checks */ + if ((vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { + atm_dbg(instance, "%s: max_sdu %d out of range!\n", __func__, vcc->qos.rxtp.max_sdu); return -EINVAL; } - down(&instance->serialize); /* vs self, usbatm_atm_close */ + mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */ + + if (instance->disconnected) { + atm_dbg(instance, "%s: disconnected!\n", __func__); + ret = -ENODEV; + goto fail; + } if (usbatm_find_vcc(instance, vpi, vci)) { atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci); @@ -749,20 +837,19 @@ static int usbatm_atm_open(struct atm_vcc *vcc) goto fail; } - if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) { - atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__); + if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) { + atm_err(instance, "%s: no memory for vcc_data!\n", __func__); ret = -ENOMEM; goto fail; } - memset(new, 0, sizeof(struct usbatm_vcc_data)); new->vcc = vcc; new->vpi = vpi; new->vci = vci; new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL); if (!new->sarb) { - atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__); + atm_err(instance, "%s: no memory for SAR buffer!\n", __func__); ret = -ENOMEM; goto fail; } @@ -770,6 +857,9 @@ static int usbatm_atm_open(struct atm_vcc *vcc) vcc->dev_data = new; tasklet_disable(&instance->rx_channel.tasklet); + instance->cached_vcc = new; + instance->cached_vpi = vpi; + instance->cached_vci = vci; list_add(&new->list, &instance->vcc_list); tasklet_enable(&instance->rx_channel.tasklet); @@ -777,7 +867,7 @@ static int usbatm_atm_open(struct atm_vcc *vcc) set_bit(ATM_VF_PARTIAL, &vcc->flags); set_bit(ATM_VF_READY, &vcc->flags); - up(&instance->serialize); + mutex_unlock(&instance->serialize); atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new); @@ -785,7 +875,7 @@ static int usbatm_atm_open(struct atm_vcc *vcc) fail: kfree(new); - up(&instance->serialize); + mutex_unlock(&instance->serialize); return ret; } @@ -806,9 +896,14 @@ static void usbatm_atm_close(struct atm_vcc *vcc) usbatm_cancel_send(instance, vcc); - down(&instance->serialize); /* vs self, usbatm_atm_open */ + mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */ tasklet_disable(&instance->rx_channel.tasklet); + if (instance->cached_vcc == vcc_data) { + instance->cached_vcc = NULL; + instance->cached_vpi = ATM_VPI_UNSPEC; + instance->cached_vci = ATM_VCI_UNSPEC; + } list_del(&vcc_data->list); tasklet_enable(&instance->rx_channel.tasklet); @@ -824,14 +919,21 @@ static void usbatm_atm_close(struct atm_vcc *vcc) clear_bit(ATM_VF_PARTIAL, &vcc->flags); clear_bit(ATM_VF_ADDR, &vcc->flags); - up(&instance->serialize); + mutex_unlock(&instance->serialize); atm_dbg(instance, "%s successful\n", __func__); } -static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, +static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg) { + struct usbatm_data *instance = atm_dev->dev_data; + + if (!instance || instance->disconnected) { + dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance"); + return -ENODEV; + } + switch (cmd) { case ATM_QUERYLOOP: return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; @@ -845,10 +947,13 @@ static int usbatm_atm_init(struct usbatm_data *instance) struct atm_dev *atm_dev; int ret, i; - /* ATM init */ + /* ATM init. The ATM initialization scheme suffers from an intrinsic race + * condition: callbacks we register can be executed at once, before we have + * initialized the struct atm_dev. To protect against this, all callbacks + * abort if atm_dev->dev_data is NULL. */ atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL); if (!atm_dev) { - usb_dbg(instance, "%s: failed to register ATM device!\n", __func__); + usb_err(instance, "%s: failed to register ATM device!\n", __func__); return -1; } @@ -862,12 +967,13 @@ static int usbatm_atm_init(struct usbatm_data *instance) atm_dev->link_rate = 128 * 1000 / 424; if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { - atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret); + atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret); goto fail; } - /* ready for ATM callbacks */ usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */ + + /* ready for ATM callbacks */ mb(); atm_dev->dev_data = instance; @@ -903,9 +1009,9 @@ static int usbatm_do_heavy_init(void *arg) if (!ret) ret = usbatm_atm_init(instance); - down(&instance->serialize); + mutex_lock(&instance->serialize); instance->thread_pid = -1; - up(&instance->serialize); + mutex_unlock(&instance->serialize); complete_and_exit(&instance->thread_exited, ret); } @@ -915,13 +1021,13 @@ static int usbatm_heavy_init(struct usbatm_data *instance) int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL); if (ret < 0) { - usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); + usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); return ret; } - down(&instance->serialize); + mutex_lock(&instance->serialize); instance->thread_pid = ret; - up(&instance->serialize); + mutex_unlock(&instance->serialize); wait_for_completion(&instance->thread_started); @@ -951,9 +1057,9 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, char *buf; int error = -ENOMEM; int i, length; - int need_heavy; + unsigned int maxpacket, num_packets; - dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n", + dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n", __func__, driver->driver_name, le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), @@ -962,7 +1068,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, /* instance init */ instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); if (!instance) { - dev_dbg(dev, "%s: no memory for instance data!\n", __func__); + dev_err(dev, "%s: no memory for instance data!\n", __func__); return -ENOMEM; } @@ -996,66 +1102,96 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, snprintf(buf, length, ")"); bind: - need_heavy = 1; - if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) { - dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error); + if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) { + dev_err(dev, "%s: bind failed: %d!\n", __func__, error); goto fail_free; } /* private fields */ kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */ - init_MUTEX(&instance->serialize); + mutex_init(&instance->serialize); instance->thread_pid = -1; init_completion(&instance->thread_started); init_completion(&instance->thread_exited); INIT_LIST_HEAD(&instance->vcc_list); + skb_queue_head_init(&instance->sndqueue); usbatm_init_channel(&instance->rx_channel); usbatm_init_channel(&instance->tx_channel); tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance); tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance); - instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in); - instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out); instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; - instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride; - instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride; instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; - skb_queue_head_init(&instance->sndqueue); + if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in) + instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in); + else + instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in); + + instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out); + + /* tx buffer size must be a positive multiple of the stride */ + instance->tx_channel.buf_size = max (instance->tx_channel.stride, + snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); + + /* rx buffer size must be a positive multiple of the endpoint maxpacket */ + maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0); + + if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) { + dev_err(dev, "%s: invalid endpoint %02x!\n", __func__, + usb_pipeendpoint(instance->rx_channel.endpoint)); + error = -EINVAL; + goto fail_unbind; + } + + num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ + + if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) + num_packets--; + + instance->rx_channel.buf_size = num_packets * maxpacket; + instance->rx_channel.packet_size = maxpacket; + +#ifdef DEBUG + for (i = 0; i < 2; i++) { + struct usbatm_channel *channel = i ? + &instance->tx_channel : &instance->rx_channel; + + dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel); + } +#endif + + /* initialize urbs */ for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { - struct urb *urb; u8 *buffer; - unsigned int iso_packets = 0, iso_size = 0; struct usbatm_channel *channel = i < num_rcv_urbs ? &instance->rx_channel : &instance->tx_channel; + struct urb *urb; + unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0; - if (usb_pipeisoc(channel->endpoint)) { - /* don't expect iso out endpoints */ - iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0); - iso_size -= iso_size % channel->stride; /* alignment */ - BUG_ON(!iso_size); - iso_packets = (channel->buf_size - 1) / iso_size + 1; - } + UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint)); urb = usb_alloc_urb(iso_packets, GFP_KERNEL); if (!urb) { - dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i); + dev_err(dev, "%s: no memory for urb %d!\n", __func__, i); + error = -ENOMEM; goto fail_unbind; } instance->urbs[i] = urb; - buffer = kmalloc(channel->buf_size, GFP_KERNEL); + /* zero the tx padding to avoid leaking information */ + buffer = kzalloc(channel->buf_size, GFP_KERNEL); if (!buffer) { - dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i); + dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i); + error = -ENOMEM; goto fail_unbind; } - memset(buffer, 0, channel->buf_size); usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint, buffer, channel->buf_size, usbatm_complete, channel); @@ -1065,9 +1201,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = iso_packets; for (j = 0; j < iso_packets; j++) { - urb->iso_frame_desc[j].offset = iso_size * j; - urb->iso_frame_desc[j].length = min_t(int, iso_size, - channel->buf_size - urb->iso_frame_desc[j].offset); + urb->iso_frame_desc[j].offset = channel->packet_size * j; + urb->iso_frame_desc[j].length = channel->packet_size; } } @@ -1079,7 +1214,17 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb); } - if (need_heavy && driver->heavy_init) { + instance->cached_vpi = ATM_VPI_UNSPEC; + instance->cached_vci = ATM_VCI_UNSPEC; + instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL); + + if (!instance->cell_buf) { + dev_err(dev, "%s: no memory for cell buffer!\n", __func__); + error = -ENOMEM; + goto fail_unbind; + } + + if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) { error = usbatm_heavy_init(instance); } else { complete(&instance->thread_exited); /* pretend that heavy_init was run */ @@ -1098,6 +1243,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, if (instance->driver->unbind) instance->driver->unbind(instance, intf); fail_free: + kfree(instance->cell_buf); + for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { if (instance->urbs[i]) kfree(instance->urbs[i]->transfer_buffer); @@ -1114,6 +1261,7 @@ void usbatm_usb_disconnect(struct usb_interface *intf) { struct device *dev = &intf->dev; struct usbatm_data *instance = usb_get_intfdata(intf); + struct usbatm_vcc_data *vcc_data; int i; dev_dbg(dev, "%s entered\n", __func__); @@ -1125,13 +1273,19 @@ void usbatm_usb_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); - down(&instance->serialize); + mutex_lock(&instance->serialize); + instance->disconnected = 1; if (instance->thread_pid >= 0) kill_proc(instance->thread_pid, SIGTERM, 1); - up(&instance->serialize); + mutex_unlock(&instance->serialize); wait_for_completion(&instance->thread_exited); + mutex_lock(&instance->serialize); + list_for_each_entry(vcc_data, &instance->vcc_list, list) + vcc_release_async(vcc_data->vcc, -EPIPE); + mutex_unlock(&instance->serialize); + tasklet_disable(&instance->rx_channel.tasklet); tasklet_disable(&instance->tx_channel.tasklet); @@ -1141,6 +1295,14 @@ void usbatm_usb_disconnect(struct usb_interface *intf) del_timer_sync(&instance->rx_channel.delay); del_timer_sync(&instance->tx_channel.delay); + /* turn usbatm_[rt]x_process into something close to a no-op */ + /* no need to take the spinlock */ + INIT_LIST_HEAD(&instance->rx_channel.list); + INIT_LIST_HEAD(&instance->tx_channel.list); + + tasklet_enable(&instance->rx_channel.tasklet); + tasklet_enable(&instance->tx_channel.tasklet); + if (instance->atm_dev && instance->driver->atm_stop) instance->driver->atm_stop(instance, instance->atm_dev); @@ -1149,19 +1311,13 @@ void usbatm_usb_disconnect(struct usb_interface *intf) instance->driver_data = NULL; - /* turn usbatm_[rt]x_process into noop */ - /* no need to take the spinlock */ - INIT_LIST_HEAD(&instance->rx_channel.list); - INIT_LIST_HEAD(&instance->tx_channel.list); - - tasklet_enable(&instance->rx_channel.tasklet); - tasklet_enable(&instance->tx_channel.tasklet); - for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { kfree(instance->urbs[i]->transfer_buffer); usb_free_urb(instance->urbs[i]); } + kfree(instance->cell_buf); + /* ATM finalize */ if (instance->atm_dev) atm_dev_deregister(instance->atm_dev); @@ -1186,10 +1342,10 @@ static int __init usbatm_usb_init(void) if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) || (num_snd_urbs > UDSL_MAX_SND_URBS) - || (rcv_buf_size < 1) - || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) - || (snd_buf_size < 1) - || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) + || (rcv_buf_bytes < 1) + || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE) + || (snd_buf_bytes < 1) + || (snd_buf_bytes > UDSL_MAX_BUF_SIZE)) return -EINVAL; return 0; diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 1adacd60d713..ff8551e93372 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -24,21 +24,21 @@ #ifndef _USBATM_H_ #define _USBATM_H_ -#include <linux/config.h> - -/* -#define VERBOSE_DEBUG -*/ - #include <asm/semaphore.h> #include <linux/atm.h> #include <linux/atmdev.h> #include <linux/completion.h> #include <linux/device.h> +#include <linux/kernel.h> #include <linux/kref.h> #include <linux/list.h> #include <linux/stringify.h> #include <linux/usb.h> +#include <linux/mutex.h> + +/* +#define VERBOSE_DEBUG +*/ #ifdef DEBUG #define UDSL_ASSERT(x) BUG_ON(!(x)) @@ -52,8 +52,13 @@ dev_info(&(instance)->usb_intf->dev , format , ## arg) #define usb_warn(instance, format, arg...) \ dev_warn(&(instance)->usb_intf->dev , format , ## arg) +#ifdef DEBUG #define usb_dbg(instance, format, arg...) \ - dev_dbg(&(instance)->usb_intf->dev , format , ## arg) + dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) +#else +#define usb_dbg(instance, format, arg...) \ + do {} while (0) +#endif /* FIXME: move to dev_* once ATM is driver model aware */ #define atm_printk(level, instance, format, arg...) \ @@ -69,12 +74,24 @@ #ifdef DEBUG #define atm_dbg(instance, format, arg...) \ atm_printk(KERN_DEBUG, instance , format , ## arg) +#define atm_rldbg(instance, format, arg...) \ + if (printk_ratelimit()) \ + atm_printk(KERN_DEBUG, instance , format , ## arg) #else #define atm_dbg(instance, format, arg...) \ do {} while (0) +#define atm_rldbg(instance, format, arg...) \ + do {} while (0) #endif +/* flags, set by mini-driver in bind() */ + +#define UDSL_SKIP_HEAVY_INIT (1<<0) +#define UDSL_USE_ISOC (1<<1) +#define UDSL_IGNORE_EILSEQ (1<<2) + + /* mini driver */ struct usbatm_data; @@ -86,16 +103,11 @@ struct usbatm_data; */ struct usbatm_driver { - struct module *owner; - const char *driver_name; - /* - * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init - * method can avoid having it called by setting need_heavy_init to zero. - */ + /* init device ... can sleep, or cause probe() failure */ int (*bind) (struct usbatm_data *, struct usb_interface *, - const struct usb_device_id *id, int *need_heavy_init); + const struct usb_device_id *id); /* additional device initialization that is too slow to be done in probe() */ int (*heavy_init) (struct usbatm_data *, struct usb_interface *); @@ -109,8 +121,9 @@ struct usbatm_driver { /* cleanup ATM device ... can sleep, but can't fail */ void (*atm_stop) (struct usbatm_data *, struct atm_dev *); - int in; /* rx endpoint */ - int out; /* tx endpoint */ + int bulk_in; /* bulk rx endpoint */ + int isoc_in; /* isochronous rx endpoint */ + int bulk_out; /* bulk tx endpoint */ unsigned rx_padding; unsigned tx_padding; @@ -125,6 +138,7 @@ struct usbatm_channel { int endpoint; /* usb pipe */ unsigned int stride; /* ATM cell size + padding */ unsigned int buf_size; /* urb buffer size */ + unsigned int packet_size; /* endpoint maxpacket */ spinlock_t lock; struct list_head list; struct tasklet_struct tasklet; @@ -143,6 +157,7 @@ struct usbatm_data { struct usbatm_driver *driver; void *driver_data; char driver_name[16]; + unsigned int flags; /* set by mini-driver in bind() */ /* USB device */ struct usb_device *usb_dev; @@ -157,7 +172,8 @@ struct usbatm_data { ********************************/ struct kref refcount; - struct semaphore serialize; + struct mutex serialize; + int disconnected; /* heavy init */ int thread_pid; @@ -171,7 +187,14 @@ struct usbatm_data { struct usbatm_channel tx_channel; struct sk_buff_head sndqueue; - struct sk_buff *current_skb; /* being emptied */ + struct sk_buff *current_skb; /* being emptied */ + + struct usbatm_vcc_data *cached_vcc; + int cached_vci; + short cached_vpi; + + unsigned char *cell_buf; /* holds partial rx cell */ + unsigned int buf_usage; struct urb *urbs[0]; }; diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 5c76e3aaaa5e..42d6823b82b3 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -41,6 +41,8 @@ XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number"); XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number"); XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)"); XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)"); +XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)"); +XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)"); static const char xusbatm_driver_name[] = "xusbatm"; @@ -48,82 +50,118 @@ static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX]; static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; static struct usb_driver xusbatm_usb_driver; -static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep) +static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep) { + struct usb_host_interface *alt; + struct usb_interface *intf; int i, j; - for (i = 0; i < intf->num_altsetting; i++) { - struct usb_host_interface *alt = intf->altsetting; - for (j = 0; j < alt->desc.bNumEndpoints; j++) - if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep) - return 1; + for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) + if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting))) + for (j = 0; j < alt->desc.bNumEndpoints; j++) + if (alt->endpoint[j].desc.bEndpointAddress == ep) + return intf; + return NULL; +} + +static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev, + struct usb_interface *intf, int altsetting, int claim) +{ + int ifnum = intf->altsetting->desc.bInterfaceNumber; + int ret; + + if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) { + usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret); + return ret; + } + if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) { + usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret); + return ret; } return 0; } -static int xusbatm_bind(struct usbatm_data *usbatm_instance, - struct usb_interface *intf, const struct usb_device_id *id, - int *need_heavy_init) +static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed) +{ + if (claimed) { + usb_set_intfdata(intf, NULL); + usb_driver_release_interface(&xusbatm_usb_driver, intf); + } +} + +static int xusbatm_bind(struct usbatm_data *usbatm, + struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *usb_dev = interface_to_usbdev(intf); int drv_ix = id - xusbatm_usb_ids; - int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]); - int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]); - u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix]; - int i, ret; - - usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x" - " rx: ep %#x padd %d tx: ep %#x padd %d\n", + int rx_alt = rx_altsetting[drv_ix]; + int tx_alt = tx_altsetting[drv_ix]; + struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]); + struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]); + int ret; + + usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x" + " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n", __func__, drv_ix, vendor[drv_ix], product[drv_ix], - rx_endpoint[drv_ix], rx_padding[drv_ix], - tx_endpoint[drv_ix], tx_padding[drv_ix]); + rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt, + tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt); + + if (!rx_intf || !tx_intf) { + if (!rx_intf) + usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n", + __func__, rx_endpoint[drv_ix], rx_alt); + if (!tx_intf) + usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n", + __func__, tx_endpoint[drv_ix], tx_alt); + return -ENODEV; + } - if (!rx_ep_present && !tx_ep_present) { - usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n", - __func__, intf->altsetting->desc.bInterfaceNumber, - rx_endpoint[drv_ix], tx_endpoint[drv_ix]); + if ((rx_intf != intf) && (tx_intf != intf)) return -ENODEV; + + if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) { + usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__, + rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt); + return -EINVAL; } - if (rx_ep_present && tx_ep_present) - return 0; + usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__, + rx_intf->altsetting->desc.bInterfaceNumber, + tx_intf->altsetting->desc.bInterfaceNumber); - for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; - - if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) { - ret = usb_driver_claim_interface(&xusbatm_usb_driver, - cur_if, usbatm_instance); - if (!ret) - usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n", - __func__, cur_if->altsetting->desc.bInterfaceNumber, ret); - return ret; - } + if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf))) + return ret; + + if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) { + xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf); + return ret; } - usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n", - __func__, searched_ep); - return -ENODEV; + return 0; } -static void xusbatm_unbind(struct usbatm_data *usbatm_instance, +static void xusbatm_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) { struct usb_device *usb_dev = interface_to_usbdev(intf); int i; - usb_dbg(usbatm_instance, "%s entered\n", __func__); + + usb_dbg(usbatm, "%s entered\n", __func__); for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; - usb_set_intfdata(cur_if, NULL); - usb_driver_release_interface(&xusbatm_usb_driver, cur_if); + struct usb_interface *cur_intf = usb_dev->actconfig->interface[i]; + + if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) { + usb_set_intfdata(cur_intf, NULL); + usb_driver_release_interface(&xusbatm_usb_driver, cur_intf); + } } } -static int xusbatm_atm_start(struct usbatm_data *usbatm_instance, +static int xusbatm_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_dev) { - atm_dbg(usbatm_instance, "%s entered\n", __func__); + atm_dbg(usbatm, "%s entered\n", __func__); /* use random MAC as we've no way to get it from the device */ random_ether_addr(atm_dev->esi); @@ -161,18 +199,19 @@ static int __init xusbatm_init(void) } for (i = 0; i < num_vendor; i++) { + rx_endpoint[i] |= USB_DIR_IN; + tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK; + xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; xusbatm_usb_ids[i].idVendor = vendor[i]; xusbatm_usb_ids[i].idProduct = product[i]; - - xusbatm_drivers[i].owner = THIS_MODULE; xusbatm_drivers[i].driver_name = xusbatm_driver_name; xusbatm_drivers[i].bind = xusbatm_bind; xusbatm_drivers[i].unbind = xusbatm_unbind; xusbatm_drivers[i].atm_start = xusbatm_atm_start; - xusbatm_drivers[i].in = rx_endpoint[i]; - xusbatm_drivers[i].out = tx_endpoint[i]; + xusbatm_drivers[i].bulk_in = rx_endpoint[i]; + xusbatm_drivers[i].bulk_out = tx_endpoint[i]; xusbatm_drivers[i].rx_padding = rx_padding[i]; xusbatm_drivers[i].tx_padding = tx_padding[i]; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b9fd39fd1b5b..97bdeb1c2181 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1014,8 +1014,13 @@ static void acm_disconnect(struct usb_interface *intf) } down(&open_sem); + if (!usb_get_intfdata(intf)) { + up(&open_sem); + return; + } acm->dev = NULL; - usb_set_intfdata (intf, NULL); + usb_set_intfdata(acm->control, NULL); + usb_set_intfdata(acm->data, NULL); tasklet_disable(&acm->urb_task); @@ -1036,7 +1041,7 @@ static void acm_disconnect(struct usb_interface *intf) for (i = 0; i < ACM_NRB; i++) usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); - usb_driver_release_interface(&acm_driver, acm->data); + usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); if (!acm->used) { acm_tty_unregister(acm); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index dba4cc026077..d34848ac30b0 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -7,6 +7,7 @@ * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com> # Copyright (c) 2001 David Paschal <paschal@rcsis.com> + * Copyright (c) 2006 Oliver Neukum <oliver@neukum.name> * * USB Printer Device Class driver for USB printers and printer cables * @@ -273,13 +274,16 @@ static void usblp_bulk_read(struct urb *urb, struct pt_regs *regs) { struct usblp *usblp = urb->context; - if (!usblp || !usblp->dev || !usblp->used || !usblp->present) + if (unlikely(!usblp || !usblp->dev || !usblp->used)) return; + if (unlikely(!usblp->present)) + goto unplug; if (unlikely(urb->status)) warn("usblp%d: nonzero read/write bulk status received: %d", usblp->minor, urb->status); usblp->rcomplete = 1; +unplug: wake_up_interruptible(&usblp->wait); } @@ -287,13 +291,15 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs) { struct usblp *usblp = urb->context; - if (!usblp || !usblp->dev || !usblp->used || !usblp->present) + if (unlikely(!usblp || !usblp->dev || !usblp->used)) return; - + if (unlikely(!usblp->present)) + goto unplug; if (unlikely(urb->status)) warn("usblp%d: nonzero read/write bulk status received: %d", usblp->minor, urb->status); usblp->wcomplete = 1; +unplug: wake_up_interruptible(&usblp->wait); } @@ -627,9 +633,8 @@ done: static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); struct usblp *usblp = file->private_data; - int timeout, err = 0, transfer_length = 0; + int timeout, rv, err = 0, transfer_length = 0; size_t writecount = 0; while (writecount < count) { @@ -641,24 +646,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t } timeout = USBLP_WRITE_TIMEOUT; - add_wait_queue(&usblp->wait, &wait); - while ( 1==1 ) { - if (signal_pending(current)) { - remove_wait_queue(&usblp->wait, &wait); - return writecount ? writecount : -EINTR; - } - set_current_state(TASK_INTERRUPTIBLE); - if (timeout && !usblp->wcomplete) { - timeout = schedule_timeout(timeout); - } else { - set_current_state(TASK_RUNNING); - break; - } - } - remove_wait_queue(&usblp->wait, &wait); + rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout); + if (rv < 0) + return writecount ? writecount : -EINTR; } - down (&usblp->sem); if (!usblp->present) { up (&usblp->sem); @@ -724,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct usblp *usblp = file->private_data; - DECLARE_WAITQUEUE(wait, current); + int rv; if (!usblp->bidir) return -EINVAL; @@ -742,26 +734,13 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, count = -EAGAIN; goto done; } - - add_wait_queue(&usblp->wait, &wait); - while (1==1) { - if (signal_pending(current)) { - count = -EINTR; - remove_wait_queue(&usblp->wait, &wait); - goto done; - } - up (&usblp->sem); - set_current_state(TASK_INTERRUPTIBLE); - if (!usblp->rcomplete) { - schedule(); - } else { - set_current_state(TASK_RUNNING); - down(&usblp->sem); - break; - } - down (&usblp->sem); + up(&usblp->sem); + rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); + down(&usblp->sem); + if (rv < 0) { + count = -EINTR; + goto done; } - remove_wait_queue(&usblp->wait, &wait); } if (!usblp->present) { @@ -874,11 +853,10 @@ static int usblp_probe(struct usb_interface *intf, /* Malloc and start initializing usblp structure so we can use it * directly. */ - if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) { + if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { err("out of memory for usblp"); goto abort; } - memset(usblp, 0, sizeof(struct usblp)); usblp->dev = dev; init_MUTEX (&usblp->sem); init_waitqueue_head(&usblp->wait); @@ -1214,10 +1192,9 @@ static int __init usblp_init(void) { int retval; retval = usb_register(&usblp_driver); - if (retval) - goto out; - info(DRIVER_VERSION ": " DRIVER_DESC); -out: + if (!retval) + info(DRIVER_VERSION ": " DRIVER_DESC); + return retval; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 076462c8ba2a..dce9d987f0fc 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, return NULL; } -EXPORT_SYMBOL_GPL(usb_match_id); +EXPORT_SYMBOL(usb_match_id); int usb_device_match(struct device *dev, struct device_driver *drv) { @@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) return retval; } -EXPORT_SYMBOL_GPL(usb_register_driver); +EXPORT_SYMBOL(usb_register_driver); /** * usb_deregister - unregister a USB driver @@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver) usbfs_update_special(); } -EXPORT_SYMBOL_GPL(usb_deregister); +EXPORT_SYMBOL(usb_deregister); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 319de03944e7..7135e542679d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -13,6 +13,7 @@ #include <linux/ctype.h> #include <linux/device.h> #include <asm/byteorder.h> +#include <asm/scatterlist.h> #include "hcd.h" /* for usbcore internals */ #include "usb.h" diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 081796726b95..dad4d8fd8180 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -468,6 +468,7 @@ int usb_unlink_urb(struct urb *urb) */ void usb_kill_urb(struct urb *urb) { + might_sleep(); if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op)) return; spin_lock_irq(&urb->lock); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 9a4edc5657aa..0aab7d24c768 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -135,6 +135,7 @@ struct dev_data { setup_out_ready : 1, setup_out_error : 1, setup_abort : 1; + unsigned setup_wLength; /* the rest is basically write-once */ struct usb_config_descriptor *config, *hs_config; @@ -942,6 +943,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) } req->complete = ep0_complete; req->length = len; + req->zero = 0; return 0; } @@ -1161,10 +1163,13 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) spin_unlock_irq (&dev->lock); if (copy_from_user (dev->req->buf, buf, len)) retval = -EFAULT; - else + else { + if (len < dev->setup_wLength) + dev->req->zero = 1; retval = usb_ep_queue ( dev->gadget->ep0, dev->req, GFP_KERNEL); + } if (retval < 0) { spin_lock_irq (&dev->lock); clean_req (dev->gadget->ep0, dev->req); @@ -1483,6 +1488,7 @@ unrecognized: delegate: dev->setup_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0; + dev->setup_wLength = w_length; dev->setup_out_ready = 0; dev->setup_out_error = 0; value = 0; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index c32e1f7476da..67b13ab2f3f5 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -47,6 +47,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ioport.h> diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 2fc110d3ad5a..ae7a1c0f5748 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -165,8 +165,8 @@ static unsigned buflen = 4096; static unsigned qlen = 32; static unsigned pattern = 0; -module_param (buflen, uint, S_IRUGO|S_IWUSR); -module_param (qlen, uint, S_IRUGO|S_IWUSR); +module_param (buflen, uint, S_IRUGO); +module_param (qlen, uint, S_IRUGO); module_param (pattern, uint, S_IRUGO|S_IWUSR); /* @@ -1127,8 +1127,10 @@ zero_unbind (struct usb_gadget *gadget) DBG (dev, "unbind\n"); /* we've already been disconnected ... no i/o is active */ - if (dev->req) + if (dev->req) { + dev->req->length = USB_BUFSIZ; free_ep_req (gadget->ep0, dev->req); + } del_timer_sync (&dev->resume); kfree (dev); set_gadget_data (gadget, NULL); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 08ca0f849dab..3a6687df5594 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -24,46 +24,11 @@ /*-------------------------------------------------------------------------*/ -/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... - * off the controller (maybe it can boot from highspeed USB disks). - */ -static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap) -{ - struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); - - /* always say Linux will own the hardware */ - pci_write_config_byte(pdev, where + 3, 1); - - /* maybe wait a while for BIOS to respond */ - if (cap & (1 << 16)) { - int msec = 5000; - - do { - msleep(10); - msec -= 10; - pci_read_config_dword(pdev, where, &cap); - } while ((cap & (1 << 16)) && msec); - if (cap & (1 << 16)) { - ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", - where, cap); - // some BIOS versions seem buggy... - // return 1; - ehci_warn(ehci, "continuing after BIOS bug...\n"); - /* disable all SMIs, and clear "BIOS owns" flag */ - pci_write_config_dword(pdev, where + 4, 0); - pci_write_config_byte(pdev, where + 2, 0); - } else - ehci_dbg(ehci, "BIOS handoff succeeded\n"); - } - return 0; -} - /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) { u32 temp; int retval; - unsigned count = 256/4; /* optional debug port, normally in the first BAR */ temp = pci_find_capability(pdev, 0x0a); @@ -84,32 +49,9 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) } } - temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params)); - - /* EHCI 0.96 and later may have "extended capabilities" */ - while (temp && count--) { - u32 cap; - - pci_read_config_dword(pdev, temp, &cap); - ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp); - switch (cap & 0xff) { - case 1: /* BIOS/SMM/... handoff */ - if (bios_handoff(ehci, temp, cap) != 0) - return -EOPNOTSUPP; - break; - case 0: /* illegal reserved capability */ - ehci_dbg(ehci, "illegal capability!\n"); - cap = 0; - /* FALLTHROUGH */ - default: /* unknown */ - break; - } - temp = (cap >> 8) & 0xff; - } - if (!count) { - ehci_err(ehci, "bogus capabilities ... PCI problems!\n"); - return -EIO; - } + /* we expect static quirk code to handle the "extended capabilities" + * (currently just BIOS handoff) allowed starting with EHCI 0.96 + */ /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ retval = pci_set_mwi(pdev); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 57e77374d228..ebcca9700671 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1063,6 +1063,7 @@ sitd_slot_ok ( /* for IN, check CSPLIT */ if (stream->c_usecs) { + uf = uframe & 7; max_used = 100 - stream->c_usecs; do { tmp = 1 << uf; @@ -1843,8 +1844,7 @@ done: #else static inline int -sitd_submit (struct ehci_hcd *ehci, struct urb *urb, - unsigned mem_flags) +sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) { ehci_dbg (ehci, "split iso support is disabled\n"); return -ENOSYS; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 584b8dc65119..972ce04889f8 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1420,20 +1420,22 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) int ret = 0; spin_lock_irqsave(&isp116x->lock, flags); - val = isp116x_read_reg32(isp116x, HCCONTROL); + switch (val & HCCONTROL_HCFS) { case HCCONTROL_USB_OPER: + spin_unlock_irqrestore(&isp116x->lock, flags); val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); val |= HCCONTROL_USB_SUSPEND; if (device_may_wakeup(&hcd->self.root_hub->dev)) val |= HCCONTROL_RWE; /* Wait for usb transfers to finish */ - mdelay(2); + msleep(2); + spin_lock_irqsave(&isp116x->lock, flags); isp116x_write_reg32(isp116x, HCCONTROL, val); + spin_unlock_irqrestore(&isp116x->lock, flags); /* Wait for devices to suspend */ - mdelay(5); - case HCCONTROL_USB_SUSPEND: + msleep(5); break; case HCCONTROL_USB_RESUME: isp116x_write_reg32(isp116x, HCCONTROL, @@ -1441,12 +1443,11 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) HCCONTROL_USB_RESET); case HCCONTROL_USB_RESET: ret = -EBUSY; + default: /* HCCONTROL_USB_SUSPEND */ + spin_unlock_irqrestore(&isp116x->lock, flags); break; - default: - ret = -EINVAL; } - spin_unlock_irqrestore(&isp116x->lock, flags); return ret; } @@ -1715,9 +1716,9 @@ static struct platform_driver isp116x_driver = { .remove = isp116x_remove, .suspend = isp116x_suspend, .resume = isp116x_resume, - .driver = { - .name = (char *)hcd_name, - }, + .driver = { + .name = (char *)hcd_name, + }, }; /*-----------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 77cd6ac07e3c..db280ca7b7a0 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -67,7 +67,7 @@ static void au1xxx_stop_hc(struct platform_device *dev) ": stopping Au1xxx OHCI USB Controller\n"); /* Disable clock */ - au_writel(readl((void *)USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); + au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 3ef2c0cdf1db..e9e5bc178cef 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -190,7 +190,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) msleep(10); } if (wait_time <= 0) - printk(KERN_WARNING "%s %s: early BIOS handoff " + printk(KERN_WARNING "%s %s: BIOS handoff " "failed (BIOS bug ?)\n", pdev->dev.bus_id, "OHCI"); @@ -212,8 +212,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) { int wait_time, delta; void __iomem *base, *op_reg_base; - u32 hcc_params, val, temp; - u8 cap_length; + u32 hcc_params, val; + u8 offset, cap_length; + int count = 256/4; if (!mmio_resource_enabled(pdev, 0)) return; @@ -224,51 +225,80 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) cap_length = readb(base); op_reg_base = base + cap_length; + + /* EHCI 0.96 and later may have "extended capabilities" + * spec section 5.1 explains the bios handoff, e.g. for + * booting from USB disk or using a usb keyboard + */ hcc_params = readl(base + EHCI_HCC_PARAMS); - hcc_params = (hcc_params >> 8) & 0xff; - if (hcc_params) { - pci_read_config_dword(pdev, - hcc_params + EHCI_USBLEGSUP, - &val); - if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) { - /* - * Ok, BIOS is in smm mode, try to hand off... + offset = (hcc_params >> 8) & 0xff; + while (offset && count--) { + u32 cap; + int msec; + + pci_read_config_dword(pdev, offset, &cap); + switch (cap & 0xff) { + case 1: /* BIOS/SMM/... handoff support */ + if ((cap & EHCI_USBLEGSUP_BIOS)) { + pr_debug("%s %s: BIOS handoff\n", + pdev->dev.bus_id, "EHCI"); + + /* BIOS workaround (?): be sure the + * pre-Linux code receives the SMI + */ + pci_read_config_dword(pdev, + offset + EHCI_USBLEGCTLSTS, + &val); + pci_write_config_dword(pdev, + offset + EHCI_USBLEGCTLSTS, + val | EHCI_USBLEGCTLSTS_SOOE); + } + + /* always say Linux will own the hardware + * by setting EHCI_USBLEGSUP_OS. */ - pci_read_config_dword(pdev, - hcc_params + EHCI_USBLEGCTLSTS, - &temp); - pci_write_config_dword(pdev, - hcc_params + EHCI_USBLEGCTLSTS, - temp | EHCI_USBLEGCTLSTS_SOOE); - val |= EHCI_USBLEGSUP_OS; - pci_write_config_dword(pdev, - hcc_params + EHCI_USBLEGSUP, - val); + pci_write_config_byte(pdev, offset + 3, 1); - wait_time = 500; - do { + /* if boot firmware now owns EHCI, spin till + * it hands it over. + */ + msec = 5000; + while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { msleep(10); - wait_time -= 10; - pci_read_config_dword(pdev, - hcc_params + EHCI_USBLEGSUP, - &val); - } while (wait_time && (val & EHCI_USBLEGSUP_BIOS)); - if (!wait_time) { - /* - * well, possibly buggy BIOS... + msec -= 10; + pci_read_config_dword(pdev, offset, &cap); + } + + if (cap & EHCI_USBLEGSUP_BIOS) { + /* well, possibly buggy BIOS... try to shut + * it down, and hope nothing goes too wrong */ - printk(KERN_WARNING "%s %s: early BIOS handoff " + printk(KERN_WARNING "%s %s: BIOS handoff " "failed (BIOS bug ?)\n", pdev->dev.bus_id, "EHCI"); - pci_write_config_dword(pdev, - hcc_params + EHCI_USBLEGSUP, - EHCI_USBLEGSUP_OS); - pci_write_config_dword(pdev, - hcc_params + EHCI_USBLEGCTLSTS, - 0); + pci_write_config_byte(pdev, offset + 2, 0); } + + /* just in case, always disable EHCI SMIs */ + pci_write_config_dword(pdev, + offset + EHCI_USBLEGCTLSTS, + 0); + break; + case 0: /* illegal reserved capability */ + cap = 0; + /* FALLTHROUGH */ + default: + printk(KERN_WARNING "%s %s: unrecognized " + "capability %02x\n", + pdev->dev.bus_id, "EHCI", + cap & 0xff); + break; } + offset = (cap >> 8) & 0xff; } + if (!count) + printk(KERN_DEBUG "%s %s: capability loop?\n", + pdev->dev.bus_id, "EHCI"); /* * halt EHCI & disable its interrupts in any case diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index b6076004a437..782398045f9f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -672,9 +672,9 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur /* Low-speed transfers get a different queue, and won't hog the bus. * Also, some devices enumerate better without FSBR; the easiest way * to do that is to put URBs on the low-speed queue while the device - * is in the DEFAULT state. */ + * isn't in the CONFIGURED state. */ if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->state == USB_STATE_DEFAULT) + urb->dev->state != USB_STATE_CONFIGURED) skelqh = uhci->skel_ls_control_qh; else { skelqh = uhci->skel_fs_control_qh; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a91e72c41415..6f7a684c3e07 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1307,7 +1307,7 @@ void hid_init_reports(struct hid_device *hid) } if (err) - warn("timeout initializing reports\n"); + warn("timeout initializing reports"); } #define USB_VENDOR_ID_WACOM 0x056a @@ -1453,6 +1453,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 +#define USB_VENDOR_ID_HP 0x03f0 +#define USB_DEVICE_ID_HP_USBHUB_KB 0x020c + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1566,6 +1569,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, + { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE }, @@ -1828,9 +1832,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); - /* May be needed for some devices */ - usb_clear_halt(hid->dev, hid->urbin->pipe); - return hid; fail: diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 4dff8473553d..925f5aba06f5 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -35,7 +35,6 @@ #include <linux/usb.h> #include "hid.h" #include <linux/hiddev.h> -#include <linux/devfs_fs_kernel.h> #ifdef CONFIG_USB_DYNAMIC_MINORS #define HIDDEV_MINOR_BASE 0 @@ -632,7 +631,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values >= field->report_count)) + uref->usage_index + uref_multi->num_values > field->report_count)) goto inval; } @@ -832,12 +831,10 @@ static /* const */ struct usb_driver hiddev_driver = { int __init hiddev_init(void) { - devfs_mk_dir("usb/hid"); return usb_register(&hiddev_driver); } void hiddev_exit(void) { usb_deregister(&hiddev_driver); - devfs_remove("usb/hid"); } diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 3b3c7b4120a2..697c5e573a11 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -337,6 +337,9 @@ static int touchkit_probe(struct usb_interface *intf, touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, touchkit_irq, touchkit, endpoint->bInterval); + touchkit->irq->transfer_dma = touchkit->data_dma; + touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + input_register_device(touchkit->input); usb_set_intfdata(intf, touchkit); diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 1bfc105ad4d6..37d2f0ba0319 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -59,7 +59,7 @@ #include "map_to_7segment.h" #include "yealink.h" -#define DRIVER_VERSION "yld-20050816" +#define DRIVER_VERSION "yld-20051230" #define DRIVER_AUTHOR "Henk Vergonet" #define DRIVER_DESC "Yealink phone driver" @@ -786,16 +786,25 @@ static struct attribute_group yld_attr_group = { * Linux interface and usb initialisation ******************************************************************************/ -static const struct yld_device { - u16 idVendor; - u16 idProduct; +struct driver_info { char *name; -} yld_device[] = { - { 0x6993, 0xb001, "Yealink usb-p1k" }, }; -static struct usb_device_id usb_table [] = { - { USB_INTERFACE_INFO(USB_CLASS_HID, 0, 0) }, +static const struct driver_info info_P1K = { + .name = "Yealink usb-p1k", +}; + +static const struct usb_device_id usb_table [] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x6993, + .idProduct = 0xb001, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .driver_info = (kernel_ulong_t)&info_P1K + }, { } }; @@ -842,33 +851,16 @@ static void usb_disconnect(struct usb_interface *intf) usb_cleanup(yld, 0); } -static int usb_match(struct usb_device *udev) -{ - int i; - u16 idVendor = le16_to_cpu(udev->descriptor.idVendor); - u16 idProduct = le16_to_cpu(udev->descriptor.idProduct); - - for (i = 0; i < ARRAY_SIZE(yld_device); i++) { - if ((idVendor == yld_device[i].idVendor) && - (idProduct == yld_device[i].idProduct)) - return i; - } - return -ENODEV; -} - static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev (intf); + struct driver_info *nfo = (struct driver_info *)id->driver_info; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct yealink_dev *yld; struct input_dev *input_dev; int ret, pipe, i; - i = usb_match(udev); - if (i < 0) - return -ENODEV; - interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; if (!(endpoint->bEndpointAddress & USB_DIR_IN)) @@ -915,7 +907,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); if (ret != USB_PKT_LEN) - err("invalid payload size %d, expected %d", ret, USB_PKT_LEN); + err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN); /* initialise irq urb */ usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data, @@ -948,7 +940,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) strlcat(yld->phys, "/input0", sizeof(yld->phys)); /* register settings for the input device */ - input_dev->name = yld_device[i].name; + input_dev->name = nfo->name; input_dev->phys = yld->phys; usb_to_input_id(udev, &input_dev->id); input_dev->cdev.dev = &intf->dev; diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig index 21232ee2974c..0d3d2cc5d7be 100644 --- a/drivers/usb/media/Kconfig +++ b/drivers/usb/media/Kconfig @@ -53,6 +53,21 @@ config USB_DSBR To compile this driver as a module, choose M here: the module will be called dsbr100. +config USB_ET61X251 + tristate "USB ET61X[12]51 PC Camera Controller support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on Etoms ET61X151 + or ET61X251 PC Camera Controllers. + + See <file:Documentation/usb/et61x251.txt> for more informations. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called et61x251. + config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" depends on USB && VIDEO_DEV @@ -209,5 +224,3 @@ config USB_PWC To compile this driver as a module, choose M here: the module will be called pwc. - - diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile index d83adffa925f..3957aa1be0f2 100644 --- a/drivers/usb/media/Makefile +++ b/drivers/usb/media/Makefile @@ -3,9 +3,11 @@ # sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o +et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_DSBR) += dsbr100.o +obj-$(CONFIG_USB_ET61X251) += et61x251.o obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o obj-$(CONFIG_USB_OV511) += ov511.o diff --git a/drivers/usb/media/et61x251.h b/drivers/usb/media/et61x251.h new file mode 100644 index 000000000000..652238f329f3 --- /dev/null +++ b/drivers/usb/media/et61x251.h @@ -0,0 +1,220 @@ +/*************************************************************************** + * V4L2 driver for ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#ifndef _ET61X251_H_ +#define _ET61X251_H_ + +#include <linux/version.h> +#include <linux/usb.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/time.h> +#include <linux/wait.h> +#include <linux/types.h> +#include <linux/param.h> +#include <linux/rwsem.h> +#include <asm/semaphore.h> + +#include "et61x251_sensor.h" + +/*****************************************************************************/ + +#define ET61X251_DEBUG +#define ET61X251_DEBUG_LEVEL 2 +#define ET61X251_MAX_DEVICES 64 +#define ET61X251_PRESERVE_IMGSCALE 0 +#define ET61X251_FORCE_MUNMAP 0 +#define ET61X251_MAX_FRAMES 32 +#define ET61X251_COMPRESSION_QUALITY 0 +#define ET61X251_URBS 2 +#define ET61X251_ISO_PACKETS 7 +#define ET61X251_ALTERNATE_SETTING 13 +#define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS) +#define ET61X251_CTRL_TIMEOUT 100 + +/*****************************************************************************/ + +static const struct usb_device_id et61x251_id_table[] = { + { USB_DEVICE(0x102c, 0x6151), }, + { USB_DEVICE(0x102c, 0x6251), }, + { USB_DEVICE(0x102c, 0x6253), }, + { USB_DEVICE(0x102c, 0x6254), }, + { USB_DEVICE(0x102c, 0x6255), }, + { USB_DEVICE(0x102c, 0x6256), }, + { USB_DEVICE(0x102c, 0x6257), }, + { USB_DEVICE(0x102c, 0x6258), }, + { USB_DEVICE(0x102c, 0x6259), }, + { USB_DEVICE(0x102c, 0x625a), }, + { USB_DEVICE(0x102c, 0x625b), }, + { USB_DEVICE(0x102c, 0x625c), }, + { USB_DEVICE(0x102c, 0x625d), }, + { USB_DEVICE(0x102c, 0x625e), }, + { USB_DEVICE(0x102c, 0x625f), }, + { USB_DEVICE(0x102c, 0x6260), }, + { USB_DEVICE(0x102c, 0x6261), }, + { USB_DEVICE(0x102c, 0x6262), }, + { USB_DEVICE(0x102c, 0x6263), }, + { USB_DEVICE(0x102c, 0x6264), }, + { USB_DEVICE(0x102c, 0x6265), }, + { USB_DEVICE(0x102c, 0x6266), }, + { USB_DEVICE(0x102c, 0x6267), }, + { USB_DEVICE(0x102c, 0x6268), }, + { USB_DEVICE(0x102c, 0x6269), }, + { } +}; + +ET61X251_SENSOR_TABLE + +/*****************************************************************************/ + +enum et61x251_frame_state { + F_UNUSED, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +struct et61x251_frame_t { + void* bufmem; + struct v4l2_buffer buf; + enum et61x251_frame_state state; + struct list_head frame; + unsigned long vma_use_count; +}; + +enum et61x251_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum et61x251_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +enum et61x251_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +struct et61x251_sysfs_attr { + u8 reg, i2c_reg; +}; + +struct et61x251_module_param { + u8 force_munmap; +}; + +static DECLARE_MUTEX(et61x251_sysfs_lock); +static DECLARE_RWSEM(et61x251_disconnect); + +struct et61x251_device { + struct video_device* v4ldev; + + struct et61x251_sensor* sensor; + + struct usb_device* usbdev; + struct urb* urb[ET61X251_URBS]; + void* transfer_buffer[ET61X251_URBS]; + u8* control_buffer; + + struct et61x251_frame_t *frame_current, frame[ET61X251_MAX_FRAMES]; + struct list_head inqueue, outqueue; + u32 frame_count, nbuffers, nreadbuffers; + + enum et61x251_io_method io; + enum et61x251_stream_state stream; + + struct v4l2_jpegcompression compression; + + struct et61x251_sysfs_attr sysfs; + struct et61x251_module_param module_param; + + enum et61x251_dev_state state; + u8 users; + + struct semaphore dev_sem, fileop_sem; + spinlock_t queue_lock; + wait_queue_head_t open, wait_frame, wait_stream; +}; + +/*****************************************************************************/ + +void +et61x251_attach_sensor(struct et61x251_device* cam, + struct et61x251_sensor* sensor) +{ + cam->sensor = sensor; + cam->sensor->usbdev = cam->usbdev; +} + +/*****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef ET61X251_DEBUG +# define DBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1) \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) == 2) \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) >= 3) \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} while (0) +# define KDBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1 || (level) == 2) \ + pr_info("et61x251: " fmt "\n", ## args); \ + else if ((level) == 3) \ + pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) +#else +# define DBG(level, fmt, args...) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ + +#endif /* _ET61X251_H_ */ diff --git a/drivers/usb/media/et61x251_core.c b/drivers/usb/media/et61x251_core.c new file mode 100644 index 000000000000..2c0171a5ad62 --- /dev/null +++ b/drivers/usb/media/et61x251_core.c @@ -0,0 +1,2605 @@ +/*************************************************************************** + * V4L2 driver for ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/param.h> +#include <linux/moduleparam.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/delay.h> +#include <linux/stddef.h> +#include <linux/compiler.h> +#include <linux/ioctl.h> +#include <linux/poll.h> +#include <linux/stat.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/page-flags.h> +#include <linux/byteorder/generic.h> +#include <asm/page.h> +#include <asm/uaccess.h> + +#include "et61x251.h" + +/*****************************************************************************/ + +#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ + "PC Camera Controllers" +#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" +#define ET61X251_MODULE_LICENSE "GPL" +#define ET61X251_MODULE_VERSION "1:1.01" +#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) + +/*****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, et61x251_id_table); + +MODULE_AUTHOR(ET61X251_MODULE_AUTHOR " " ET61X251_AUTHOR_EMAIL); +MODULE_DESCRIPTION(ET61X251_MODULE_NAME); +MODULE_VERSION(ET61X251_MODULE_VERSION); +MODULE_LICENSE(ET61X251_MODULE_LICENSE); + +static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1}; +module_param_array(video_nr, short, NULL, 0444); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] = + ET61X251_FORCE_MUNMAP}; +module_param_array(force_munmap, bool, NULL, 0444); +MODULE_PARM_DESC(force_munmap, + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); + +#ifdef ET61X251_DEBUG +static unsigned short debug = ET61X251_DEBUG_LEVEL; +module_param(debug, ushort, 0644); +MODULE_PARM_DESC(debug, + "\n<n> Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." + "\n"); +#endif + +/*****************************************************************************/ + +static u32 +et61x251_request_buffers(struct et61x251_device* cam, u32 count, + enum et61x251_io_method io) +{ + struct v4l2_pix_format* p = &(cam->sensor->pix_format); + struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); + const size_t imagesize = cam->module_param.force_munmap || + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; + void* buff = NULL; + u32 i; + + if (count > ET61X251_MAX_FRAMES) + count = ET61X251_MAX_FRAMES; + + cam->nbuffers = count; + while (cam->nbuffers > 0) { + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) + break; + cam->nbuffers--; + } + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.index = i; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.length = imagesize; + cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->frame[i].buf.sequence = 0; + cam->frame[i].buf.field = V4L2_FIELD_NONE; + cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; + cam->frame[i].buf.flags = 0; + } + + return cam->nbuffers; +} + + +static void et61x251_release_buffers(struct et61x251_device* cam) +{ + if (cam->nbuffers) { + vfree(cam->frame[0].bufmem); + cam->nbuffers = 0; + } + cam->frame_current = NULL; +} + + +static void et61x251_empty_framequeues(struct et61x251_device* cam) +{ + u32 i; + + INIT_LIST_HEAD(&cam->inqueue); + INIT_LIST_HEAD(&cam->outqueue); + + for (i = 0; i < ET61X251_MAX_FRAMES; i++) { + cam->frame[i].state = F_UNUSED; + cam->frame[i].buf.bytesused = 0; + } +} + + +static void et61x251_requeue_outqueue(struct et61x251_device* cam) +{ + struct et61x251_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + +static void et61x251_queue_unusedframes(struct et61x251_device* cam) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].state == F_UNUSED) { + cam->frame[i].state = F_QUEUED; + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[i].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + } +} + +/*****************************************************************************/ + +int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + *buff = value; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) { + DBG(3, "Failed to write a register (value 0x%02X, index " + "0x%02X, error %d)", value, index, res); + return -1; + } + + return 0; +} + + +int et61x251_read_reg(struct et61x251_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + DBG(3, "Failed to read a register (index 0x%02X, error %d)", + index, res); + + return (res >= 0) ? (int)(*buff) : -1; +} + + +static int +et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) +{ + int i, r; + + for (i = 1; i <= 8; i++) { + if (sensor->interface == ET61X251_I2C_3WIRES) { + r = et61x251_read_reg(cam, 0x8e); + if (!(r & 0x02) && (r >= 0)) + return 0; + } else { + r = et61x251_read_reg(cam, 0x8b); + if (!(r & 0x01) && (r >= 0)) + return 0; + } + if (r < 0) + return -EIO; + udelay(8*8); /* minimum for sensors at 400kHz */ + } + + return -EBUSY; +} + + +int +et61x251_i2c_try_read(struct et61x251_device* cam, + struct et61x251_sensor* sensor, u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor->i2c_slave_id; + data[2] = cam->sensor->rsta | 0x10; + data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C read failed for %s image sensor", sensor->name); + + PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); + + return err ? -1 : (int)data[0]; +} + + +int +et61x251_i2c_try_write(struct et61x251_device* cam, + struct et61x251_sensor* sensor, u8 address, u8 value) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor->i2c_slave_id; + data[2] = cam->sensor->rsta | 0x12; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = value; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + if (err) + DBG(3, "I2C write failed for %s image sensor", sensor->name); + + PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); + + return err ? -1 : 0; +} + + +int +et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, + u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, + u8 data8, u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + if (!cam->sensor) + return -1; + + data[0] = data2; + data[1] = data3; + data[2] = data4; + data[3] = data5; + data[4] = data6; + data[5] = data7; + data[6] = data8; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = address; + data[1] = cam->sensor->i2c_slave_id; + data[2] = cam->sensor->rsta | 0x02 | (n << 4); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + /* Start writing through the serial interface */ + data[0] = data1; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, cam->sensor); + + if (err) + DBG(3, "I2C raw write failed for %s image sensor", + cam->sensor->name); + + PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, " + "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X," + " data6 = 0x%02X, data7 = 0x%02X, data8 = 0x%02X", n, address, + data1, data2, data3, data4, data5, data6, data7, data8); + + return err ? -1 : 0; + +} + + +int et61x251_i2c_read(struct et61x251_device* cam, u8 address) +{ + if (!cam->sensor) + return -1; + + return et61x251_i2c_try_read(cam, cam->sensor, address); +} + + +int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value) +{ + if (!cam->sensor) + return -1; + + return et61x251_i2c_try_write(cam, cam->sensor, address, value); +} + +/*****************************************************************************/ + +static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) +{ + struct et61x251_device* cam = urb->context; + struct et61x251_frame_t** f; + size_t imagesize; + u8 i; + int err = 0; + + if (urb->status == -ENOENT) + return; + + f = &cam->frame_current; + + if (cam->stream == STREAM_INTERRUPT) { + cam->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + DBG(3, "Stream interrupted"); + wake_up_interruptible(&cam->wait_stream); + } + + if (cam->state & DEV_DISCONNECTED) + return; + + if (cam->state & DEV_MISCONFIGURED) { + wake_up_interruptible(&cam->wait_frame); + return; + } + + if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) + goto resubmit_urb; + + if (!(*f)) + (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, + frame); + + imagesize = (cam->sensor->pix_format.width * + cam->sensor->pix_format.height * + cam->sensor->pix_format.priv) / 8; + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int len, status; + void *pos; + u8* b1, * b2, sof; + const u8 VOID_BYTES = 6; + size_t imglen; + + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status) { + DBG(3, "Error in isochronous frame"); + (*f)->state = F_ERROR; + continue; + } + + b1 = pos++; + b2 = pos++; + sof = ((*b1 & 0x3f) == 63); + imglen = ((*b1 & 0xc0) << 2) | *b2; + + PDBGG("Isochrnous frame: length %u, #%u i, image length %zu", + len, i, imglen); + + if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) +start_of_frame: + if (sof) { + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + do_gettimeofday(&(*f)->buf.timestamp); + pos += 22; + DBG(3, "SOF detected: new video frame"); + } + + if ((*f)->state == F_GRABBING) { + if (sof && (*f)->buf.bytesused) { + if (cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_ET61X251) + goto end_of_frame; + else { + DBG(3, "Not expected SOF detected " + "after %lu bytes", + (unsigned long)(*f)->buf.bytesused); + (*f)->state = F_ERROR; + continue; + } + } + + if ((*f)->buf.bytesused + imglen > imagesize) { + DBG(3, "Video frame size exceeded"); + (*f)->state = F_ERROR; + continue; + } + + pos += VOID_BYTES; + + memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, imglen); + (*f)->buf.bytesused += imglen; + + if ((*f)->buf.bytesused == imagesize) { + u32 b; +end_of_frame: + b = (*f)->buf.bytesused; + (*f)->state = F_DONE; + (*f)->buf.sequence= ++cam->frame_count; + spin_lock(&cam->queue_lock); + list_move_tail(&(*f)->frame, &cam->outqueue); + if (!list_empty(&cam->inqueue)) + (*f) = list_entry(cam->inqueue.next, + struct et61x251_frame_t, + frame); + else + (*f) = NULL; + spin_unlock(&cam->queue_lock); + DBG(3, "Video frame captured: : %lu bytes", + (unsigned long)(b)); + + if (!(*f)) + goto resubmit_urb; + + if (sof && + cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_ET61X251) + goto start_of_frame; + } + } + } + +resubmit_urb: + urb->dev = cam->usbdev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0 && err != -EPERM) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "usb_submit_urb() failed"); + } + + wake_up_interruptible(&cam->wait_frame); +} + + +static int et61x251_start_transfer(struct et61x251_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, + 864, 896, 920, 956, 980, 1000, + 1022}; + const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; + s8 i, j; + int err = 0; + + for (i = 0; i < ET61X251_URBS; i++) { + cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, + GFP_KERNEL); + if (!cam->transfer_buffer[i]) { + err = -ENOMEM; + DBG(1, "Not enough memory"); + goto free_buffers; + } + } + + for (i = 0; i < ET61X251_URBS; i++) { + urb = usb_alloc_urb(ET61X251_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + err = -ENOMEM; + DBG(1, "usb_alloc_urb() failed"); + goto free_urbs; + } + urb->dev = udev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = ET61X251_ISO_PACKETS; + urb->complete = et61x251_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < ET61X251_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = psz * j; + urb->iso_frame_desc[j].length = psz; + } + } + + err = et61x251_write_reg(cam, 0x01, 0x03); + err = et61x251_write_reg(cam, 0x00, 0x03); + err = et61x251_write_reg(cam, 0x08, 0x03); + if (err) { + err = -EIO; + DBG(1, "I/O hardware error"); + goto free_urbs; + } + + err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING); + if (err) { + DBG(1, "usb_set_interface() failed"); + goto free_urbs; + } + + cam->frame_current = NULL; + + for (i = 0; i < ET61X251_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + for (j = i-1; j >= 0; j--) + usb_kill_urb(cam->urb[j]); + DBG(1, "usb_submit_urb() failed, error %d", err); + goto free_urbs; + } + } + + return 0; + +free_urbs: + for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) + usb_free_urb(cam->urb[i]); + +free_buffers: + for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++) + kfree(cam->transfer_buffer[i]); + + return err; +} + + +static int et61x251_stop_transfer(struct et61x251_device* cam) +{ + struct usb_device *udev = cam->usbdev; + s8 i; + int err = 0; + + if (cam->state & DEV_DISCONNECTED) + return 0; + + for (i = ET61X251_URBS-1; i >= 0; i--) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + kfree(cam->transfer_buffer[i]); + } + + err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + if (err) + DBG(3, "usb_set_interface() failed"); + + return err; +} + + +static int et61x251_stream_interrupt(struct et61x251_device* cam) +{ + int err = 0; + + cam->stream = STREAM_INTERRUPT; + err = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ET61X251_URB_TIMEOUT); + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + else if (err) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "URB timeout reached. The camera is misconfigured. To " + "use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return err; + } + + return 0; +} + +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) +{ + char str[5]; + char* endp; + unsigned long val; + + if (len < 4) { + strncpy(str, buff, len); + str[len+1] = '\0'; + } else { + strncpy(str, buff, 4); + str[4] = '\0'; + } + + val = simple_strtoul(str, &endp, 0); + + *count = 0; + if (val <= 0xff) + *count = (ssize_t)(endp - str); + if ((*count) && (len == *count+1) && (buff[*count] == '\n')) + *count += 1; + + return (u8)val; +} + +/* + NOTE 1: being inside one of the following methods implies that the v4l + device exists for sure (see kobjects and reference counters) + NOTE 2: buffers are PAGE_SIZE long +*/ + +static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.reg); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 index; + ssize_t count; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + index = et61x251_strtou8(buf, len, &count); + if (index > 0x8e || !count) { + up(&et61x251_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.reg = index; + + DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); + DBG(3, "Written bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_val(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + int val; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { + up(&et61x251_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_val(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 value; + ssize_t count; + int err; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + value = et61x251_strtou8(buf, len, &count); + if (!count) { + up(&et61x251_sysfs_lock); + return -EINVAL; + } + + err = et61x251_write_reg(cam, value, cam->sysfs.reg); + if (err) { + up(&et61x251_sysfs_lock); + return -EIO; + } + + DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X", + cam->sysfs.reg, value); + DBG(3, "Written bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); + + DBG(3, "Read bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 index; + ssize_t count; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + index = et61x251_strtou8(buf, len, &count); + if (!count) { + up(&et61x251_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.i2c_reg = index; + + DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); + DBG(3, "Written bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + int val; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { + up(&et61x251_sysfs_lock); + return -ENOSYS; + } + + if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { + up(&et61x251_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 value; + ssize_t count; + int err; + + if (down_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&et61x251_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { + up(&et61x251_sysfs_lock); + return -ENOSYS; + } + + value = et61x251_strtou8(buf, len, &count); + if (!count) { + up(&et61x251_sysfs_lock); + return -EINVAL; + } + + err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); + if (err) { + up(&et61x251_sysfs_lock); + return -EIO; + } + + DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", + cam->sysfs.i2c_reg, value); + DBG(3, "Written bytes: %zd", count); + + up(&et61x251_sysfs_lock); + + return count; +} + + +static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, + et61x251_show_reg, et61x251_store_reg); +static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, + et61x251_show_val, et61x251_store_val); +static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, + et61x251_show_i2c_reg, et61x251_store_i2c_reg); +static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, + et61x251_show_i2c_val, et61x251_store_i2c_val); + + +static void et61x251_create_sysfs(struct et61x251_device* cam) +{ + struct video_device *v4ldev = cam->v4ldev; + + video_device_create_file(v4ldev, &class_device_attr_reg); + video_device_create_file(v4ldev, &class_device_attr_val); + if (cam->sensor && cam->sensor->sysfs_ops) { + video_device_create_file(v4ldev, &class_device_attr_i2c_reg); + video_device_create_file(v4ldev, &class_device_attr_i2c_val); + } +} +#endif /* CONFIG_VIDEO_ADV_DEBUG */ + +/*****************************************************************************/ + +static int +et61x251_set_pix_format(struct et61x251_device* cam, + struct v4l2_pix_format* pix) +{ + int r, err = 0; + + if ((r = et61x251_read_reg(cam, 0x12)) < 0) + err += r; + if (pix->pixelformat == V4L2_PIX_FMT_ET61X251) + err += et61x251_write_reg(cam, r & 0xfd, 0x12); + else + err += et61x251_write_reg(cam, r | 0x02, 0x12); + + return err ? -EIO : 0; +} + + +static int +et61x251_set_compression(struct et61x251_device* cam, + struct v4l2_jpegcompression* compression) +{ + int r, err = 0; + + if ((r = et61x251_read_reg(cam, 0x12)) < 0) + err += r; + if (compression->quality == 0) + err += et61x251_write_reg(cam, r & 0xfb, 0x12); + else + err += et61x251_write_reg(cam, r | 0x04, 0x12); + + return err ? -EIO : 0; +} + + +static int et61x251_set_scale(struct et61x251_device* cam, u8 scale) +{ + int r = 0, err = 0; + + r = et61x251_read_reg(cam, 0x12); + if (r < 0) + err += r; + + if (scale == 1) + err += et61x251_write_reg(cam, r & ~0x01, 0x12); + else if (scale == 2) + err += et61x251_write_reg(cam, r | 0x01, 0x12); + + if (err) + return -EIO; + + PDBGG("Scaling factor: %u", scale); + + return 0; +} + + +static int +et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) +{ + struct et61x251_sensor* s = cam->sensor; + u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + + s->active_pixel.left), + fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + + s->active_pixel.top), + fmw_length = (u16)(rect->width), + fmw_height = (u16)(rect->height); + int err = 0; + + err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69); + err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a); + err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b); + err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c); + err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6) + | ((fmw_length & 0x300) >> 4) + | ((fmw_height & 0x300) >> 2), 0x6d); + if (err) + return -EIO; + + PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u", + fmw_sx, fmw_sy, fmw_length, fmw_height); + + return 0; +} + + +static int et61x251_init(struct et61x251_device* cam) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_control ctrl; + struct v4l2_queryctrl *qctrl; + struct v4l2_rect* rect; + u8 i = 0; + int err = 0; + + if (!(cam->state & DEV_INITIALIZED)) { + init_waitqueue_head(&cam->open); + qctrl = s->qctrl; + rect = &(s->cropcap.defrect); + cam->compression.quality = ET61X251_COMPRESSION_QUALITY; + } else { /* use current values */ + qctrl = s->_qctrl; + rect = &(s->_rect); + } + + err += et61x251_set_scale(cam, rect->width / s->pix_format.width); + err += et61x251_set_crop(cam, rect); + if (err) + return err; + + if (s->init) { + err = s->init(cam); + if (err) { + DBG(3, "Sensor initialization failed"); + return err; + } + } + + err += et61x251_set_compression(cam, &cam->compression); + err += et61x251_set_pix_format(cam, &s->pix_format); + if (s->set_pix_format) + err += s->set_pix_format(cam, &s->pix_format); + if (err) + return err; + + if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251) + DBG(3, "Compressed video format is active, quality %d", + cam->compression.quality); + else + DBG(3, "Uncompressed video format is active"); + + if (s->set_crop) + if ((err = s->set_crop(cam, rect))) { + DBG(3, "set_crop() failed"); + return err; + } + + if (s->set_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (s->qctrl[i].id != 0 && + !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { + ctrl.id = s->qctrl[i].id; + ctrl.value = qctrl[i].default_value; + err = s->set_ctrl(cam, &ctrl); + if (err) { + DBG(3, "Set %s control failed", + s->qctrl[i].name); + return err; + } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name); + } + } + + if (!(cam->state & DEV_INITIALIZED)) { + init_MUTEX(&cam->fileop_sem); + spin_lock_init(&cam->queue_lock); + init_waitqueue_head(&cam->wait_frame); + init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; + memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); + memcpy(&(s->_rect), &(s->cropcap.defrect), + sizeof(struct v4l2_rect)); + cam->state |= DEV_INITIALIZED; + } + + DBG(2, "Initialization succeeded"); + return 0; +} + + +static void et61x251_release_resources(struct et61x251_device* cam) +{ + down(&et61x251_sysfs_lock); + + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + video_set_drvdata(cam->v4ldev, NULL); + video_unregister_device(cam->v4ldev); + + up(&et61x251_sysfs_lock); + + kfree(cam->control_buffer); +} + +/*****************************************************************************/ + +static int et61x251_open(struct inode* inode, struct file* filp) +{ + struct et61x251_device* cam; + int err = 0; + + /* + This is the only safe way to prevent race conditions with + disconnect + */ + if (!down_read_trylock(&et61x251_disconnect)) + return -ERESTARTSYS; + + cam = video_get_drvdata(video_devdata(filp)); + + if (down_interruptible(&cam->dev_sem)) { + up_read(&et61x251_disconnect); + return -ERESTARTSYS; + } + + if (cam->users) { + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + if ((filp->f_flags & O_NONBLOCK) || + (filp->f_flags & O_NDELAY)) { + err = -EWOULDBLOCK; + goto out; + } + up(&cam->dev_sem); + err = wait_event_interruptible_exclusive(cam->open, + cam->state & DEV_DISCONNECTED + || !cam->users); + if (err) { + up_read(&et61x251_disconnect); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up_read(&et61x251_disconnect); + return -ENODEV; + } + down(&cam->dev_sem); + } + + + if (cam->state & DEV_MISCONFIGURED) { + err = et61x251_init(cam); + if (err) { + DBG(1, "Initialization failed again. " + "I will retry on next open()."); + goto out; + } + cam->state &= ~DEV_MISCONFIGURED; + } + + if ((err = et61x251_start_transfer(cam))) + goto out; + + filp->private_data = cam; + cam->users++; + cam->io = IO_NONE; + cam->stream = STREAM_OFF; + cam->nbuffers = 0; + cam->frame_count = 0; + et61x251_empty_framequeues(cam); + + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + +out: + up(&cam->dev_sem); + up_read(&et61x251_disconnect); + return err; +} + + +static int et61x251_release(struct inode* inode, struct file* filp) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + + down(&cam->dev_sem); /* prevent disconnect() to be called */ + + et61x251_stop_transfer(cam); + + et61x251_release_buffers(cam); + + if (cam->state & DEV_DISCONNECTED) { + et61x251_release_resources(cam); + up(&cam->dev_sem); + kfree(cam); + return 0; + } + + cam->users--; + wake_up_interruptible_nr(&cam->open, 1); + + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + + up(&cam->dev_sem); + + return 0; +} + + +static ssize_t +et61x251_read(struct file* filp, char __user * buf, + size_t count, loff_t* f_pos) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_frame_t* f, * i; + unsigned long lock_flags; + int err = 0; + + if (down_interruptible(&cam->fileop_sem)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + up(&cam->fileop_sem); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + up(&cam->fileop_sem); + return -EIO; + } + + if (cam->io == IO_MMAP) { + DBG(3, "Close and open the device again to choose the read " + "method"); + up(&cam->fileop_sem); + return -EINVAL; + } + + if (cam->io == IO_NONE) { + if (!et61x251_request_buffers(cam, cam->nreadbuffers, + IO_READ)) { + DBG(1, "read() failed, not enough memory"); + up(&cam->fileop_sem); + return -ENOMEM; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + et61x251_empty_framequeues(cam); + et61x251_queue_unusedframes(cam); + } + + if (!count) { + up(&cam->fileop_sem); + return 0; + } + + if (list_empty(&cam->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + up(&cam->fileop_sem); + return -EAGAIN; + } + err = wait_event_interruptible + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED) ); + if (err) { + up(&cam->fileop_sem); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up(&cam->fileop_sem); + return -ENODEV; + } + if (cam->state & DEV_MISCONFIGURED) { + up(&cam->fileop_sem); + return -EIO; + } + } + + f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame); + + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(i, &cam->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + et61x251_queue_unusedframes(cam); + + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); + + up(&cam->fileop_sem); + + return err ? err : count; +} + + +static unsigned int et61x251_poll(struct file *filp, poll_table *wait) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_frame_t* f; + unsigned long lock_flags; + unsigned int mask = 0; + + if (down_interruptible(&cam->fileop_sem)) + return POLLERR; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + goto error; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + goto error; + } + + if (cam->io == IO_NONE) { + if (!et61x251_request_buffers(cam, cam->nreadbuffers, + IO_READ)) { + DBG(1, "poll() failed, not enough memory"); + goto error; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + et61x251_queue_unusedframes(cam); + } + + poll_wait(filp, &cam->wait_frame, wait); + + if (!list_empty(&cam->outqueue)) + mask |= POLLIN | POLLRDNORM; + + up(&cam->fileop_sem); + + return mask; + +error: + up(&cam->fileop_sem); + return POLLERR; +} + + +static void et61x251_vm_open(struct vm_area_struct* vma) +{ + struct et61x251_frame_t* f = vma->vm_private_data; + f->vma_use_count++; +} + + +static void et61x251_vm_close(struct vm_area_struct* vma) +{ + /* NOTE: buffers are not freed here */ + struct et61x251_frame_t* f = vma->vm_private_data; + f->vma_use_count--; +} + + +static struct vm_operations_struct et61x251_vm_ops = { + .open = et61x251_vm_open, + .close = et61x251_vm_close, +}; + + +static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start; + void *pos; + u32 i; + + if (down_interruptible(&cam->fileop_sem)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + up(&cam->fileop_sem); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + up(&cam->fileop_sem); + return -EIO; + } + + if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(cam->frame[0].buf.length)) { + up(&cam->fileop_sem); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) { + if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == cam->nbuffers) { + up(&cam->fileop_sem); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + pos = cam->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { + up(&cam->fileop_sem); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &et61x251_vm_ops; + vma->vm_private_data = &cam->frame[i]; + + et61x251_vm_open(vma); + + up(&cam->fileop_sem); + + return 0; +} + +/*****************************************************************************/ + +static int +et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_capability cap = { + .driver = "et61x251", + .version = ET61X251_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_input i; + + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; + + if (i.index) + return -EINVAL; + + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); + + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg) +{ + int index; + + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; + + if (index != 0) + return -EINVAL; + + return 0; +} + + +static int +et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; + } + return -EINVAL; + } else + err = s->get_ctrl(cam, &ctrl); + +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; + + return err; +} + + +static int +et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; + + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + return 0; +} + + +static int +et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_pix_format* pix_format = &(s->pix_format); + u8 scale; + const enum et61x251_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + /* Preserve R,G or B origin */ + rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; + rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; + + if (rect->width < 4) + rect->width = 4; + if (rect->height < 4) + rect->height = 4; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + + rect->width &= ~3L; + rect->height &= ~3L; + + if (ET61X251_PRESERVE_IMGSCALE) { + /* Calculate the actual scaling factor */ + u32 a, b; + a = rect->width * rect->height; + b = pix_format->width * pix_format->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } else + scale = 1; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + et61x251_release_buffers(cam); + + err = et61x251_set_crop(cam, rect); + if (s->set_crop) + err += s->set_crop(cam, rect); + err += et61x251_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + s->pix_format.width = rect->width/scale; + s->pix_format.height = rect->height/scale; + memcpy(&(s->_rect), rect, sizeof(*rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + et61x251_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + et61x251_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; + + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; + + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_ET61X251; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; + + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, + void __user * arg) +{ + struct et61x251_sensor* s = cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + u8 scale; + const enum et61x251_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + pix = &(format.fmt.pix); + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memcpy(&rect, &(s->_rect), sizeof(rect)); + + { /* calculate the actual scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } + + rect.width = scale * pix->width; + rect.height = scale * pix->height; + + if (rect.width < 4) + rect.width = 4; + if (rect.height < 4) + rect.height = 4; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; + + rect.width &= ~3L; + rect.height &= ~3L; + + { /* adjust the scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } + + pix->width = rect.width / scale; + pix->height = rect.height / scale; + + if (pix->pixelformat != V4L2_PIX_FMT_ET61X251 && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; /* bpp */ + pix->colorspace = pfmt->colorspace; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + return 0; + } + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + et61x251_release_buffers(cam); + + err += et61x251_set_pix_format(cam, pix); + err += et61x251_set_crop(cam, &rect); + if (s->set_pix_format) + err += s->set_pix_format(cam, pix); + if (s->set_crop) + err += s->set_crop(cam, &rect); + err += et61x251_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + et61x251_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + et61x251_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum et61x251_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + err += et61x251_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; + + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; + + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. " + "Previous buffers are still mapped."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + et61x251_empty_framequeues(cam); + + et61x251_release_buffers(cam); + if (rb.count) + rb.count = et61x251_request_buffers(cam, rb.count, IO_MMAP); + + if (copy_to_user(arg, &rb, sizeof(rb))) { + et61x251_release_buffers(cam); + cam->io = IO_NONE; + return -EFAULT; + } + + cam->io = rb.count ? IO_MMAP : IO_NONE; + + return 0; +} + + +static int +et61x251_vidioc_querybuf(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; + + cam->frame[b.index].state = F_QUEUED; + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + PDBGG("Frame #%lu queued", (unsigned long)b.index); + + return 0; +} + + +static int +et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct et61x251_frame_t *f; + unsigned long lock_flags; + int err = 0; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + err = wait_event_interruptible + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED) ); + if (err) + return err; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (cam->state & DEV_MISCONFIGURED) + return -EIO; + } + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct et61x251_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + f->state = F_UNUSED; + + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); + + return 0; +} + + +static int +et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg) +{ + int type; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->inqueue)) + return -EINVAL; + + cam->stream = STREAM_ON; + + DBG(3, "Stream on"); + + return 0; +} + + +static int +et61x251_vidioc_streamoff(struct et61x251_device* cam, void __user * arg) +{ + int type, err; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + et61x251_empty_framequeues(cam); + + DBG(3, "Stream off"); + + return 0; +} + + +static int +et61x251_vidioc_g_parm(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > ET61X251_MAX_FRAMES) + sp.parm.capture.readbuffers = ET61X251_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; +} + + +static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return et61x251_vidioc_querycap(cam, arg); + + case VIDIOC_ENUMINPUT: + return et61x251_vidioc_enuminput(cam, arg); + + case VIDIOC_G_INPUT: + case VIDIOC_S_INPUT: + return et61x251_vidioc_gs_input(cam, arg); + + case VIDIOC_QUERYCTRL: + return et61x251_vidioc_query_ctrl(cam, arg); + + case VIDIOC_G_CTRL: + return et61x251_vidioc_g_ctrl(cam, arg); + + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return et61x251_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return et61x251_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return et61x251_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return et61x251_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return et61x251_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return et61x251_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return et61x251_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return et61x251_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return et61x251_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return et61x251_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return et61x251_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return et61x251_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return et61x251_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return et61x251_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return et61x251_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return et61x251_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return et61x251_vidioc_s_parm(cam, arg); + + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYMENU: + return -EINVAL; + + default: + return -EINVAL; + + } +} + + +static int et61x251_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + int err = 0; + + if (down_interruptible(&cam->fileop_sem)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + up(&cam->fileop_sem); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + up(&cam->fileop_sem); + return -EIO; + } + + V4LDBG(3, "et61x251", cmd); + + err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + + up(&cam->fileop_sem); + + return err; +} + + +static struct file_operations et61x251_fops = { + .owner = THIS_MODULE, + .open = et61x251_open, + .release = et61x251_release, + .ioctl = et61x251_ioctl, + .read = et61x251_read, + .poll = et61x251_poll, + .mmap = et61x251_mmap, + .llseek = no_llseek, +}; + +/*****************************************************************************/ + +/* It exists a single interface only. We do not need to validate anything. */ +static int +et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct et61x251_device* cam; + static unsigned int dev_nr = 0; + unsigned int i; + int err = 0; + + if (!(cam = kzalloc(sizeof(struct et61x251_device), GFP_KERNEL))) + return -ENOMEM; + + cam->usbdev = udev; + + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); + err = -ENOMEM; + goto fail; + } + + if (!(cam->v4ldev = video_device_alloc())) { + DBG(1, "video_device_alloc() failed"); + err = -ENOMEM; + goto fail; + } + + init_MUTEX(&cam->dev_sem); + + DBG(2, "ET61X[12]51 PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); + + for (i = 0; et61x251_sensor_table[i]; i++) { + err = et61x251_sensor_table[i](cam); + if (!err) + break; + } + + if (!err && cam->sensor) + DBG(2, "%s image sensor detected", cam->sensor->name); + else { + DBG(1, "No supported image sensor detected"); + err = -ENODEV; + goto fail; + } + + if (et61x251_init(cam)) { + DBG(1, "Initialization failed. I will retry on open()."); + cam->state |= DEV_MISCONFIGURED; + } + + strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = 0; + cam->v4ldev->fops = &et61x251_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + + down(&cam->dev_sem); + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L2 device registration failed"); + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(1, "Free /dev/videoX node not found"); + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; + up(&cam->dev_sem); + goto fail; + } + + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + + cam->module_param.force_munmap = force_munmap[dev_nr]; + + dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + et61x251_create_sysfs(cam); + DBG(2, "Optional device control through 'sysfs' interface ready"); +#endif + + usb_set_intfdata(intf, cam); + + up(&cam->dev_sem); + + return 0; + +fail: + if (cam) { + kfree(cam->control_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + kfree(cam); + } + return err; +} + + +static void et61x251_usb_disconnect(struct usb_interface* intf) +{ + struct et61x251_device* cam = usb_get_intfdata(intf); + + if (!cam) + return; + + down_write(&et61x251_disconnect); + + down(&cam->dev_sem); + + DBG(2, "Disconnecting %s...", cam->v4ldev->name); + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "Device /dev/video%d is open! Deregistration and " + "memory deallocation are deferred on close.", + cam->v4ldev->minor); + cam->state |= DEV_MISCONFIGURED; + et61x251_stop_transfer(cam); + cam->state |= DEV_DISCONNECTED; + wake_up_interruptible(&cam->wait_frame); + wake_up_interruptible(&cam->wait_stream); + } else { + cam->state |= DEV_DISCONNECTED; + et61x251_release_resources(cam); + } + + up(&cam->dev_sem); + + if (!cam->users) + kfree(cam); + + up_write(&et61x251_disconnect); +} + + +static struct usb_driver et61x251_usb_driver = { + .name = "et61x251", + .id_table = et61x251_id_table, + .probe = et61x251_usb_probe, + .disconnect = et61x251_usb_disconnect, +}; + +/*****************************************************************************/ + +static int __init et61x251_module_init(void) +{ + int err = 0; + + KDBG(2, ET61X251_MODULE_NAME " v" ET61X251_MODULE_VERSION); + KDBG(3, ET61X251_MODULE_AUTHOR); + + if ((err = usb_register(&et61x251_usb_driver))) + KDBG(1, "usb_register() failed"); + + return err; +} + + +static void __exit et61x251_module_exit(void) +{ + usb_deregister(&et61x251_usb_driver); +} + + +module_init(et61x251_module_init); +module_exit(et61x251_module_exit); diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/usb/media/et61x251_sensor.h new file mode 100644 index 000000000000..b9df91062fc0 --- /dev/null +++ b/drivers/usb/media/et61x251_sensor.h @@ -0,0 +1,115 @@ +/*************************************************************************** + * API for image sensors connected to ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#ifndef _ET61X251_SENSOR_H_ +#define _ET61X251_SENSOR_H_ + +#include <linux/usb.h> +#include <linux/videodev.h> +#include <linux/device.h> +#include <linux/stddef.h> +#include <linux/errno.h> +#include <asm/types.h> + +struct et61x251_device; +struct et61x251_sensor; + +/*****************************************************************************/ + +extern int et61x251_probe_tas5130d1b(struct et61x251_device* cam); + +#define ET61X251_SENSOR_TABLE \ +/* Weak detections must go at the end of the list */ \ +static int (*et61x251_sensor_table[])(struct et61x251_device*) = { \ + &et61x251_probe_tas5130d1b, \ + NULL, \ +}; + +extern void +et61x251_attach_sensor(struct et61x251_device* cam, + struct et61x251_sensor* sensor); + +/*****************************************************************************/ + +extern int et61x251_write_reg(struct et61x251_device*, u8 value, u16 index); +extern int et61x251_read_reg(struct et61x251_device*, u16 index); +extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); +extern int et61x251_i2c_read(struct et61x251_device*, u8 address); +extern int et61x251_i2c_try_write(struct et61x251_device*, + struct et61x251_sensor*, u8 address, + u8 value); +extern int et61x251_i2c_try_read(struct et61x251_device*, + struct et61x251_sensor*, u8 address); +extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, + u8 data2, u8 data3, u8 data4, u8 data5, + u8 data6, u8 data7, u8 data8, u8 address); + +/*****************************************************************************/ + +enum et61x251_i2c_sysfs_ops { + ET61X251_I2C_READ = 0x01, + ET61X251_I2C_WRITE = 0x02, +}; + +enum et61x251_i2c_interface { + ET61X251_I2C_2WIRES, + ET61X251_I2C_3WIRES, +}; + +/* Repeat start condition when RSTA is high */ +enum et61x251_i2c_rsta { + ET61X251_I2C_RSTA_STOP = 0x00, /* stop then start */ + ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ +}; + +#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 + +struct et61x251_sensor { + char name[32]; + + enum et61x251_i2c_sysfs_ops sysfs_ops; + + enum et61x251_i2c_interface interface; + u8 i2c_slave_id; + enum et61x251_i2c_rsta rsta; + struct v4l2_rect active_pixel; /* left and top define FVSX and FVSY */ + + struct v4l2_queryctrl qctrl[ET61X251_MAX_CTRLS]; + struct v4l2_cropcap cropcap; + struct v4l2_pix_format pix_format; + + int (*init)(struct et61x251_device* cam); + int (*get_ctrl)(struct et61x251_device* cam, + struct v4l2_control* ctrl); + int (*set_ctrl)(struct et61x251_device* cam, + const struct v4l2_control* ctrl); + int (*set_crop)(struct et61x251_device* cam, + const struct v4l2_rect* rect); + int (*set_pix_format)(struct et61x251_device* cam, + const struct v4l2_pix_format* pix); + + const struct usb_device* usbdev; + + /* Private */ + struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; + struct v4l2_rect _rect; +}; + +#endif /* _ET61X251_SENSOR_H_ */ diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/usb/media/et61x251_tas5130d1b.c new file mode 100644 index 000000000000..65f1ae9cf2b3 --- /dev/null +++ b/drivers/usb/media/et61x251_tas5130d1b.c @@ -0,0 +1,137 @@ +/*************************************************************************** + * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * + * PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include "et61x251_sensor.h" + + +static int tas5130d1b_init(struct et61x251_device* cam) +{ + int err = 0; + + err += et61x251_write_reg(cam, 0x14, 0x01); + err += et61x251_write_reg(cam, 0x1b, 0x02); + err += et61x251_write_reg(cam, 0x02, 0x12); + err += et61x251_write_reg(cam, 0x0e, 0x60); + err += et61x251_write_reg(cam, 0x80, 0x61); + err += et61x251_write_reg(cam, 0xf0, 0x62); + err += et61x251_write_reg(cam, 0x03, 0x63); + err += et61x251_write_reg(cam, 0x14, 0x64); + err += et61x251_write_reg(cam, 0xf4, 0x65); + err += et61x251_write_reg(cam, 0x01, 0x66); + err += et61x251_write_reg(cam, 0x05, 0x67); + err += et61x251_write_reg(cam, 0x8f, 0x68); + err += et61x251_write_reg(cam, 0x0f, 0x8d); + err += et61x251_write_reg(cam, 0x08, 0x8e); + + return err; +} + + +static int tas5130d1b_set_ctrl(struct et61x251_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += et61x251_i2c_raw_write(cam, 2, 0x20, + 0xf6-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); + break; + case V4L2_CID_EXPOSURE: + err += et61x251_i2c_raw_write(cam, 2, 0x40, + 0x47-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static struct et61x251_sensor tas5130d1b = { + .name = "TAS5130D1B", + .interface = ET61X251_I2C_3WIRES, + .rsta = ET61X251_I2C_RSTA_STOP, + .active_pixel = { + .left = 106, + .top = 13, + }, + .init = &tas5130d1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x02, + .default_value = 0x0d, + .flags = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x47, + .step = 0x01, + .default_value = 0x23, + .flags = 0, + }, + }, + .set_ctrl = &tas5130d1b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, +}; + + +int et61x251_probe_tas5130d1b(struct et61x251_device* cam) +{ + /* This sensor has no identifiers, so let's attach it anyway */ + et61x251_attach_sensor(cam, &tas5130d1b); + + /* Sensor detection is based on USB pid/vid */ + if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251) + return -ENODEV; + + return 0; +} diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 8af665bbe330..51e9cc06f7e3 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -204,22 +204,10 @@ MODULE_LICENSE("GPL"); static struct usb_driver ov511_driver; -static struct ov51x_decomp_ops *ov511_decomp_ops; -static struct ov51x_decomp_ops *ov511_mmx_decomp_ops; -static struct ov51x_decomp_ops *ov518_decomp_ops; -static struct ov51x_decomp_ops *ov518_mmx_decomp_ops; - /* Number of times to retry a failed I2C transaction. Increase this if you * are getting "Failed to read sensor ID..." */ static const int i2c_detect_tries = 5; -/* MMX support is present in kernel and CPU. Checked upon decomp module load. */ -#if defined(__i386__) || defined(__x86_64__) -#define ov51x_mmx_available (cpu_has_mmx) -#else -#define ov51x_mmx_available (0) -#endif - static struct usb_device_id device_table [] = { { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, @@ -3012,93 +3000,18 @@ yuv420raw_to_yuv420p(struct ov511_frame *frame, * **********************************************************************/ -/* Chooses a decompression module, locks it, and sets ov->decomp_ops - * accordingly. Returns -ENXIO if decompressor is not available, otherwise - * returns 0 if no other error. - */ static int request_decompressor(struct usb_ov511 *ov) { - if (!ov) - return -ENODEV; - - if (ov->decomp_ops) { - err("ERROR: Decompressor already requested!"); - return -EINVAL; - } - - lock_kernel(); - - /* Try to get MMX, and fall back on no-MMX if necessary */ - if (ov->bclass == BCL_OV511) { - if (ov511_mmx_decomp_ops) { - PDEBUG(3, "Using OV511 MMX decompressor"); - ov->decomp_ops = ov511_mmx_decomp_ops; - } else if (ov511_decomp_ops) { - PDEBUG(3, "Using OV511 decompressor"); - ov->decomp_ops = ov511_decomp_ops; - } else { - err("No decompressor available"); - } - } else if (ov->bclass == BCL_OV518) { - if (ov518_mmx_decomp_ops) { - PDEBUG(3, "Using OV518 MMX decompressor"); - ov->decomp_ops = ov518_mmx_decomp_ops; - } else if (ov518_decomp_ops) { - PDEBUG(3, "Using OV518 decompressor"); - ov->decomp_ops = ov518_decomp_ops; - } else { - err("No decompressor available"); - } + if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) { + err("No decompressor available"); } else { err("Unknown bridge"); } - if (!ov->decomp_ops) - goto nosys; - - if (!ov->decomp_ops->owner) { - ov->decomp_ops = NULL; - goto nosys; - } - - if (!try_module_get(ov->decomp_ops->owner)) - goto nosys; - - unlock_kernel(); - return 0; - - nosys: - unlock_kernel(); return -ENOSYS; } -/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even - * if ov->decomp_ops is NULL. - */ -static void -release_decompressor(struct usb_ov511 *ov) -{ - int released = 0; /* Did we actually do anything? */ - - if (!ov) - return; - - lock_kernel(); - - if (ov->decomp_ops) { - module_put(ov->decomp_ops->owner); - released = 1; - } - - ov->decomp_ops = NULL; - - unlock_kernel(); - - if (released) - PDEBUG(3, "Decompressor released"); -} - static void decompress(struct usb_ov511 *ov, struct ov511_frame *frame, unsigned char *pIn0, unsigned char *pOut0) @@ -3107,31 +3020,6 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame, if (request_decompressor(ov)) return; - PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd); - - if (frame->format == VIDEO_PALETTE_GREY - && ov->decomp_ops->decomp_400) { - int ret = ov->decomp_ops->decomp_400( - pIn0, - pOut0, - frame->compbuf, - frame->rawwidth, - frame->rawheight, - frame->bytes_recvd); - PDEBUG(4, "DEBUG: decomp_400 returned %d", ret); - } else if (frame->format != VIDEO_PALETTE_GREY - && ov->decomp_ops->decomp_420) { - int ret = ov->decomp_ops->decomp_420( - pIn0, - pOut0, - frame->compbuf, - frame->rawwidth, - frame->rawheight, - frame->bytes_recvd); - PDEBUG(4, "DEBUG: decomp_420 returned %d", ret); - } else { - err("Decompressor does not support this format"); - } } /********************************************************************** @@ -4087,8 +3975,6 @@ ov51x_v4l1_close(struct inode *inode, struct file *file) ov->user--; ov51x_stop_isoc(ov); - release_decompressor(ov); - if (ov->led_policy == LED_AUTO) ov51x_led_control(ov, 0); @@ -6021,82 +5907,6 @@ static struct usb_driver ov511_driver = { * ***************************************************************************/ -/* Returns 0 for success */ -int -ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518, - int mmx) -{ - if (ver != DECOMP_INTERFACE_VER) { - err("Decompression module has incompatible"); - err("interface version %d", ver); - err("Interface version %d is required", DECOMP_INTERFACE_VER); - return -EINVAL; - } - - if (!ops) - return -EFAULT; - - if (mmx && !ov51x_mmx_available) { - err("MMX not available on this system or kernel"); - return -EINVAL; - } - - lock_kernel(); - - if (ov518) { - if (mmx) { - if (ov518_mmx_decomp_ops) - goto err_in_use; - else - ov518_mmx_decomp_ops = ops; - } else { - if (ov518_decomp_ops) - goto err_in_use; - else - ov518_decomp_ops = ops; - } - } else { - if (mmx) { - if (ov511_mmx_decomp_ops) - goto err_in_use; - else - ov511_mmx_decomp_ops = ops; - } else { - if (ov511_decomp_ops) - goto err_in_use; - else - ov511_decomp_ops = ops; - } - } - - unlock_kernel(); - return 0; - -err_in_use: - unlock_kernel(); - return -EBUSY; -} - -void -ov511_deregister_decomp_module(int ov518, int mmx) -{ - lock_kernel(); - - if (ov518) { - if (mmx) - ov518_mmx_decomp_ops = NULL; - else - ov518_decomp_ops = NULL; - } else { - if (mmx) - ov511_mmx_decomp_ops = NULL; - else - ov511_decomp_ops = NULL; - } - - unlock_kernel(); -} - static int __init usb_ov511_init(void) { @@ -6123,5 +5933,3 @@ usb_ov511_exit(void) module_init(usb_ov511_init); module_exit(usb_ov511_exit); -EXPORT_SYMBOL(ov511_register_decomp_module); -EXPORT_SYMBOL(ov511_deregister_decomp_module); diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c index 359c4b2df735..3ebb6e9cdf92 100644 --- a/drivers/usb/media/pwc/pwc-ctrl.c +++ b/drivers/usb/media/pwc/pwc-ctrl.c @@ -1152,45 +1152,6 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) /* End of Add-Ons */ /* ************************************************* */ -/* Linux 2.5.something and 2.6 pass direct pointers to arguments of - ioctl() calls. With 2.4, you have to do tedious copy_from_user() - and copy_to_user() calls. With these macros we circumvent this, - and let me maintain only one source file. The functionality is - exactly the same otherwise. - */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - -/* define local variable for arg */ -#define ARG_DEF(ARG_type, ARG_name)\ - ARG_type *ARG_name = arg; -/* copy arg to local variable */ -#define ARG_IN(ARG_name) /* nothing */ -/* argument itself (referenced) */ -#define ARGR(ARG_name) (*ARG_name) -/* argument address */ -#define ARGA(ARG_name) ARG_name -/* copy local variable to arg */ -#define ARG_OUT(ARG_name) /* nothing */ - -#else - -#define ARG_DEF(ARG_type, ARG_name)\ - ARG_type ARG_name; -#define ARG_IN(ARG_name)\ - if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\ - ret = -EFAULT;\ - break;\ - } -#define ARGR(ARG_name) ARG_name -#define ARGA(ARG_name) &ARG_name -#define ARG_OUT(ARG_name)\ - if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\ - ret = -EFAULT;\ - break;\ - } - -#endif int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { @@ -1220,243 +1181,206 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) case VIDIOCPWCSCQUAL: { - ARG_DEF(int, qual) + int *qual = arg; - ARG_IN(qual) - if (ARGR(qual) < 0 || ARGR(qual) > 3) + if (*qual < 0 || *qual > 3) ret = -EINVAL; else - ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); + ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); if (ret >= 0) - pdev->vcompression = ARGR(qual); + pdev->vcompression = *qual; break; } case VIDIOCPWCGCQUAL: { - ARG_DEF(int, qual) - - ARGR(qual) = pdev->vcompression; - ARG_OUT(qual) + int *qual = arg; + *qual = pdev->vcompression; break; } case VIDIOCPWCPROBE: { - ARG_DEF(struct pwc_probe, probe) - - strcpy(ARGR(probe).name, pdev->vdev->name); - ARGR(probe).type = pdev->type; - ARG_OUT(probe) + struct pwc_probe *probe = arg; + strcpy(probe->name, pdev->vdev->name); + probe->type = pdev->type; break; } case VIDIOCPWCGSERIAL: { - ARG_DEF(struct pwc_serial, serial) - - strcpy(ARGR(serial).serial, pdev->serial); - ARG_OUT(serial) + struct pwc_serial *serial = arg; + strcpy(serial->serial, pdev->serial); break; } case VIDIOCPWCSAGC: { - ARG_DEF(int, agc) - - ARG_IN(agc) - if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc))) + int *agc = arg; + if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) ret = -EINVAL; break; } case VIDIOCPWCGAGC: { - ARG_DEF(int, agc) + int *agc = arg; - if (pwc_get_agc(pdev, ARGA(agc))) + if (pwc_get_agc(pdev, agc)) ret = -EINVAL; - ARG_OUT(agc) break; } case VIDIOCPWCSSHUTTER: { - ARG_DEF(int, shutter_speed) - - ARG_IN(shutter_speed) - ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed)); + int *shutter_speed = arg; + ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); break; } case VIDIOCPWCSAWB: { - ARG_DEF(struct pwc_whitebalance, wb) + struct pwc_whitebalance *wb = arg; - ARG_IN(wb) - ret = pwc_set_awb(pdev, ARGR(wb).mode); - if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { - pwc_set_red_gain(pdev, ARGR(wb).manual_red); - pwc_set_blue_gain(pdev, ARGR(wb).manual_blue); + ret = pwc_set_awb(pdev, wb->mode); + if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { + pwc_set_red_gain(pdev, wb->manual_red); + pwc_set_blue_gain(pdev, wb->manual_blue); } break; } case VIDIOCPWCGAWB: { - ARG_DEF(struct pwc_whitebalance, wb) + struct pwc_whitebalance *wb = arg; - memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); - ARGR(wb).mode = pwc_get_awb(pdev); - if (ARGR(wb).mode < 0) + memset(wb, 0, sizeof(struct pwc_whitebalance)); + wb->mode = pwc_get_awb(pdev); + if (wb->mode < 0) ret = -EINVAL; else { - if (ARGR(wb).mode == PWC_WB_MANUAL) { - ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red); + if (wb->mode == PWC_WB_MANUAL) { + ret = pwc_get_red_gain(pdev, &wb->manual_red); if (ret < 0) break; - ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue); + ret = pwc_get_blue_gain(pdev, &wb->manual_blue); if (ret < 0) break; } - if (ARGR(wb).mode == PWC_WB_AUTO) { - ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); + if (wb->mode == PWC_WB_AUTO) { + ret = pwc_read_red_gain(pdev, &wb->read_red); if (ret < 0) break; - ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); + ret = pwc_read_blue_gain(pdev, &wb->read_blue); if (ret < 0) break; } } - ARG_OUT(wb) break; } case VIDIOCPWCSAWBSPEED: { - ARG_DEF(struct pwc_wb_speed, wbs) + struct pwc_wb_speed *wbs = arg; - if (ARGR(wbs).control_speed > 0) { - ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); + if (wbs->control_speed > 0) { + ret = pwc_set_wb_speed(pdev, wbs->control_speed); } - if (ARGR(wbs).control_delay > 0) { - ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); + if (wbs->control_delay > 0) { + ret = pwc_set_wb_delay(pdev, wbs->control_delay); } break; } case VIDIOCPWCGAWBSPEED: { - ARG_DEF(struct pwc_wb_speed, wbs) + struct pwc_wb_speed *wbs = arg; - ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); + ret = pwc_get_wb_speed(pdev, &wbs->control_speed); if (ret < 0) break; - ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); + ret = pwc_get_wb_delay(pdev, &wbs->control_delay); if (ret < 0) break; - ARG_OUT(wbs) break; } case VIDIOCPWCSLED: { - ARG_DEF(struct pwc_leds, leds) - - ARG_IN(leds) - ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off); + struct pwc_leds *leds = arg; + ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); break; } case VIDIOCPWCGLED: { - ARG_DEF(struct pwc_leds, leds) - - ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off); - ARG_OUT(leds) + struct pwc_leds *leds = arg; + ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); break; } case VIDIOCPWCSCONTOUR: { - ARG_DEF(int, contour) - - ARG_IN(contour) - ret = pwc_set_contour(pdev, ARGR(contour)); + int *contour = arg; + ret = pwc_set_contour(pdev, *contour); break; } case VIDIOCPWCGCONTOUR: { - ARG_DEF(int, contour) - - ret = pwc_get_contour(pdev, ARGA(contour)); - ARG_OUT(contour) + int *contour = arg; + ret = pwc_get_contour(pdev, contour); break; } case VIDIOCPWCSBACKLIGHT: { - ARG_DEF(int, backlight) - - ARG_IN(backlight) - ret = pwc_set_backlight(pdev, ARGR(backlight)); + int *backlight = arg; + ret = pwc_set_backlight(pdev, *backlight); break; } case VIDIOCPWCGBACKLIGHT: { - ARG_DEF(int, backlight) - - ret = pwc_get_backlight(pdev, ARGA(backlight)); - ARG_OUT(backlight) + int *backlight = arg; + ret = pwc_get_backlight(pdev, backlight); break; } case VIDIOCPWCSFLICKER: { - ARG_DEF(int, flicker) - - ARG_IN(flicker) - ret = pwc_set_flicker(pdev, ARGR(flicker)); + int *flicker = arg; + ret = pwc_set_flicker(pdev, *flicker); break; } case VIDIOCPWCGFLICKER: { - ARG_DEF(int, flicker) - - ret = pwc_get_flicker(pdev, ARGA(flicker)); - ARG_OUT(flicker) + int *flicker = arg; + ret = pwc_get_flicker(pdev, flicker); break; } case VIDIOCPWCSDYNNOISE: { - ARG_DEF(int, dynnoise) - - ARG_IN(dynnoise) - ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise)); + int *dynnoise = arg; + ret = pwc_set_dynamic_noise(pdev, *dynnoise); break; } case VIDIOCPWCGDYNNOISE: { - ARG_DEF(int, dynnoise) - - ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise)); - ARG_OUT(dynnoise); + int *dynnoise = arg; + ret = pwc_get_dynamic_noise(pdev, dynnoise); break; } case VIDIOCPWCGREALSIZE: { - ARG_DEF(struct pwc_imagesize, size) - - ARGR(size).width = pdev->image.x; - ARGR(size).height = pdev->image.y; - ARG_OUT(size) + struct pwc_imagesize *size = arg; + size->width = pdev->image.x; + size->height = pdev->image.y; break; } @@ -1464,10 +1388,9 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { if (pdev->features & FEATURE_MOTOR_PANTILT) { - ARG_DEF(int, flags) + int *flags = arg; - ARG_IN(flags) - ret = pwc_mpt_reset(pdev, ARGR(flags)); + ret = pwc_mpt_reset(pdev, *flags); if (ret >= 0) { pdev->pan_angle = 0; @@ -1485,10 +1408,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { if (pdev->features & FEATURE_MOTOR_PANTILT) { - ARG_DEF(struct pwc_mpt_range, range) - - ARGR(range) = pdev->angle_range; - ARG_OUT(range) + struct pwc_mpt_range *range = arg; + *range = pdev->angle_range; } else { @@ -1503,21 +1424,19 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) if (pdev->features & FEATURE_MOTOR_PANTILT) { - ARG_DEF(struct pwc_mpt_angles, angles) - - ARG_IN(angles) + struct pwc_mpt_angles *angles = arg; /* The camera can only set relative angles, so do some calculations when getting an absolute angle . */ - if (ARGR(angles).absolute) + if (angles->absolute) { - new_pan = ARGR(angles).pan; - new_tilt = ARGR(angles).tilt; + new_pan = angles->pan; + new_tilt = angles->tilt; } else { - new_pan = pdev->pan_angle + ARGR(angles).pan; - new_tilt = pdev->tilt_angle + ARGR(angles).tilt; + new_pan = pdev->pan_angle + angles->pan; + new_tilt = pdev->tilt_angle + angles->tilt; } /* check absolute ranges */ if (new_pan < pdev->angle_range.pan_min || @@ -1560,12 +1479,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) if (pdev->features & FEATURE_MOTOR_PANTILT) { - ARG_DEF(struct pwc_mpt_angles, angles) + struct pwc_mpt_angles *angles = arg; - ARGR(angles).absolute = 1; - ARGR(angles).pan = pdev->pan_angle; - ARGR(angles).tilt = pdev->tilt_angle; - ARG_OUT(angles) + angles->absolute = 1; + angles->pan = pdev->pan_angle; + angles->tilt = pdev->tilt_angle; } else { @@ -1578,10 +1496,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { if (pdev->features & FEATURE_MOTOR_PANTILT) { - ARG_DEF(struct pwc_mpt_status, status) - - ret = pwc_mpt_get_status(pdev, ARGA(status)); - ARG_OUT(status) + struct pwc_mpt_status *status = arg; + ret = pwc_mpt_get_status(pdev, status); } else { @@ -1592,24 +1508,22 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) case VIDIOCPWCGVIDCMD: { - ARG_DEF(struct pwc_video_command, cmd); + struct pwc_video_command *cmd = arg; - ARGR(cmd).type = pdev->type; - ARGR(cmd).release = pdev->release; - ARGR(cmd).command_len = pdev->cmd_len; - memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); - ARGR(cmd).bandlength = pdev->vbandlength; - ARGR(cmd).frame_size = pdev->frame_size; - ARG_OUT(cmd) + cmd->type = pdev->type; + cmd->release = pdev->release; + cmd->command_len = pdev->cmd_len; + memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); + cmd->bandlength = pdev->vbandlength; + cmd->frame_size = pdev->frame_size; break; } /* case VIDIOCPWCGVIDTABLE: { - ARG_DEF(struct pwc_table_init_buffer, table); - ARGR(table).len = pdev->cmd_len; - memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); - ARG_OUT(table) + struct pwc_table_init_buffer *table = arg; + table->len = pdev->cmd_len; + memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); break; } */ diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h index e5cea0e2eb57..17d60c1eea7e 100644 --- a/drivers/usb/media/sn9c102.h +++ b/drivers/usb/media/sn9c102.h @@ -1,7 +1,7 @@ /*************************************************************************** * V4L2 driver for SN9C10x PC Camera Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * @@ -23,7 +23,8 @@ #include <linux/version.h> #include <linux/usb.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> #include <linux/device.h> #include <linux/list.h> #include <linux/spinlock.h> @@ -52,13 +53,6 @@ /*****************************************************************************/ -#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" -#define SN9C102_MODULE_AUTHOR "(C) 2004-2005 Luca Risolia" -#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" -#define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.24a" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 24) - enum sn9c102_bridge { BRIDGE_SN9C101 = 0x01, BRIDGE_SN9C102 = 0x02, @@ -102,12 +96,13 @@ enum sn9c102_stream_state { STREAM_ON, }; +typedef char sn9c103_sof_header_t[18]; typedef char sn9c102_sof_header_t[12]; typedef char sn9c102_eof_header_t[4]; struct sn9c102_sysfs_attr { u8 reg, i2c_reg; - sn9c102_sof_header_t frame_header; + sn9c103_sof_header_t frame_header; }; struct sn9c102_module_param { @@ -118,8 +113,6 @@ static DECLARE_MUTEX(sn9c102_sysfs_lock); static DECLARE_RWSEM(sn9c102_disconnect); struct sn9c102_device { - struct device dev; - struct video_device* v4ldev; enum sn9c102_bridge bridge; @@ -140,8 +133,8 @@ struct sn9c102_device { struct v4l2_jpegcompression compression; struct sn9c102_sysfs_attr sysfs; - sn9c102_sof_header_t sof_header; - u16 reg[32]; + sn9c103_sof_header_t sof_header; + u16 reg[63]; struct sn9c102_module_param module_param; @@ -160,7 +153,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) { cam->sensor = sensor; - cam->sensor->dev = &cam->dev; cam->sensor->usbdev = cam->usbdev; } @@ -170,19 +162,24 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, #undef KDBG #ifdef SN9C102_DEBUG # define DBG(level, fmt, args...) \ -{ \ +do { \ if (debug >= (level)) { \ if ((level) == 1) \ - dev_err(&cam->dev, fmt "\n", ## args); \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) == 2) \ - dev_info(&cam->dev, fmt "\n", ## args); \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ - dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ __FUNCTION__, __LINE__ , ## args); \ } \ -} +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) # define KDBG(level, fmt, args...) \ -{ \ +do { \ if (debug >= (level)) { \ if ((level) == 1 || (level) == 2) \ pr_info("sn9c102: " fmt "\n", ## args); \ @@ -190,17 +187,18 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ __LINE__ , ## args); \ } \ -} +} while (0) #else -# define KDBG(level, fmt, args...) do {;} while(0); -# define DBG(level, fmt, args...) do {;} while(0); +# define DBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) #endif #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args); +dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) #undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0); /* placeholder */ +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ #endif /* _SN9C102_H_ */ diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index 8d1a1c357d5a..c81397e4714b 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -1,7 +1,7 @@ /*************************************************************************** * V4L2 driver for SN9C10x PC Camera Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * @@ -45,6 +45,15 @@ /*****************************************************************************/ +#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" +#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" +#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" +#define SN9C102_MODULE_LICENSE "GPL" +#define SN9C102_MODULE_VERSION "1:1.26" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26) + +/*****************************************************************************/ + MODULE_DEVICE_TABLE(usb, sn9c102_id_table); MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); @@ -70,10 +79,10 @@ static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FORCE_MUNMAP}; module_param_array(force_munmap, bool, NULL, 0444); MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously " - "\nmapped buffer memory before calling any VIDIOC_S_CROP or " - "\nVIDIOC_S_FMT ioctl's. Not all the applications support " - "\nthis feature. This parameter is specific for each " + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" "\ndetected camera." "\n 0 = do not force memory unmapping" "\n 1 = force memory unmapping (save memory)" @@ -102,6 +111,9 @@ static sn9c102_sof_header_t sn9c102_sof_header[] = { {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, }; +static sn9c103_sof_header_t sn9c103_sof_header[] = { + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20}, +}; static sn9c102_eof_header_t sn9c102_eof_header[] = { {0x00, 0x00, 0x00, 0x00}, @@ -112,50 +124,6 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = { /*****************************************************************************/ -static void* rvmalloc(size_t size) -{ - void* mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - - mem = vmalloc_32((unsigned long)size); - if (!mem) - return NULL; - - memset(mem, 0, size); - - adr = (unsigned long)mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - - -static void rvfree(void* mem, size_t size) -{ - unsigned long adr; - - if (!mem) - return; - - size = PAGE_ALIGN(size); - - adr = (unsigned long)mem; - while (size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vfree(mem); -} - - static u32 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, enum sn9c102_io_method io) @@ -174,7 +142,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, cam->nbuffers = count; while (cam->nbuffers > 0) { - if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize)))) + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) break; cam->nbuffers--; } @@ -198,10 +166,10 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, static void sn9c102_release_buffers(struct sn9c102_device* cam) { if (cam->nbuffers) { - rvfree(cam->frame[0].bufmem, - cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length)); + vfree(cam->frame[0].bufmem); cam->nbuffers = 0; } + cam->frame_current = NULL; } @@ -219,6 +187,19 @@ static void sn9c102_empty_framequeues(struct sn9c102_device* cam) } +static void sn9c102_requeue_outqueue(struct sn9c102_device* cam) +{ + struct sn9c102_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) { unsigned long lock_flags; @@ -235,19 +216,46 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) /*****************************************************************************/ +int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) +{ + struct usb_device* udev = cam->usbdev; + int i, res; + + if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg)) + return -1; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + index, 0, buff, sizeof(buff), + SN9C102_CTRL_TIMEOUT*sizeof(buff)); + if (res < 0) { + DBG(3, "Failed to write registers (index 0x%02X, error %d)", + index, res); + return -1; + } + + for (i = 0; i < sizeof(buff); i++) + cam->reg[index+i] = buff[i]; + + return 0; +} + + int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) { struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int res; + if (index >= ARRAY_SIZE(cam->reg)) + return -1; + *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, index " - "0x%02X, error %d)", value, index, res) + "0x%02X, error %d)", value, index, res); return -1; } @@ -268,7 +276,7 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%02X, error %d)", - index, res) + index, res); return (res >= 0) ? (int)(*buff) : -1; } @@ -276,8 +284,8 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) { - if (index > 0x1f) - return -EINVAL; + if (index >= ARRAY_SIZE(cam->reg)) + return -1; return cam->reg[index]; } @@ -367,10 +375,10 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, err += sn9c102_i2c_detect_read_error(cam, sensor); PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, - data[4]) + data[4]); if (err) { - DBG(3, "I2C read failed for %s image sensor", sensor->name) + DBG(3, "I2C read failed for %s image sensor", sensor->name); return -1; } @@ -410,11 +418,11 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, err += sn9c102_i2c_detect_write_error(cam, sensor); if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name) + DBG(3, "I2C write failed for %s image sensor", sensor->name); PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", - n, data0, data1, data2, data3, data4, data5) + n, data0, data1, data2, data3, data4, data5); return err ? -1 : 0; } @@ -461,13 +469,27 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) static void* sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) { - size_t soflen = sizeof(sn9c102_sof_header_t), i; - u8 j, n = sizeof(sn9c102_sof_header) / soflen; + size_t soflen = 0, i; + u8 j, n = 0; - for (i = 0; (len >= soflen) && (i <= len - soflen); i++) + switch (cam->bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + soflen = sizeof(sn9c102_sof_header_t); + n = sizeof(sn9c102_sof_header) / soflen; + break; + case BRIDGE_SN9C103: + soflen = sizeof(sn9c103_sof_header_t); + n = sizeof(sn9c103_sof_header) / soflen; + } + + for (i = 0; (len >= soflen) && (i <= len - soflen); i++) for (j = 0; j < n; j++) - /* It's enough to compare 7 bytes */ - if (!memcmp(mem + i, sn9c102_sof_header[j], 7)) { + /* The invariable part of the header is 6 bytes long */ + if ((cam->bridge != BRIDGE_SN9C103 && + !memcmp(mem + i, sn9c102_sof_header[j], 6)) || + (cam->bridge == BRIDGE_SN9C103 && + !memcmp(mem + i, sn9c103_sof_header[j], 6))) { memcpy(cam->sof_header, mem + i, soflen); /* Skip the header */ return mem + i + soflen; @@ -499,8 +521,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) { struct sn9c102_device* cam = urb->context; struct sn9c102_frame_t** f; - size_t imagesize; - unsigned long lock_flags; + size_t imagesize, soflen; u8 i; int err = 0; @@ -513,7 +534,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) cam->stream = STREAM_OFF; if ((*f)) (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted") + DBG(3, "Stream interrupted"); wake_up_interruptible(&cam->wait_stream); } @@ -536,6 +557,10 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) cam->sensor->pix_format.height * cam->sensor->pix_format.priv) / 8; + soflen = (cam->bridge) == BRIDGE_SN9C103 ? + sizeof(sn9c103_sof_header_t) : + sizeof(sn9c102_sof_header_t); + for (i = 0; i < urb->number_of_packets; i++) { unsigned int img, len, status; void *pos, *sof, *eof; @@ -545,19 +570,12 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; if (status) { - DBG(3, "Error in isochronous frame") + DBG(3, "Error in isochronous frame"); (*f)->state = F_ERROR; continue; } - PDBGG("Isochrnous frame: length %u, #%u i", len, i) - - /* - NOTE: It is probably correct to assume that SOF and EOF - headers do not occur between two consecutive packets, - but who knows..Whatever is the truth, this assumption - doesn't introduce bugs. - */ + PDBGG("Isochrnous frame: length %u, #%u i", len, i); redo: sof = sn9c102_find_sof_header(cam, pos, len); @@ -575,10 +593,10 @@ end_of_frame: imagesize; img = imagesize - (*f)->buf.bytesused; DBG(3, "Expected EOF not found: " - "video frame cut") + "video frame cut"); if (eof) DBG(3, "Exceeded limit: +%u " - "bytes", (unsigned)(b)) + "bytes", (unsigned)(b)); } memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, @@ -595,8 +613,7 @@ end_of_frame: u32 b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; - spin_lock_irqsave(&cam->queue_lock, - lock_flags); + spin_lock(&cam->queue_lock); list_move_tail(&(*f)->frame, &cam->outqueue); if (!list_empty(&cam->inqueue)) @@ -606,13 +623,11 @@ end_of_frame: frame ); else (*f) = NULL; - spin_unlock_irqrestore(&cam->queue_lock - , lock_flags); + spin_unlock(&cam->queue_lock); memcpy(cam->sysfs.frame_header, - cam->sof_header, - sizeof(sn9c102_sof_header_t)); - DBG(3, "Video frame captured: " - "%lu bytes", (unsigned long)(b)) + cam->sof_header, soflen); + DBG(3, "Video frame captured: %lu " + "bytes", (unsigned long)(b)); if (!(*f)) goto resubmit_urb; @@ -621,18 +636,19 @@ end_of_frame: (*f)->state = F_ERROR; DBG(3, "Not expected EOF after %lu " "bytes of image data", - (unsigned long)((*f)->buf.bytesused)) + (unsigned long) + ((*f)->buf.bytesused)); } if (sof) /* (1) */ goto start_of_frame; } else if (eof) { - DBG(3, "EOF without SOF") + DBG(3, "EOF without SOF"); continue; } else { - PDBGG("Ignoring pointless isochronous frame") + PDBGG("Ignoring pointless isochronous frame"); continue; } @@ -642,7 +658,7 @@ start_of_frame: (*f)->buf.bytesused = 0; len -= (sof - pos); pos = sof; - DBG(3, "SOF detected: new video frame") + DBG(3, "SOF detected: new video frame"); if (len) goto redo; @@ -653,12 +669,13 @@ start_of_frame: else { if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) { - eof = sof-sizeof(sn9c102_sof_header_t); + eof = sof - soflen; goto end_of_frame; } else { DBG(3, "SOF before expected EOF after " "%lu bytes of image data", - (unsigned long)((*f)->buf.bytesused)) + (unsigned long) + ((*f)->buf.bytesused)); goto start_of_frame; } } @@ -670,7 +687,7 @@ resubmit_urb: err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0 && err != -EPERM) { cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed") + DBG(1, "usb_submit_urb() failed"); } wake_up_interruptible(&cam->wait_frame); @@ -681,18 +698,22 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) { struct usb_device *udev = cam->usbdev; struct urb* urb; - const unsigned int wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1023}; - const unsigned int psz = wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; + const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, + 680, 800, 900, 1023}; + const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, + 680, 800, 900, 1003}; + const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? + sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : + sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; s8 i, j; int err = 0; for (i = 0; i < SN9C102_URBS; i++) { - cam->transfer_buffer[i] = kmalloc(SN9C102_ISO_PACKETS * psz, + cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, GFP_KERNEL); if (!cam->transfer_buffer[i]) { err = -ENOMEM; - DBG(1, "Not enough memory") + DBG(1, "Not enough memory"); goto free_buffers; } } @@ -702,7 +723,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) cam->urb[i] = urb; if (!urb) { err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed") + DBG(1, "usb_alloc_urb() failed"); goto free_urbs; } urb->dev = udev; @@ -725,14 +746,14 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01); if (err) { err = -EIO; - DBG(1, "I/O hardware error") + DBG(1, "I/O hardware error"); goto free_urbs; } } err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING); if (err) { - DBG(1, "usb_set_interface() failed") + DBG(1, "usb_set_interface() failed"); goto free_urbs; } @@ -743,7 +764,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) if (err) { for (j = i-1; j >= 0; j--) usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err) + DBG(1, "usb_submit_urb() failed, error %d", err); goto free_urbs; } } @@ -779,7 +800,7 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam) err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ if (err) - DBG(3, "usb_set_interface() failed") + DBG(3, "usb_set_interface() failed"); return err; } @@ -799,7 +820,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) else if (err) { cam->state |= DEV_MISCONFIGURED; DBG(1, "The camera is misconfigured. To use it, close and " - "open /dev/video%d again.", cam->v4ldev->minor) + "open /dev/video%d again.", cam->v4ldev->minor); return err; } @@ -808,6 +829,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) /*****************************************************************************/ +#ifdef CONFIG_VIDEO_ADV_DEBUG static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) { char str[5]; @@ -885,8 +907,8 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) cam->sysfs.reg = index; - DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg) - DBG(3, "Written bytes: %zd", count) + DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); + DBG(3, "Written bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -916,7 +938,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count) + DBG(3, "Read bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -954,8 +976,8 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) } DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", - cam->sysfs.reg, value) - DBG(3, "Written bytes: %zd", count) + cam->sysfs.reg, value); + DBG(3, "Written bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -979,7 +1001,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); - DBG(3, "Read bytes: %zd", count) + DBG(3, "Read bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -1011,8 +1033,8 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) cam->sysfs.i2c_reg = index; - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg) - DBG(3, "Written bytes: %zd", count) + DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); + DBG(3, "Written bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -1047,7 +1069,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) count = sprintf(buf, "%d\n", val); - DBG(3, "Read bytes: %zd", count) + DBG(3, "Read bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -1090,8 +1112,8 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) } DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", - cam->sysfs.i2c_reg, value) - DBG(3, "Written bytes: %zd", count) + cam->sysfs.i2c_reg, value); + DBG(3, "Written bytes: %zd", count); up(&sn9c102_sysfs_lock); @@ -1193,7 +1215,7 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) count = sizeof(cam->sysfs.frame_header); memcpy(buf, cam->sysfs.frame_header, count); - DBG(3, "Frame header, read bytes: %zd", count) + DBG(3, "Frame header, read bytes: %zd", count); return count; } @@ -1227,11 +1249,12 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) video_device_create_file(v4ldev, &class_device_attr_blue); video_device_create_file(v4ldev, &class_device_attr_red); } - if (cam->sensor->sysfs_ops) { + if (cam->sensor && cam->sensor->sysfs_ops) { video_device_create_file(v4ldev, &class_device_attr_i2c_reg); video_device_create_file(v4ldev, &class_device_attr_i2c_val); } } +#endif /* CONFIG_VIDEO_ADV_DEBUG */ /*****************************************************************************/ @@ -1281,7 +1304,7 @@ static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) if (err) return -EIO; - PDBGG("Scaling factor: %u", scale) + PDBGG("Scaling factor: %u", scale); return 0; } @@ -1304,7 +1327,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) return -EIO; PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " - "%u %u %u %u", h_start, v_start, h_size, v_size) + "%u %u %u %u", h_start, v_start, h_size, v_size); return 0; } @@ -1336,7 +1359,7 @@ static int sn9c102_init(struct sn9c102_device* cam) if (s->init) { err = s->init(cam); if (err) { - DBG(3, "Sensor initialization failed") + DBG(3, "Sensor initialization failed"); return err; } } @@ -1353,13 +1376,13 @@ static int sn9c102_init(struct sn9c102_device* cam) if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) DBG(3, "Compressed video format is active, quality %d", - cam->compression.quality) + cam->compression.quality); else - DBG(3, "Uncompressed video format is active") + DBG(3, "Uncompressed video format is active"); if (s->set_crop) if ((err = s->set_crop(cam, rect))) { - DBG(3, "set_crop() failed") + DBG(3, "set_crop() failed"); return err; } @@ -1372,11 +1395,11 @@ static int sn9c102_init(struct sn9c102_device* cam) err = s->set_ctrl(cam, &ctrl); if (err) { DBG(3, "Set %s control failed", - s->qctrl[i].name) + s->qctrl[i].name); return err; } DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name) + s->qctrl[i].name); } } @@ -1392,7 +1415,7 @@ static int sn9c102_init(struct sn9c102_device* cam) cam->state |= DEV_INITIALIZED; } - DBG(2, "Initialization succeeded") + DBG(2, "Initialization succeeded"); return 0; } @@ -1401,7 +1424,7 @@ static void sn9c102_release_resources(struct sn9c102_device* cam) { down(&sn9c102_sysfs_lock); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor) + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); @@ -1432,7 +1455,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) } if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor) + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { err = -EWOULDBLOCK; @@ -1458,7 +1481,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) err = sn9c102_init(cam); if (err) { DBG(1, "Initialization failed again. " - "I will retry on next open().") + "I will retry on next open()."); goto out; } cam->state &= ~DEV_MISCONFIGURED; @@ -1475,7 +1498,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) cam->frame_count = 0; sn9c102_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor) + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: up(&cam->dev_sem); @@ -1504,7 +1527,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) cam->users--; wake_up_interruptible_nr(&cam->open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor) + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); up(&cam->dev_sem); @@ -1524,32 +1547,38 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present") + DBG(1, "Device not present"); up(&cam->fileop_sem); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it again.") + DBG(1, "The camera is misconfigured. Close and open it " + "again."); up(&cam->fileop_sem); return -EIO; } if (cam->io == IO_MMAP) { DBG(3, "Close and open the device again to choose " - "the read method") + "the read method"); up(&cam->fileop_sem); return -EINVAL; } if (cam->io == IO_NONE) { if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory") + DBG(1, "read() failed, not enough memory"); up(&cam->fileop_sem); return -ENOMEM; } cam->io = IO_READ; cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + sn9c102_empty_framequeues(cam); sn9c102_queue_unusedframes(cam); } @@ -1584,6 +1613,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame); + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: spin_lock_irqsave(&cam->queue_lock, lock_flags); list_for_each_entry(i, &cam->outqueue, frame) i->state = F_UNUSED; @@ -1592,16 +1631,8 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) sn9c102_queue_unusedframes(cam); - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - up(&cam->fileop_sem); - return -EFAULT; - } - *f_pos += count; - - PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index,count) + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); up(&cam->fileop_sem); @@ -1612,33 +1643,42 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_frame_t* f; + unsigned long lock_flags; unsigned int mask = 0; if (down_interruptible(&cam->fileop_sem)) return POLLERR; if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present") + DBG(1, "Device not present"); goto error; } if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it again.") + DBG(1, "The camera is misconfigured. Close and open it " + "again."); goto error; } if (cam->io == IO_NONE) { if (!sn9c102_request_buffers(cam, cam->nreadbuffers, IO_READ)) { - DBG(1, "poll() failed, not enough memory") + DBG(1, "poll() failed, not enough memory"); goto error; } cam->io = IO_READ; cam->stream = STREAM_ON; } - if (cam->io == IO_READ) + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); sn9c102_queue_unusedframes(cam); + } poll_wait(filp, &cam->wait_frame, wait); @@ -1680,22 +1720,22 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start, - pos, - page; + start = vma->vm_start; + void *pos; u32 i; if (down_interruptible(&cam->fileop_sem)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present") + DBG(1, "Device not present"); up(&cam->fileop_sem); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it again.") + DBG(1, "The camera is misconfigured. Close and open it " + "again."); up(&cam->fileop_sem); return -EIO; } @@ -1715,15 +1755,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return -EINVAL; } - /* VM_IO is eventually going to replace PageReserved altogether */ vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + vma->vm_flags |= VM_RESERVED; - pos = (unsigned long)cam->frame[i].bufmem; + pos = cam->frame[i].bufmem; while (size > 0) { /* size is page-aligned */ - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, - vma->vm_page_prot)) { + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { up(&cam->fileop_sem); return -EAGAIN; } @@ -1742,738 +1779,861 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return 0; } +/*****************************************************************************/ -static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) +static int +sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct v4l2_capability cap = { + .driver = "sn9c102", + .version = SN9C102_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; - switch (cmd) { + return 0; +} - case VIDIOC_QUERYCAP: - { - struct v4l2_capability cap = { - .driver = "sn9c102", - .version = SN9C102_MODULE_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, - sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, cam->dev.bus_id, - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - return 0; - } +static int +sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_input i; - case VIDIOC_ENUMINPUT: - { - struct v4l2_input i; + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; + if (i.index) + return -EINVAL; - if (i.index) - return -EINVAL; + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); - memset(&i, 0, sizeof(i)); - strcpy(i.name, "USB"); + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; + return 0; +} - return 0; - } - case VIDIOC_G_INPUT: - case VIDIOC_S_INPUT: - { - int index; +static int +sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) +{ + int index; - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; - if (index != 0) - return -EINVAL; + if (index != 0) + return -EINVAL; - return 0; - } + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; +static int +sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; + if (ctrl.id && ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; } - return -EINVAL; - } + } else + err = s->get_ctrl(cam, &ctrl); - case VIDIOC_G_CTRL: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_control ctrl; - int err = 0; +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; - if (!s->get_ctrl) - return -EINVAL; + return err; +} - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - err = s->get_ctrl(cam, &ctrl); +static int +sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) return err; - } - case VIDIOC_S_CTRL_OLD: - case VIDIOC_S_CTRL: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; + s->_qctrl[i].default_value = ctrl.value; - if (!s->set_ctrl) - return -EINVAL; + PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", + (unsigned long)ctrl.id, (unsigned long)ctrl.value); - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; + return 0; +} - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; + +static int +sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_pix_format* pix_format = &(s->pix_format); + u8 scale; + const enum sn9c102_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; } - if ((err = s->set_ctrl(cam, &ctrl))) + /* Preserve R,G or B origin */ + rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; + rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; + + if (rect->width < 16) + rect->width = 16; + if (rect->height < 16) + rect->height = 16; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + + rect->width &= ~15L; + rect->height &= ~15L; + + if (SN9C102_PRESERVE_IMGSCALE) { + /* Calculate the actual scaling factor */ + u32 a, b; + a = rect->width * rect->height; + b = pix_format->width * pix_format->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; + } else + scale = 1; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - s->_qctrl[i].default_value = ctrl.value; + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + sn9c102_release_buffers(cam); - PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value) + err = sn9c102_set_crop(cam, rect); + if (s->set_crop) + err += s->set_crop(cam, rect); + err += sn9c102_set_scale(cam, scale); - return 0; + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; } - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + s->pix_format.width = rect->width/scale; + s->pix_format.height = rect->height/scale; + memcpy(&(s->_rect), rect, sizeof(*rect)); - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; + if (cam->io == IO_READ) + sn9c102_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + sn9c102_requeue_outqueue(cam); - return 0; - } + cam->stream = stream; - case VIDIOC_G_CROP: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; + return 0; +} - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; +static int +sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; - return 0; - } + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; - case VIDIOC_S_CROP: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_pix_format* pix_format = &(s->pix_format); - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; - rect = &(crop.c); + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first.") - return -EINVAL; - } + return 0; +} - /* Preserve R,G or B origin */ - rect->left = (s->_rect.left & 1L) ? - rect->left | 1L : rect->left & ~1L; - rect->top = (s->_rect.top & 1L) ? - rect->top | 1L : rect->top & ~1L; - - if (rect->width < 16) - rect->width = 16; - if (rect->height < 16) - rect->height = 16; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - - rect->width &= ~15L; - rect->height &= ~15L; - - if (SN9C102_PRESERVE_IMGSCALE) { - /* Calculate the actual scaling factor */ - u32 a, b; - a = rect->width * rect->height; - b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) < 4 ? 1 : - ((a / b) < 16 ? 2 : 4)) : 1; - } else - scale = 1; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); +static int +sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); - err = sn9c102_set_crop(cam, rect); - if (s->set_crop) - err += s->set_crop(cam, rect); - err += sn9c102_set_scale(cam, scale); + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor) - return -EIO; - } + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; - s->pix_format.width = rect->width/scale; - s->pix_format.height = rect->height/scale; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, - cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough " - "memory. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor) - return -ENOMEM; - } + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - cam->stream = stream; + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; - return 0; - } + return 0; +} - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc fmtd; - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; +static int +sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, + void __user * arg) +{ + struct sn9c102_sensor* s = cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + u8 scale; + const enum sn9c102_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; - if (fmtd.index == 0) { - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; - } else if (fmtd.index == 1) { - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + pix = &(format.fmt.pix); - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; - return 0; + memcpy(&rect, &(s->_rect), sizeof(rect)); + + { /* calculate the actual scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; } - case VIDIOC_G_FMT: - { - struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + rect.width = scale * pix->width; + rect.height = scale * pix->height; - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; + if (rect.width < 16) + rect.width = 16; + if (rect.height < 16) + rect.height = 16; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + rect.width &= ~15L; + rect.height &= ~15L; + + { /* adjust the scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; + } - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) - ? 0 : (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); - pfmt->field = V4L2_FIELD_NONE; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + pix->width = rect.width / scale; + pix->height = rect.height / scale; + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; /* bpp */ + pix->colorspace = pfmt->colorspace; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { if (copy_to_user(arg, &format, sizeof(format))) return -EFAULT; - return 0; } - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - { - struct sn9c102_sensor* s = cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. Unmap the " + "buffers first."); + return -EINVAL; + } - pix = &(format.fmt.pix); + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } - memcpy(&rect, &(s->_rect), sizeof(rect)); + if (cam->module_param.force_munmap || cam->io == IO_READ) + sn9c102_release_buffers(cam); - { /* calculate the actual scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : - ((a / b) < 16 ? 2 : 4)) : 1; - } + err += sn9c102_set_pix_format(cam, pix); + err += sn9c102_set_crop(cam, &rect); + if (s->set_pix_format) + err += s->set_pix_format(cam, pix); + if (s->set_crop) + err += s->set_crop(cam, &rect); + err += sn9c102_set_scale(cam, scale); - rect.width = scale * pix->width; - rect.height = scale * pix->height; - - if (rect.width < 16) - rect.width = 16; - if (rect.height < 16) - rect.height = 16; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - - rect.width &= ~15L; - rect.height &= ~15L; - - { /* adjust the scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : - ((a / b) < 16 ? 2 : 4)) : 1; - } + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } - pix->width = rect.width / scale; - pix->height = rect.height / scale; - - if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = pfmt->colorspace; - pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - ? 0 : (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. " - "Unmap the buffers first.") - return -EINVAL; - } + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; + if (cam->io == IO_READ) + sn9c102_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + sn9c102_requeue_outqueue(cam); - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } + cam->stream = stream; - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err += sn9c102_set_pix_format(cam, pix); - err += sn9c102_set_crop(cam, &rect); - if (s->set_pix_format) - err += s->set_pix_format(cam, pix); - if (s->set_crop) - err += s->set_crop(cam, &rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor) - return -EIO; - } + return 0; +} - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, - cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough " - "memory. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor) - return -ENOMEM; - } +static int +sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; - cam->stream = stream; + return 0; +} - return 0; - } - case VIDIOC_G_JPEGCOMP: - { - if (copy_to_user(arg, &cam->compression, - sizeof(cam->compression))) - return -EFAULT; +static int +sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum sn9c102_stream_state stream = cam->stream; + int err = 0; - return 0; - } + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; - case VIDIOC_S_JPEGCOMP: - { - struct v4l2_jpegcompression jc; - const enum sn9c102_stream_state stream = cam->stream; - int err = 0; + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; - if (jc.quality != 0 && jc.quality != 1) - return -EINVAL; + err += sn9c102_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; + cam->compression.quality = jc.quality; - err += sn9c102_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor) - return -EIO; - } + cam->stream = stream; - cam->compression.quality = jc.quality; + return 0; +} - cam->stream = stream; - return 0; - } +static int +sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers rb; - u32 i; - int err; + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose " - "the mmap I/O method") + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " + "still mapped."); return -EINVAL; } - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_REQBUFS failed. " - "Previous buffers are still mapped.") - return -EINVAL; - } + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; + sn9c102_empty_framequeues(cam); - sn9c102_empty_framequeues(cam); + sn9c102_release_buffers(cam); + if (rb.count) + rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP); + if (copy_to_user(arg, &rb, sizeof(rb))) { sn9c102_release_buffers(cam); - if (rb.count) - rb.count = sn9c102_request_buffers(cam, rb.count, - IO_MMAP); + cam->io = IO_NONE; + return -EFAULT; + } - if (copy_to_user(arg, &rb, sizeof(rb))) { - sn9c102_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } + cam->io = rb.count ? IO_MMAP : IO_NONE; - cam->io = rb.count ? IO_MMAP : IO_NONE; + return 0; +} - return 0; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer b; +static int +sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_buffer b; - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; - memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; - return 0; - } + return 0; +} - case VIDIOC_QBUF: - { - struct v4l2_buffer b; - unsigned long lock_flags; - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; +static int +sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; - cam->frame[b.index].state = F_QUEUED; + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + cam->frame[b.index].state = F_QUEUED; - PDBGG("Frame #%lu queued", (unsigned long)b.index) + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - return 0; - } + PDBGG("Frame #%lu queued", (unsigned long)b.index); - case VIDIOC_DQBUF: - { - struct v4l2_buffer b; - struct sn9c102_frame_t *f; - unsigned long lock_flags; - int err = 0; + return 0; +} - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) +static int +sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct sn9c102_frame_t *f; + unsigned long lock_flags; + int err = 0; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + err = wait_event_interruptible + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED) ); + if (err) + return err; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (cam->state & DEV_MISCONFIGURED) + return -EIO; + } - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) - return err; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (cam->state & DEV_MISCONFIGURED) - return -EIO; - } + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, - frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + f->state = F_UNUSED; - f->state = F_UNUSED; + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; - memcpy(&b, &f->buf, sizeof(b)); - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index) + return 0; +} - return 0; - } - case VIDIOC_STREAMON: - { - int type; +static int +sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) +{ + int type; - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; - if (list_empty(&cam->inqueue)) - return -EINVAL; + if (list_empty(&cam->inqueue)) + return -EINVAL; - cam->stream = STREAM_ON; + cam->stream = STREAM_ON; - DBG(3, "Stream on") + DBG(3, "Stream on"); - return 0; - } + return 0; +} - case VIDIOC_STREAMOFF: - { - int type, err; - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; +static int +sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg) +{ + int type, err; - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; - sn9c102_empty_framequeues(cam); + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; - DBG(3, "Stream off") + sn9c102_empty_framequeues(cam); - return 0; - } + DBG(3, "Stream off"); - case VIDIOC_G_PARM: - { - struct v4l2_streamparm sp; + return 0; +} - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; +static int +sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; - sp.parm.capture.extendedmode = 0; + if (sp.parm.capture.readbuffers == 0) sp.parm.capture.readbuffers = cam->nreadbuffers; - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; + if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) + sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; - return 0; - } + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; - case VIDIOC_S_PARM_OLD: - case VIDIOC_S_PARM: - { - struct v4l2_streamparm sp; + cam->nreadbuffers = sp.parm.capture.readbuffers; - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; + return 0; +} - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - sp.parm.capture.extendedmode = 0; +static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return sn9c102_vidioc_querycap(cam, arg); - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; + case VIDIOC_ENUMINPUT: + return sn9c102_vidioc_enuminput(cam, arg); - if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) - sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; + case VIDIOC_G_INPUT: + case VIDIOC_S_INPUT: + return sn9c102_vidioc_gs_input(cam, arg); - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; + case VIDIOC_QUERYCTRL: + return sn9c102_vidioc_query_ctrl(cam, arg); - cam->nreadbuffers = sp.parm.capture.readbuffers; + case VIDIOC_G_CTRL: + return sn9c102_vidioc_g_ctrl(cam, arg); - return 0; - } + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return sn9c102_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return sn9c102_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return sn9c102_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return sn9c102_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return sn9c102_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return sn9c102_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return sn9c102_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return sn9c102_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return sn9c102_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return sn9c102_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return sn9c102_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return sn9c102_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return sn9c102_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return sn9c102_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return sn9c102_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return sn9c102_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return sn9c102_vidioc_s_parm(cam, arg); case VIDIOC_G_STD: case VIDIOC_S_STD: @@ -2499,17 +2659,20 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present") + DBG(1, "Device not present"); up(&cam->fileop_sem); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it again.") + DBG(1, "The camera is misconfigured. Close and open it " + "again."); up(&cam->fileop_sem); return -EIO; } + V4LDBG(3, "sn9c102", cmd); + err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); up(&cam->fileop_sem); @@ -2517,9 +2680,10 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, return err; } +/*****************************************************************************/ static struct file_operations sn9c102_fops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .open = sn9c102_open, .release = sn9c102_release, .ioctl = sn9c102_ioctl, @@ -2538,36 +2702,22 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) struct usb_device *udev = interface_to_usbdev(intf); struct sn9c102_device* cam; static unsigned int dev_nr = 0; - unsigned int i, n; + unsigned int i; int err = 0, r; - n = ARRAY_SIZE(sn9c102_id_table); - for (i = 0; i < n-1; i++) - if (le16_to_cpu(udev->descriptor.idVendor) == - sn9c102_id_table[i].idVendor && - le16_to_cpu(udev->descriptor.idProduct) == - sn9c102_id_table[i].idProduct) - break; - if (i == n-1) - return -ENODEV; - - if (!(cam = kmalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) + if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) return -ENOMEM; - memset(cam, 0, sizeof(*cam)); cam->usbdev = udev; - memcpy(&cam->dev, &udev->dev, sizeof(struct device)); - - if (!(cam->control_buffer = kmalloc(8, GFP_KERNEL))) { - DBG(1, "kmalloc() failed") + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); err = -ENOMEM; goto fail; } - memset(cam->control_buffer, 0, 8); if (!(cam->v4ldev = video_device_alloc())) { - DBG(1, "video_device_alloc() failed") + DBG(1, "video_device_alloc() failed"); err = -ENOMEM; goto fail; } @@ -2577,25 +2727,22 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) r = sn9c102_read_reg(cam, 0x00); if (r < 0 || r != 0x10) { DBG(1, "Sorry, this is not a SN9C10x based camera " - "(vid/pid 0x%04X/0x%04X)", - sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct) + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); err = -ENODEV; goto fail; } - cam->bridge = (sn9c102_id_table[i].idProduct & 0xffc0) == 0x6080 ? + cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? BRIDGE_SN9C103 : BRIDGE_SN9C102; switch (cam->bridge) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor, - sn9c102_id_table[i].idProduct) + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); break; case BRIDGE_SN9C103: DBG(2, "SN9C103 PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor, - sn9c102_id_table[i].idProduct) + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); break; } @@ -2606,24 +2753,24 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) } if (!err && cam->sensor) { - DBG(2, "%s image sensor detected", cam->sensor->name) + DBG(2, "%s image sensor detected", cam->sensor->name); DBG(3, "Support for %s maintained by %s", - cam->sensor->name, cam->sensor->maintainer) + cam->sensor->name, cam->sensor->maintainer); } else { - DBG(1, "No supported image sensor detected") + DBG(1, "No supported image sensor detected"); err = -ENODEV; goto fail; } if (sn9c102_init(cam)) { - DBG(1, "Initialization failed. I will retry on open().") + DBG(1, "Initialization failed. I will retry on open()."); cam->state |= DEV_MISCONFIGURED; } strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); cam->v4ldev->owner = THIS_MODULE; cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - cam->v4ldev->hardware = VID_HARDWARE_SN9C102; + cam->v4ldev->hardware = 0; cam->v4ldev->fops = &sn9c102_fops; cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; @@ -2634,23 +2781,25 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); if (err) { - DBG(1, "V4L2 device registration failed") + DBG(1, "V4L2 device registration failed"); if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found") + DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; up(&cam->dev_sem); goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor) + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); cam->module_param.force_munmap = force_munmap[dev_nr]; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; +#ifdef CONFIG_VIDEO_ADV_DEBUG sn9c102_create_sysfs(cam); - DBG(2, "Optional device control through 'sysfs' interface ready") + DBG(2, "Optional device control through 'sysfs' interface ready"); +#endif usb_set_intfdata(intf, cam); @@ -2680,14 +2829,14 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) down(&cam->dev_sem); - DBG(2, "Disconnecting %s...", cam->v4ldev->name) + DBG(2, "Disconnecting %s...", cam->v4ldev->name); wake_up_interruptible_all(&cam->open); if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " "memory deallocation are deferred on close.", - cam->v4ldev->minor) + cam->v4ldev->minor); cam->state |= DEV_MISCONFIGURED; sn9c102_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; @@ -2720,11 +2869,11 @@ static int __init sn9c102_module_init(void) { int err = 0; - KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION) - KDBG(3, SN9C102_MODULE_AUTHOR) + KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION); + KDBG(3, SN9C102_MODULE_AUTHOR); if ((err = usb_register(&sn9c102_usb_driver))) - KDBG(1, "usb_register() failed") + KDBG(1, "usb_register() failed"); return err; } diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/usb/media/sn9c102_hv7131d.c index 18070d5333cf..46c12ec3ca62 100644 --- a/drivers/usb/media/sn9c102_hv7131d.c +++ b/drivers/usb/media/sn9c102_hv7131d.c @@ -2,7 +2,7 @@ * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/usb/media/sn9c102_mi0343.c index 86676abf3547..d9aa7a61095d 100644 --- a/drivers/usb/media/sn9c102_mi0343.c +++ b/drivers/usb/media/sn9c102_mi0343.c @@ -2,7 +2,7 @@ * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c index d27c5aedeaf8..4a36519b5af4 100644 --- a/drivers/usb/media/sn9c102_ov7630.c +++ b/drivers/usb/media/sn9c102_ov7630.c @@ -2,7 +2,7 @@ * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * @@ -375,8 +375,10 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) sn9c102_attach_sensor(cam, &ov7630); - if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f && - le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c) + if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c && + le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d && + le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f && + le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0) return -ENODEV; err += sn9c102_write_reg(cam, 0x01, 0x01); diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c index 48e3ec39d4e2..b1dee78abe04 100644 --- a/drivers/usb/media/sn9c102_pas106b.c +++ b/drivers/usb/media/sn9c102_pas106b.c @@ -2,7 +2,7 @@ * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h index a45166c3488c..7d953b24f2f2 100644 --- a/drivers/usb/media/sn9c102_sensor.h +++ b/drivers/usb/media/sn9c102_sensor.h @@ -1,7 +1,7 @@ /*************************************************************************** * API for image sensors connected to the SN9C10x PC Camera Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * @@ -92,7 +92,18 @@ extern void sn9c102_attach_sensor(struct sn9c102_device* cam, struct sn9c102_sensor* sensor); -/* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/ +/* + Each SN9C10x camera has proper PID/VID identifiers. + SN9C103 supports multiple interfaces, but we only handle the video class + interface. +*/ +#define SN9C102_USB_DEVICE(vend, prod, intclass) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .bInterfaceClass = (intclass) + #define SN9C102_ID_TABLE \ static const struct usb_device_id sn9c102_id_table[] = { \ { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ @@ -107,33 +118,34 @@ static const struct usb_device_id sn9c102_id_table[] = { \ { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \ { USB_DEVICE(0x0c45, 0x602d), }, \ + { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \ { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ - { USB_DEVICE(0x0c45, 0x6080), }, \ - { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */ \ - { USB_DEVICE(0x0c45, 0x6083), }, /* HV7131[D|E1] */ \ - { USB_DEVICE(0x0c45, 0x6088), }, \ - { USB_DEVICE(0x0c45, 0x608a), }, \ - { USB_DEVICE(0x0c45, 0x608b), }, \ - { USB_DEVICE(0x0c45, 0x608c), }, /* HV7131x */ \ - { USB_DEVICE(0x0c45, 0x608e), }, /* CIS-VF10 */ \ - { USB_DEVICE(0x0c45, 0x608f), }, /* OV7630 */ \ - { USB_DEVICE(0x0c45, 0x60a0), }, \ - { USB_DEVICE(0x0c45, 0x60a2), }, \ - { USB_DEVICE(0x0c45, 0x60a3), }, \ - { USB_DEVICE(0x0c45, 0x60a8), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x60aa), }, /* TAS5130D1B */ \ - { USB_DEVICE(0x0c45, 0x60ab), }, /* TAS5110C1B */ \ - { USB_DEVICE(0x0c45, 0x60ac), }, \ - { USB_DEVICE(0x0c45, 0x60ae), }, \ - { USB_DEVICE(0x0c45, 0x60af), }, /* PAS202BCB */ \ - { USB_DEVICE(0x0c45, 0x60b0), }, \ - { USB_DEVICE(0x0c45, 0x60b2), }, \ - { USB_DEVICE(0x0c45, 0x60b3), }, \ - { USB_DEVICE(0x0c45, 0x60b8), }, \ - { USB_DEVICE(0x0c45, 0x60ba), }, \ - { USB_DEVICE(0x0c45, 0x60bb), }, \ - { USB_DEVICE(0x0c45, 0x60bc), }, \ - { USB_DEVICE(0x0c45, 0x60be), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \ { } \ }; @@ -177,16 +189,18 @@ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); /* I/O on registers in the bridge. Could be used by the sensor methods too */ +extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index); extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); /* NOTE: there are no exported debugging functions. To uniform the output you must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, - already included here, the argument being the struct device 'dev' of the - sensor structure. Do NOT use these macros before the sensor is attached or - the kernel will crash! However, you should not need to notify the user about - common errors or other messages, since this is done by the master module. + already included here, the argument being the struct device '&usbdev->dev' + of the sensor structure. Do NOT use these macros before the sensor is + attached or the kernel will crash! However, you should not need to notify + the user about common errors or other messages, since this is done by the + master module. */ /*****************************************************************************/ @@ -345,13 +359,6 @@ struct sn9c102_sensor { error code without rolling back. */ - const struct device* dev; - /* - This is the argument for dev_err(), dev_info() and dev_warn(). It - is used for debugging purposes. You must not access the struct - before the sensor is attached. - */ - const struct usb_device* usbdev; /* Points to the usb_device struct after the sensor is attached. diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c index 8775999b5aff..32ddf236cafe 100644 --- a/drivers/usb/media/sn9c102_tas5110c1b.c +++ b/drivers/usb/media/sn9c102_tas5110c1b.c @@ -2,7 +2,7 @@ * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c index 927eafdd8c73..a0728f0ae00c 100644 --- a/drivers/usb/media/sn9c102_tas5130d1b.c +++ b/drivers/usb/media/sn9c102_tas5130d1b.c @@ -2,7 +2,7 @@ * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * * Controllers * * * - * Copyright (C) 2004-2005 by Luca Risolia <luca.risolia@studio.unibo.it> * + * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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 * diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index bff9434c8e55..9937fc64c8bf 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -62,7 +62,6 @@ MODULE_LICENSE(W9968CF_MODULE_LICENSE); MODULE_SUPPORTED_DEVICE("Video"); static int ovmod_load = W9968CF_OVMOD_LOAD; -static int vppmod_load = W9968CF_VPPMOD_LOAD; static unsigned short simcams = W9968CF_SIMCAMS; static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = @@ -107,7 +106,6 @@ static unsigned int param_nv[24]; /* number of values per parameter */ #ifdef CONFIG_KMOD module_param(ovmod_load, bool, 0644); -module_param(vppmod_load, bool, 0444); #endif module_param(simcams, ushort, 0644); module_param_array(video_nr, short, ¶m_nv[0], 0444); @@ -150,18 +148,6 @@ MODULE_PARM_DESC(ovmod_load, "\ninto memory." "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." "\n"); -MODULE_PARM_DESC(vppmod_load, - "\n<0|1> Automatic 'w9968cf-vpp' module loading." - "\n0 disabled, 1 enabled." - "\nIf enabled, every time an application attempts to open a" - "\ncamera, 'insmod' searches for the video post-processing" - "\nmodule in the system and loads it automatically (if" - "\npresent). The optional 'w9968cf-vpp' module adds extra" - "\n image manipulation functions to the 'w9968cf' module,like" - "\nsoftware up-scaling,colour conversions and video decoding" - "\nfor very high frame rates." - "\nDefault value is "__MODULE_STRING(W9968CF_VPPMOD_LOAD)"." - "\n"); #endif MODULE_PARM_DESC(simcams, "\n<n> Number of cameras allowed to stream simultaneously." @@ -492,10 +478,6 @@ static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); static void w9968cf_release_resources(struct w9968cf_device*); -/* Intermodule communication */ -static int w9968cf_vppmod_detect(struct w9968cf_device*); -static void w9968cf_vppmod_release(struct w9968cf_device*); - /**************************************************************************** @@ -2737,9 +2719,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) cam->streaming = 0; cam->misconfigured = 0; - if (!w9968cf_vpp) - if ((err = w9968cf_vppmod_detect(cam))) - goto out; + w9968cf_adjust_configuration(cam); if ((err = w9968cf_allocate_memory(cam))) goto deallocate_memory; @@ -2766,7 +2746,6 @@ static int w9968cf_open(struct inode* inode, struct file* filp) deallocate_memory: w9968cf_deallocate_memory(cam); -out: DBG(2, "Failed to open the video device") up(&cam->dev_sem); up_read(&w9968cf_disconnect); @@ -2784,8 +2763,6 @@ static int w9968cf_release(struct inode* inode, struct file* filp) w9968cf_stop_transfer(cam); - w9968cf_vppmod_release(cam); - if (cam->disconnected) { w9968cf_release_resources(cam); up(&cam->dev_sem); @@ -3681,106 +3658,6 @@ static struct usb_driver w9968cf_usb_driver = { * Module init, exit and intermodule communication * ****************************************************************************/ -static int w9968cf_vppmod_detect(struct w9968cf_device* cam) -{ - if (!w9968cf_vpp) - if (vppmod_load) - request_module("w9968cf-vpp"); - - down(&w9968cf_vppmod_lock); - - if (!w9968cf_vpp) { - DBG(4, "Video post-processing module not detected") - w9968cf_adjust_configuration(cam); - goto out; - } - - if (!try_module_get(w9968cf_vpp->owner)) { - DBG(1, "Couldn't increment the reference count of " - "the video post-processing module") - up(&w9968cf_vppmod_lock); - return -ENOSYS; - } - - w9968cf_vpp->busy++; - - DBG(5, "Video post-processing module detected") - -out: - up(&w9968cf_vppmod_lock); - return 0; -} - - -static void w9968cf_vppmod_release(struct w9968cf_device* cam) -{ - down(&w9968cf_vppmod_lock); - - if (w9968cf_vpp && w9968cf_vpp->busy) { - module_put(w9968cf_vpp->owner); - w9968cf_vpp->busy--; - wake_up(&w9968cf_vppmod_wait); - DBG(5, "Video post-processing module released") - } - - up(&w9968cf_vppmod_lock); -} - - -int w9968cf_vppmod_register(struct w9968cf_vpp_t* vpp) -{ - down(&w9968cf_vppmod_lock); - - if (w9968cf_vpp) { - KDBG(1, "Video post-processing module already registered") - up(&w9968cf_vppmod_lock); - return -EINVAL; - } - - w9968cf_vpp = vpp; - w9968cf_vpp->busy = 0; - - KDBG(2, "Video post-processing module registered") - up(&w9968cf_vppmod_lock); - return 0; -} - - -int w9968cf_vppmod_deregister(struct w9968cf_vpp_t* vpp) -{ - down(&w9968cf_vppmod_lock); - - if (!w9968cf_vpp) { - up(&w9968cf_vppmod_lock); - return -EINVAL; - } - - if (w9968cf_vpp != vpp) { - KDBG(1, "Only the owner can unregister the video " - "post-processing module") - up(&w9968cf_vppmod_lock); - return -EINVAL; - } - - if (w9968cf_vpp->busy) { - KDBG(2, "Video post-processing module busy. Wait for it to be " - "released...") - up(&w9968cf_vppmod_lock); - wait_event(w9968cf_vppmod_wait, !w9968cf_vpp->busy); - w9968cf_vpp = NULL; - goto out; - } - - w9968cf_vpp = NULL; - - up(&w9968cf_vppmod_lock); - -out: - KDBG(2, "Video post-processing module unregistered") - return 0; -} - - static int __init w9968cf_module_init(void) { int err; @@ -3810,6 +3687,3 @@ static void __exit w9968cf_module_exit(void) module_init(w9968cf_module_init); module_exit(w9968cf_module_exit); - -EXPORT_SYMBOL(w9968cf_vppmod_register); -EXPORT_SYMBOL(w9968cf_vppmod_deregister); diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h index 8acbfe205bc7..47a6ff794171 100644 --- a/drivers/usb/media/w9968cf.h +++ b/drivers/usb/media/w9968cf.h @@ -195,7 +195,6 @@ enum w9968cf_vpp_flag { }; static struct w9968cf_vpp_t* w9968cf_vpp; -static DECLARE_MUTEX(w9968cf_vppmod_lock); static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ diff --git a/drivers/usb/media/w9968cf_vpp.h b/drivers/usb/media/w9968cf_vpp.h index 3f5317dc4c29..f3b91b782671 100644 --- a/drivers/usb/media/w9968cf_vpp.h +++ b/drivers/usb/media/w9968cf_vpp.h @@ -37,7 +37,4 @@ struct w9968cf_vpp_t { u8 busy; /* read-only flag: module is/is not in use */ }; -extern int w9968cf_vppmod_register(struct w9968cf_vpp_t*); -extern int w9968cf_vppmod_deregister(struct w9968cf_vpp_t*); - #endif /* _W9968CF_VPP_H_ */ diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 449b2501acf3..ad2f4cccd388 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -2093,6 +2093,8 @@ static void auerswald_disconnect (struct usb_interface *intf) static struct usb_device_id auerswald_ids [] = { { USB_DEVICE (ID_AUERSWALD, 0x00C0) }, /* COMpact 2104 USB */ { USB_DEVICE (ID_AUERSWALD, 0x00DB) }, /* COMpact 4410/2206 USB */ + { USB_DEVICE (ID_AUERSWALD, 0x00DC) }, /* COMpact 4406 DSL */ + { USB_DEVICE (ID_AUERSWALD, 0x00DD) }, /* COMpact 2204 USB */ { USB_DEVICE (ID_AUERSWALD, 0x00F1) }, /* Comfort 2000 System Telephone */ { USB_DEVICE (ID_AUERSWALD, 0x00F2) }, /* Comfort 1200 System Telephone */ { } /* Terminating entry */ diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 981d8a5fbfd9..331d4ae949ed 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -593,7 +593,7 @@ static struct file_operations ld_usb_fops = { /* * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with devfs and the driver core + * and to have the device registered with the driver core */ static struct usb_class_driver ld_usb_class = { .name = "ldusb%d", diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 541181695040..3094970615cb 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -916,6 +916,10 @@ static const struct usb_device_id products [] = { // Linksys USB200M Rev 2 USB_DEVICE (0x13b1, 0x0018), .driver_info = (unsigned long) &ax88772_info, +}, { + // 0Q0 cable ethernet + USB_DEVICE (0x1557, 0x7720), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index da46b351e188..dc7a069503e0 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -32,7 +32,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.05" +#define DRIVER_VERSION "v0.06" #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" /* @@ -55,11 +55,15 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ - { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ - { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ - { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ + { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ + { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ + { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ { } /* Terminating Entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 10bc1bf23b35..f2b4ca8692d8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -476,10 +476,16 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) }, { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 00d45f8600de..ca40f16370f1 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -31,9 +31,14 @@ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ + /* www.irtrans.de device */ #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ + +/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ +#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ + /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ @@ -51,6 +56,12 @@ #define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ /* + * PCDJ use ftdi based dj-controllers. The following PID is for their DAC-2 device + * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen) + * (the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_PCDJ_DAC2_PID 0xFA88 + +/* * The following are the values for the Matrix Orbital LCD displays, * which are the FT232BM ( similar to the 8U232AM ) */ @@ -215,8 +226,10 @@ * Definitions for ATIK Instruments astronomical USB based cameras * Check it at http://www.atik-instruments.com/ */ -#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Camera */ -#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Camera */ +#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ +#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ +#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ +#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ /* * Protego product ids @@ -365,6 +378,12 @@ #define POSIFLEX_VID 0x0d3a /* Vendor ID */ #define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ +/* + * Westrex International devices submitted by Cory Lee + */ +#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ +#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 0eb883f44ada..e8e575e037c1 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -73,7 +73,9 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, - { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, + { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, + { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID ) }, + { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 21d434d81813..1807087a76e3 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -64,3 +64,10 @@ /* Nokia CA-42 Cable */ #define NOKIA_CA42_VENDOR_ID 0x078b #define NOKIA_CA42_PRODUCT_ID 0x1234 + +/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */ +#define CA_42_CA42_VENDOR_ID 0x10b5 +#define CA_42_CA42_PRODUCT_ID 0xac70 + +#define SAGEM_VENDOR_ID 0x079b +#define SAGEM_PRODUCT_ID 0x0027 diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 5b06f9240d05..ab173b30076e 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -45,6 +45,12 @@ #include "debug.h" #include "transport.h" +#define RIO_MSC 0x08 +#define RIOP_INIT "RIOP\x00\x01\x08" +#define RIOP_INIT_LEN 7 +#define RIO_SEND_LEN 40 +#define RIO_RECV_LEN 0x200 + /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target * mode */ int usb_stor_euscsi_init(struct us_data *us) @@ -91,3 +97,70 @@ int usb_stor_ucr61s2b_init(struct us_data *us) return (res ? -1 : 0); } + +/* Place the Rio Karma into mass storage mode. + * + * The initialization begins by sending 40 bytes starting + * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte + * packet with the high four bits set and everything else null. + * + * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response + * must be read, but we must loop until byte 5 in the response is 0x08, + * indicating success. */ +int rio_karma_init(struct us_data *us) +{ + int result, partial; + char *recv; + unsigned long timeout; + + // us->iobuf is big enough to hold cmd but not receive + if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL))) + goto die_nomem; + + US_DEBUGP("Initializing Karma...\n"); + + memset(us->iobuf, 0, RIO_SEND_LEN); + memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN); + + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, + us->iobuf, RIO_SEND_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto die; + + result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, + recv, RIO_RECV_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto die; + + us->iobuf[4] = 0x80; + us->iobuf[5] = 0; + timeout = jiffies + msecs_to_jiffies(3000); + for (;;) { + US_DEBUGP("Sending init command\n"); + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, + us->iobuf, RIO_SEND_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto die; + + result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, + recv, RIO_RECV_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto die; + + if (recv[5] == RIO_MSC) + break; + if (time_after(jiffies, timeout)) + goto die; + msleep(10); + } + US_DEBUGP("Karma initialized.\n"); + kfree(recv); + return 0; + +die: + kfree(recv); +die_nomem: + US_DEBUGP("Could not initialize karma.\n"); + return USB_STOR_TRANSPORT_FAILED; +} + diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 4c1b2bd2e2e4..f9907a5cf129 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -48,3 +48,4 @@ int usb_stor_euscsi_init(struct us_data *us); /* This function is required to activate all four slots on the UCR-61S2B * flash reader */ int usb_stor_ucr61s2b_init(struct us_data *us); +int rio_karma_init(struct us_data *us); diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index b28151d1b609..b1ec4a718547 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c @@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(usb_usual_check_type); static int usu_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int type; + unsigned long type; int rc; unsigned long flags; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index dc301e567cfc..ee958f986eb8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -145,6 +145,11 @@ UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, US_SC_DEVICE, US_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), +UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, + "Rio", + "Rio Karma", + US_SC_SCSI, US_PR_BULK, rio_karma_init, 0), + /* Patch submitted by Philipp Friedrich <philipp@void.at> */ UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, "Kyocera", @@ -424,11 +429,11 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), /* This entry is needed because the device reports Sub=ff */ -UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500, - "Sony", - "DSC-T1", - US_SC_8070, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN ), +UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0600, + "Sony", + "DSC-T1/T5", + US_SC_8070, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), /* Reported by wim@geeks.nl */ diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 5d02f16b7d0e..4de9fb56ebfc 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -234,7 +234,7 @@ static struct file_operations skel_fops = { /* * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with devfs and the driver core + * and to have the device registered with the driver core */ static struct usb_class_driver skel_class = { .name = "skel%d", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3e153d313bb0..e64ed16bd42f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -525,11 +525,6 @@ config FB_GBE_MEM This is the amount of memory reserved for the framebuffer, which can be any value between 1MB and 8MB. -config BUS_I2C - bool - depends on (FB = y) && VISWS - default y - config FB_SUN3 bool "Sun3 framebuffer support" depends on (FB = y) && (SUN3 || SUN3X) && BROKEN diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index b2187175d03f..6761b68c35e9 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -116,9 +116,10 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) int ret = 0; memset(&var->transp, 0, sizeof(var->transp)); - memset(&var->red, 0, sizeof(var->red)); - memset(&var->green, 0, sizeof(var->green)); - memset(&var->blue, 0, sizeof(var->blue)); + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; switch (var->bits_per_pixel) { case 1: @@ -133,34 +134,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) var->blue.offset = 0; break; case 16: - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - if (fb->panel->cntl & CNTL_BGR) { - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - } else { - var->red.offset = 0; - var->green.offset = 5; - var->blue.offset = 11; - } + var->red.length = 5; + var->blue.length = 5; + /* + * Green length can be 5 or 6 depending whether + * we're operating in RGB555 or RGB565 mode. + */ + if (var->green.length != 5 && var->green.length != 6) + var->green.length = 6; break; case 32: if (fb->panel->cntl & CNTL_LCDTFT) { var->red.length = 8; var->green.length = 8; var->blue.length = 8; - - if (fb->panel->cntl & CNTL_BGR) { - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - } else { - var->red.offset = 0; - var->green.offset = 8; - var->blue.offset = 16; - } break; } default: @@ -168,6 +155,23 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) break; } + /* + * >= 16bpp displays have separate colour component bitfields + * encoded in the pixel data. Calculate their position from + * the bitfield length defined above. + */ + if (ret == 0 && var->bits_per_pixel >= 16) { + if (fb->panel->cntl & CNTL_BGR) { + var->blue.offset = 0; + var->green.offset = var->blue.offset + var->blue.length; + var->red.offset = var->green.offset + var->green.length; + } else { + var->red.offset = 0; + var->green.offset = var->red.offset + var->red.length; + var->blue.offset = var->green.offset + var->green.length; + } + } + return ret; } diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 996d543d6609..9d996f2c10d5 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -50,3 +50,11 @@ config BACKLIGHT_CORGI If you have a Sharp Zaurus SL-C7xx, say y to enable the backlight driver. +config BACKLIGHT_HP680 + tristate "HP Jornada 680 Backlight Driver" + depends on BACKLIGHT_DEVICE && SH_HP6XX + default y + help + If you have a HP Jornada 680, say y to enable the + backlight driver. + diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 4af321fae390..744210c38e74 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o +obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 9d5015e99372..bd39bbd88d41 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -13,7 +13,6 @@ #include <linux/ctype.h> #include <linux/err.h> #include <linux/fb.h> -#include <asm/bug.h> static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c new file mode 100644 index 000000000000..95da4c9ed1f1 --- /dev/null +++ b/drivers/video/backlight/hp680_bl.c @@ -0,0 +1,189 @@ +/* + * Backlight Driver for HP Jornada 680 + * + * Copyright (c) 2005 Andriy Skulysh + * + * Based on Sharp's Corgi Backlight Driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/spinlock.h> +#include <linux/fb.h> +#include <linux/backlight.h> + +#include <asm/cpu/dac.h> +#include <asm/hp6xx/hp6xx.h> +#include <asm/hd64461/hd64461.h> + +#define HP680_MAX_INTENSITY 255 +#define HP680_DEFAULT_INTENSITY 10 + +static int hp680bl_powermode = FB_BLANK_UNBLANK; +static int current_intensity = 0; +static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; + +static void hp680bl_send_intensity(int intensity) +{ + unsigned long flags; + + if (hp680bl_powermode != FB_BLANK_UNBLANK) + intensity = 0; + + spin_lock_irqsave(&bl_lock, flags); + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + spin_unlock_irqrestore(&bl_lock, flags); +} + +static void hp680bl_blank(int blank) +{ + u16 v; + + switch(blank) { + + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + if (hp680bl_powermode == FB_BLANK_UNBLANK) { + hp680bl_send_intensity(0); + hp680bl_powermode = blank; + sh_dac_disable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v |= HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + } + break; + case FB_BLANK_UNBLANK: + if (hp680bl_powermode != FB_BLANK_UNBLANK) { + sh_dac_enable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v &= ~HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + hp680bl_powermode = blank; + hp680bl_send_intensity(current_intensity); + } + break; + } +} + +#ifdef CONFIG_PM +static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level) +{ + if (level == SUSPEND_POWER_DOWN) + hp680bl_blank(FB_BLANK_POWERDOWN); + return 0; +} + +static int hp680bl_resume(struct device *dev, u32 level) +{ + if (level == RESUME_POWER_ON) + hp680bl_blank(FB_BLANK_UNBLANK); + return 0; +} +#else +#define hp680bl_suspend NULL +#define hp680bl_resume NULL +#endif + + +static int hp680bl_set_power(struct backlight_device *bd, int state) +{ + hp680bl_blank(state); + return 0; +} + +static int hp680bl_get_power(struct backlight_device *bd) +{ + return hp680bl_powermode; +} + +static int hp680bl_set_intensity(struct backlight_device *bd, int intensity) +{ + if (intensity > HP680_MAX_INTENSITY) + intensity = HP680_MAX_INTENSITY; + hp680bl_send_intensity(intensity); + current_intensity = intensity; + return 0; +} + +static int hp680bl_get_intensity(struct backlight_device *bd) +{ + return current_intensity; +} + +static struct backlight_properties hp680bl_data = { + .owner = THIS_MODULE, + .get_power = hp680bl_get_power, + .set_power = hp680bl_set_power, + .max_brightness = HP680_MAX_INTENSITY, + .get_brightness = hp680bl_get_intensity, + .set_brightness = hp680bl_set_intensity, +}; + +static struct backlight_device *hp680_backlight_device; + +static int __init hp680bl_probe(struct device *dev) +{ + hp680_backlight_device = backlight_device_register ("hp680-bl", + NULL, &hp680bl_data); + if (IS_ERR (hp680_backlight_device)) + return PTR_ERR (hp680_backlight_device); + + hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY); + + return 0; +} + +static int hp680bl_remove(struct device *dev) +{ + backlight_device_unregister(hp680_backlight_device); + + return 0; +} + +static struct device_driver hp680bl_driver = { + .name = "hp680-bl", + .bus = &platform_bus_type, + .probe = hp680bl_probe, + .remove = hp680bl_remove, + .suspend = hp680bl_suspend, + .resume = hp680bl_resume, +}; + +static struct platform_device hp680bl_device = { + .name = "hp680-bl", + .id = -1, +}; + +static int __init hp680bl_init(void) +{ + int ret; + + ret=driver_register(&hp680bl_driver); + if (!ret) { + ret = platform_device_register(&hp680bl_device); + if (ret) + driver_unregister(&hp680bl_driver); + } + return ret; +} + +static void __exit hp680bl_exit(void) +{ + platform_device_unregister(&hp680bl_device); + driver_unregister(&hp680bl_driver); +} + +module_init(hp680bl_init); +module_exit(hp680bl_exit); + +MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>"); +MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 68c690605aa7..9e32485ee7bb 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -13,7 +13,6 @@ #include <linux/ctype.h> #include <linux/err.h> #include <linux/fb.h> -#include <asm/bug.h> static ssize_t lcd_show_power(struct class_device *cdev, char *buf) { diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index a7bcd17112c0..0339f5640a78 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -30,10 +30,11 @@ #define STI_DRIVERVERSION "Version 0.9a" -struct sti_struct *default_sti; +struct sti_struct *default_sti __read_mostly; -static int num_sti_roms; /* # of STI ROMS found */ -static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */ +/* number of STI ROMS found and their ptrs to each struct */ +static int num_sti_roms __read_mostly; +static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly; /* The colour indices used by STI are @@ -266,7 +267,7 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest) -static char default_sti_path[21]; +static char default_sti_path[21] __read_mostly; #ifndef MODULE static int __init sti_setup(char *str) @@ -414,10 +415,10 @@ sti_init_glob_cfg(struct sti_struct *sti, if (!sti->sti_mem_request) sti->sti_mem_request = 256; /* STI default */ - glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); - glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); - save_addr = kmalloc(save_addr_size, GFP_KERNEL); - sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL); + glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); + glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); + save_addr = kzalloc(save_addr_size, GFP_KERNEL); + sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { kfree(glob_cfg); @@ -427,11 +428,6 @@ sti_init_glob_cfg(struct sti_struct *sti, return -ENOMEM; } - memset(glob_cfg, 0, sizeof(*glob_cfg)); - memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext)); - memset(save_addr, 0, save_addr_size); - memset(sti_mem_addr, 0, sti->sti_mem_request); - glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); glob_cfg->save_addr = STI_PTR(save_addr); for (i=0; i<8; i++) { @@ -502,9 +498,9 @@ sti_init_glob_cfg(struct sti_struct *sti, #ifdef CONFIG_FB struct sti_cooked_font * __init -sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) +sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { - struct font_desc *fbfont; + const struct font_desc *fbfont; unsigned int size, bpc; void *dest; struct sti_rom_font *nf; @@ -525,10 +521,9 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) size = bpc * 256; size += sizeof(struct sti_rom_font); - nf = kmalloc(size, GFP_KERNEL); + nf = kzalloc(size, GFP_KERNEL); if (!nf) return NULL; - memset(nf, 0, size); nf->first_char = 0; nf->last_char = 255; @@ -544,7 +539,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) dest += sizeof(struct sti_rom_font); memcpy(dest, fbfont->data, bpc*256); - cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); + cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font) { kfree(nf); return NULL; @@ -559,7 +554,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) } #else struct sti_cooked_font * __init -sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name) +sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { return NULL; } @@ -617,7 +612,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom, struct sti_rom_font *raw_font, *font_start; struct sti_cooked_font *cooked_font; - cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); + cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font) return 0; @@ -631,7 +626,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom, while (raw_font->next_font) { raw_font = ((void *)font_start) + (raw_font->next_font); - cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); + cooked_font->next_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font->next_font) return 1; @@ -668,10 +663,9 @@ sti_bmode_font_raw(struct sti_cooked_font *f) unsigned char *n, *p, *q; int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - n = kmalloc (4*size, GFP_KERNEL); + n = kzalloc (4*size, GFP_KERNEL); if (!n) return NULL; - memset (n, 0, 4*size); p = n + 3; q = (unsigned char *)f->raw; while (size--) { @@ -816,13 +810,12 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd return NULL; } - sti = kmalloc(sizeof(*sti), GFP_KERNEL); + sti = kzalloc(sizeof(*sti), GFP_KERNEL); if (!sti) { printk(KERN_ERR "Not enough memory !\n"); return NULL; } - memset(sti, 0, sizeof(*sti)); spin_lock_init(&sti->lock); test_rom: @@ -1035,7 +1028,7 @@ static struct parisc_driver pa_sti_driver = { * sti_init_roms() - detects all STI ROMs and stores them in sti_roms[] */ -static int sticore_initialized; +static int sticore_initialized __read_mostly; static void __init sti_init_roms(void) { diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 2b972461a030..0ae0a97b0fed 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -1665,7 +1665,6 @@ static int __devinit cyblafb_init(void) } #endif output("CyblaFB version %s initializing\n", VERSION); - return pci_module_init(&cyblafb_pci_driver); return pci_register_driver(&cyblafb_pci_driver); } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d2dede6ed3e5..996c7b58564e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1550,6 +1550,7 @@ int fb_get_options(char *name, char **option) return retval; } +#ifndef MODULE /** * video_setup - process command line options * @options: string of options @@ -1593,6 +1594,7 @@ static int __init video_setup(char *options) return 0; } __setup("video=", video_setup); +#endif /* * Visible symbols for modules diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index bd410e06db73..e3c8b5f1ca76 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -191,11 +191,11 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) u8 *edid = NULL; int i; - DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); - if (conn < 4) { + DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1); + if (conn < par->ddc_num) { for (i = 0; i < 3; i++) { /* Do the real work */ - edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); + edid = i810_do_probe_i2c_edid(&par->chan[conn]); if (edid) break; } diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index 6c187d5fe951..579195c2bea3 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h @@ -280,6 +280,7 @@ struct i810fb_par { u32 blit_bpp; u32 ovract; u32 cur_state; + u32 ddc_num; int mtrr_reg; u16 bltcntl; u8 interlace; diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 266d0ab92663..d8467c03b49f 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -149,6 +149,7 @@ static int vyres __devinitdata; static int sync __devinitdata; static int extvga __devinitdata; static int dcolor __devinitdata; +static int ddc3 __devinitdata = 2; /*------------------------------------------------------------*/ @@ -1763,6 +1764,8 @@ static void __devinit i810_init_defaults(struct i810fb_par *par, if (sync) par->dev_flags |= ALWAYS_SYNC; + par->ddc_num = ddc3; + if (bpp < 8) bpp = 8; @@ -1885,7 +1888,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) int found = 0; #ifdef CONFIG_FB_I810_I2C int i; - int err; + int err = 1; struct i810fb_par *par = info->par; #endif @@ -1895,8 +1898,8 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) #ifdef CONFIG_FB_I810_I2C i810_create_i2c_busses(par); - for (i = 0; i < 4; i++) { - err = i810_probe_i2c_connector(info, &par->edid, i+1); + for (i = 0; i < par->ddc_num + 1; i++) { + err = i810_probe_i2c_connector(info, &par->edid, i); if (!err) break; } @@ -1983,6 +1986,8 @@ static int __devinit i810fb_setup(char *options) vsync2 = simple_strtoul(this_opt+7, NULL, 0); else if (!strncmp(this_opt, "dcolor", 6)) dcolor = 1; + else if (!strncmp(this_opt, "ddc3", 4)) + ddc3 = 3; else mode_option = this_opt; } @@ -2190,6 +2195,8 @@ MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" module_param(dcolor, bool, 0); MODULE_PARM_DESC(dcolor, "use DirectColor visuals" " (default = 0 = TrueColor)"); +module_param(ddc3, bool, 0); +MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)"); module_param(mode_option, charp, 0); MODULE_PARM_DESC(mode_option, "Specify initial video mode"); diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index dbcb8962e57d..a7c4e5e8ead6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -138,6 +138,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO, diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index f3927b6cda9d..f5361cd8ccce 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -30,7 +30,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <asm/bug.h> #include <asm/io.h> #include <asm/system.h> diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 25148de5fe67..eeeac924b500 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -27,7 +27,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <asm/bug.h> #include <asm/io.h> #include <asm/system.h> diff --git a/fs/9p/Makefile b/fs/9p/Makefile index 3d023089707e..2f4ce43f7b6c 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_9P_FS) := 9p2000.o conv.o \ vfs_super.o \ vfs_inode.o \ + vfs_addr.o \ vfs_file.o \ vfs_dir.o \ vfs_dentry.o \ diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 32a9f99154e2..bf1f10067960 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -116,13 +116,19 @@ static void buf_put_int64(struct cbuf *buf, u64 val) } } -static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) +static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) { + char *ret; + + ret = NULL; if (buf_check_size(buf, slen + 2)) { buf_put_int16(buf, slen); + ret = buf->p; memcpy(buf->p, s, slen); buf->p += slen; } + + return ret; } static inline void buf_put_string(struct cbuf *buf, const char *s) @@ -430,15 +436,19 @@ static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) static void v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) { - if (data) { - str->len = strlen(data); - str->str = bufp->p; - } else { - str->len = 0; - str->str = NULL; - } + int len; + char *s; + + if (data) + len = strlen(data); + else + len = 0; - buf_put_stringn(bufp, data, str->len); + s = buf_put_stringn(bufp, data, len); + if (str) { + str->len = len; + str->str = s; + } } static int diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 945cb368d451..ea1134eb47c8 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c @@ -471,10 +471,13 @@ static void v9fs_write_work(void *a) } spin_lock(&m->lock); - req = - list_entry(m->unsent_req_list.next, struct v9fs_req, +again: + req = list_entry(m->unsent_req_list.next, struct v9fs_req, req_list); list_move_tail(&req->req_list, &m->req_list); + if (req->err == ERREQFLUSH) + goto again; + m->wbuf = req->tcall->sdata; m->wsize = req->tcall->size; m->wpos = 0; @@ -525,7 +528,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) struct v9fs_str *ename; tag = req->tag; - if (req->rcall->id == RERROR && !req->err) { + if (!req->err && req->rcall->id == RERROR) { ecode = req->rcall->params.rerror.errno; ename = &req->rcall->params.rerror.error; @@ -551,7 +554,10 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) req->err = -EIO; } - if (req->cb && req->err != ERREQFLUSH) { + if (req->err == ERREQFLUSH) + return; + + if (req->cb) { dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n", req->tcall, req->rcall); @@ -812,6 +818,7 @@ v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err) struct v9fs_mux_rpc *r; if (err == ERREQFLUSH) { + kfree(rc); dprintk(DEBUG_MUX, "err req flush\n"); return; } diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index c78502ad00ed..69cf2905dc90 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -39,6 +39,7 @@ */ extern struct file_system_type v9fs_fs_type; +extern struct address_space_operations v9fs_addr_operations; extern struct file_operations v9fs_file_operations; extern struct file_operations v9fs_dir_operations; extern struct dentry_operations v9fs_dentry_operations; diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c new file mode 100644 index 000000000000..8100fb5171b7 --- /dev/null +++ b/fs/9p/vfs_addr.c @@ -0,0 +1,109 @@ +/* + * linux/fs/9p/vfs_addr.c + * + * This file contians vfs address (mmap) ops for 9P2000. + * + * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com> + * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/stat.h> +#include <linux/string.h> +#include <linux/smp_lock.h> +#include <linux/inet.h> +#include <linux/version.h> +#include <linux/pagemap.h> +#include <linux/idr.h> + +#include "debug.h" +#include "v9fs.h" +#include "9p.h" +#include "v9fs_vfs.h" +#include "fid.h" + +/** + * v9fs_vfs_readpage - read an entire page in from 9P + * + * @file: file being read + * @page: structure to page + * + */ + +static int v9fs_vfs_readpage(struct file *filp, struct page *page) +{ + char *buffer = NULL; + int retval = -EIO; + loff_t offset = page_offset(page); + int count = PAGE_CACHE_SIZE; + struct inode *inode = filp->f_dentry->d_inode; + struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); + int rsize = v9ses->maxdata - V9FS_IOHDRSZ; + struct v9fs_fid *v9f = filp->private_data; + struct v9fs_fcall *fcall = NULL; + int fid = v9f->fid; + int total = 0; + int result = 0; + + buffer = kmap(page); + do { + if (count < rsize) + rsize = count; + + result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall); + + if (result < 0) { + printk(KERN_ERR "v9fs_t_read returned %d\n", + result); + + kfree(fcall); + goto UnmapAndUnlock; + } else + offset += result; + + memcpy(buffer, fcall->params.rread.data, result); + + count -= result; + buffer += result; + total += result; + + kfree(fcall); + + if (result < rsize) + break; + } while (count); + + memset(buffer, 0, count); + flush_dcache_page(page); + SetPageUptodate(page); + retval = 0; + +UnmapAndUnlock: + kunmap(page); + unlock_page(page); + return retval; +} + +struct address_space_operations v9fs_addr_operations = { + .readpage = v9fs_vfs_readpage, +}; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 6852f0eb96ed..c7e14d917215 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -289,6 +289,9 @@ v9fs_file_write(struct file *filp, const char __user * data, total += result; } while (count); + if(inode->i_mapping->nrpages) + invalidate_inode_pages2(inode->i_mapping); + return total; } @@ -299,4 +302,5 @@ struct file_operations v9fs_file_operations = { .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, + .mmap = generic_file_mmap, }; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index a17b28854288..63e5b0398e8b 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -177,6 +177,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) inode->i_blocks = 0; inode->i_rdev = 0; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_mapping->a_ops = &v9fs_addr_operations; switch (mode & S_IFMT) { case S_IFIFO: @@ -885,8 +886,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) } /* copy extension buffer into buffer */ - if (fcall->params.rstat.stat.extension.len < buflen) - buflen = fcall->params.rstat.stat.extension.len; + if (fcall->params.rstat.stat.extension.len+1 < buflen) + buflen = fcall->params.rstat.stat.extension.len + 1; memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); buffer[buflen-1] = 0; @@ -950,7 +951,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) if (!link) link = ERR_PTR(-ENOMEM); else { - len = v9fs_readlink(dentry, link, strlen(link)); + len = v9fs_readlink(dentry, link, PATH_MAX); if (len < 0) { __putname(link); diff --git a/fs/Kconfig b/fs/Kconfig index ef78e3a42d32..e9749b0eecd8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -883,8 +883,6 @@ config CONFIGFS_FS Both sysfs and configfs can and should exist together on the same system. One is not a replacement for the other. - If unsure, say N. - endmenu menu "Miscellaneous filesystems" @@ -1327,7 +1325,7 @@ config UFS_FS config UFS_FS_WRITE bool "UFS file system write support (DANGEROUS)" - depends on UFS_FS && EXPERIMENTAL + depends on UFS_FS && EXPERIMENTAL && BROKEN help Say Y here if you want to try writing to UFS partitions. This is experimental, so you should back up your UFS partitions beforehand. @@ -411,6 +411,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page /** * bio_add_pc_page - attempt to add page to bio + * @q: the target queue * @bio: destination bio * @page: page to add * @len: vec entry length diff --git a/fs/buffer.c b/fs/buffer.c index 3dc712f29d2d..62cfd17dc5fe 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1022,6 +1022,7 @@ try_again: bh->b_state = 0; atomic_set(&bh->b_count, 0); + bh->b_private = NULL; bh->b_size = size; /* Link the buffer to its page */ @@ -2866,22 +2867,22 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) else if (test_set_buffer_locked(bh)) continue; - get_bh(bh); if (rw == WRITE || rw == SWRITE) { if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; + get_bh(bh); submit_bh(WRITE, bh); continue; } } else { if (!buffer_uptodate(bh)) { bh->b_end_io = end_buffer_read_sync; + get_bh(bh); submit_bh(rw, bh); continue; } } unlock_buffer(bh); - put_bh(bh); } } @@ -3050,6 +3051,66 @@ asmlinkage long sys_bdflush(int func, long data) } /* + * Migration function for pages with buffers. This function can only be used + * if the underlying filesystem guarantees that no other references to "page" + * exist. + */ +#ifdef CONFIG_MIGRATION +int buffer_migrate_page(struct page *newpage, struct page *page) +{ + struct address_space *mapping = page->mapping; + struct buffer_head *bh, *head; + + if (!mapping) + return -EAGAIN; + + if (!page_has_buffers(page)) + return migrate_page(newpage, page); + + head = page_buffers(page); + + if (migrate_page_remove_references(newpage, page, 3)) + return -EAGAIN; + + bh = head; + do { + get_bh(bh); + lock_buffer(bh); + bh = bh->b_this_page; + + } while (bh != head); + + ClearPagePrivate(page); + set_page_private(newpage, page_private(page)); + set_page_private(page, 0); + put_page(page); + get_page(newpage); + + bh = head; + do { + set_bh_page(bh, newpage, bh_offset(bh)); + bh = bh->b_this_page; + + } while (bh != head); + + SetPagePrivate(newpage); + + migrate_page_copy(newpage, page); + + bh = head; + do { + unlock_buffer(bh); + put_bh(bh); + bh = bh->b_this_page; + + } while (bh != head); + + return 0; +} +EXPORT_SYMBOL(buffer_migrate_page); +#endif + +/* * Buffer-head allocation */ static kmem_cache_t *bh_cachep; diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 943ef9b82244..d335015473a5 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,11 @@ +Version 1.40 +------------ +Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance +of readpages by eliminating one extra memcpy. Allow update of file size +from remote server even if file is open for write as long as mount is +directio. Recognize share mode security and send NTLM encrypted password +on tree connect if share mode negotiated. + Version 1.39 ------------ Defer close of a file handle slightly if pending writes depend on that handle @@ -7,6 +15,8 @@ Fix SFU style symlinks and mknod needed for servers which do not support the CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative dentries so files that the client sees as deleted but that later get created on the server will be recognized. Add client side permission check on setattr. +Timeout stuck requests better (where server has never responded or sent corrupt +responses) Version 1.38 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index e5d09a2fc7a5..b0070d1b149d 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -436,7 +436,17 @@ A partial list of the supported mount options follows: SFU does). In the future the bottom 9 bits of the mode mode also will be emulated using queries of the security descriptor (ACL). - +sec Security mode. Allowed values are: + none attempt to connection as a null user (no name) + krb5 Use Kerberos version 5 authentication + krb5i Use Kerberos authentication and packet signing + ntlm Use NTLM password hashing (default) + ntlmi Use NTLM password hashing with signing (if + /proc/fs/cifs/PacketSigningEnabled on or if + server requires signing also can be the default) + ntlmv2 Use NTLMv2 password hashing + ntlmv2i Use NTLMv2 password hashing with packet signing + The mount.cifs mount helper also accepts a few mount options before -o including: diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 22a444a3fe4c..f4124a32bef8 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -219,6 +219,10 @@ cifs_stats_write(struct file *file, const char __user *buffer, if (c == '1' || c == 'y' || c == 'Y' || c == '0') { read_lock(&GlobalSMBSeslock); +#ifdef CONFIG_CIFS_STATS2 + atomic_set(&totBufAllocCount, 0); + atomic_set(&totSmBufAllocCount, 0); +#endif /* CONFIG_CIFS_STATS2 */ list_for_each(tmp, &GlobalTreeConnectionList) { tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); @@ -276,6 +280,14 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, smBufAllocCount.counter,cifs_min_small); length += item_length; buf += item_length; +#ifdef CONFIG_CIFS_STATS2 + item_length = sprintf(buf, "Total Large %d Small %d Allocations\n", + atomic_read(&totBufAllocCount), + atomic_read(&totSmBufAllocCount)); + length += item_length; + buf += item_length; +#endif /* CONFIG_CIFS_STATS2 */ + item_length = sprintf(buf,"Operations (MIDs): %d\n", midCount.counter); @@ -389,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read; static write_proc_t ntlmv2_enabled_write; static read_proc_t packet_signing_enabled_read; static write_proc_t packet_signing_enabled_write; -static read_proc_t quotaEnabled_read; -static write_proc_t quotaEnabled_write; +static read_proc_t experimEnabled_read; +static write_proc_t experimEnabled_write; static read_proc_t linuxExtensionsEnabled_read; static write_proc_t linuxExtensionsEnabled_write; @@ -430,9 +442,9 @@ cifs_proc_init(void) pde->write_proc = oplockEnabled_write; pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs, - quotaEnabled_read, NULL); + experimEnabled_read, NULL); if (pde) - pde->write_proc = quotaEnabled_write; + pde->write_proc = experimEnabled_write; pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs, linuxExtensionsEnabled_read, NULL); @@ -574,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer, } static int -quotaEnabled_read(char *page, char **start, off_t off, +experimEnabled_read(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; len = sprintf(page, "%d\n", experimEnabled); -/* could also check if quotas are enabled in kernel - as a whole first */ + len -= off; *start = page + off; @@ -596,21 +607,23 @@ quotaEnabled_read(char *page, char **start, off_t off, return len; } static int -quotaEnabled_write(struct file *file, const char __user *buffer, +experimEnabled_write(struct file *file, const char __user *buffer, unsigned long count, void *data) { - char c; - int rc; + char c; + int rc; - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - experimEnabled = 0; - else if (c == '1' || c == 'y' || c == 'Y') - experimEnabled = 1; + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + experimEnabled = 0; + else if (c == '1' || c == 'y' || c == 'Y') + experimEnabled = 1; + else if (c == '2') + experimEnabled = 2; - return count; + return count; } static int @@ -620,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off, int len; len = sprintf(page, "%d\n", linuxExtEnabled); -/* could also check if quotas are enabled in kernel - as a whole first */ len -= off; *start = page + off; diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index f799f6f0e729..ad58eb0c4d6d 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -24,9 +24,10 @@ #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ -#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ -#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ +#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ +#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ #define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ +#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h new file mode 100644 index 000000000000..d0776ac2b804 --- /dev/null +++ b/fs/cifs/cifsacl.h @@ -0,0 +1,38 @@ +/* + * fs/cifs/cifsacl.h + * + * Copyright (c) International Business Machines Corp., 2005 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CIFSACL_H +#define _CIFSACL_H + +struct cifs_sid { + __u8 revision; /* revision level */ + __u8 num_subauths; + __u8 authority[6]; + __u32 sub_auth[4]; + /* next sub_auth if any ... */ +} __attribute__((packed)); + +/* everyone */ +extern const struct cifs_sid sid_everyone; +/* group users */ +extern const struct cifs_sid sid_user; + +#endif /* _CIFSACL_H */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index fe2bb7c4c912..a2c24858d40f 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifsencrypt.c * - * Copyright (C) International Business Machines Corp., 2003 + * Copyright (C) International Business Machines Corp., 2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -82,6 +82,59 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server, return rc; } +static int cifs_calc_signature2(const struct kvec * iov, int n_vec, + const char * key, char * signature) +{ + struct MD5Context context; + + if((iov == NULL) || (signature == NULL)) + return -EINVAL; + + MD5Init(&context); + MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); + +/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */ + + MD5Final(signature,&context); + + return -EOPNOTSUPP; +/* return 0; */ +} + + +int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server, + __u32 * pexpected_response_sequence_number) +{ + int rc = 0; + char smb_signature[20]; + struct smb_hdr * cifs_pdu = iov[0].iov_base; + + if((cifs_pdu == NULL) || (server == NULL)) + return -EINVAL; + + if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) + return rc; + + spin_lock(&GlobalMid_Lock); + cifs_pdu->Signature.Sequence.SequenceNumber = + cpu_to_le32(server->sequence_number); + cifs_pdu->Signature.Sequence.Reserved = 0; + + *pexpected_response_sequence_number = server->sequence_number++; + server->sequence_number++; + spin_unlock(&GlobalMid_Lock); + + rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key, + smb_signature); + if(rc) + memset(cifs_pdu->Signature.SecuritySignature, 0, 8); + else + memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); + + return rc; + +} + int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, __u32 expected_sequence_number) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e10213b7541e..79eeccd0437f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -513,6 +513,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, return written; } +static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) +{ + /* origin == SEEK_END => we must revalidate the cached file length */ + if (origin == 2) { + int retval = cifs_revalidate(file->f_dentry); + if (retval < 0) + return (loff_t)retval; + } + return remote_llseek(file, offset, origin); +} + static struct file_system_type cifs_fs_type = { .owner = THIS_MODULE, .name = "cifs", @@ -586,6 +597,7 @@ struct file_operations cifs_file_ops = { .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, + .llseek = cifs_llseek, #ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ @@ -609,7 +621,7 @@ struct file_operations cifs_file_direct_ops = { #ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ - + .llseek = cifs_llseek, #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ @@ -627,6 +639,7 @@ struct file_operations cifs_file_nobrl_ops = { .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, + .llseek = cifs_llseek, #ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ @@ -649,7 +662,7 @@ struct file_operations cifs_file_direct_nobrl_ops = { #ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ - + .llseek = cifs_llseek, #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ @@ -733,7 +746,7 @@ cifs_init_request_bufs(void) kmem_cache_destroy(cifs_req_cachep); return -ENOMEM; } - /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and + /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and almost all handle based requests (but not write response, nor is it sufficient for path based requests). A smaller size would have been more efficient (compacting multiple slab items on one 4k page) @@ -742,7 +755,8 @@ cifs_init_request_bufs(void) efficient to alloc 1 per page off the slab compared to 17K (5page) alloc of large cifs buffers even when page debugging is on */ cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", - MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); if (cifs_sm_req_cachep == NULL) { mempool_destroy(cifs_req_poolp); kmem_cache_destroy(cifs_req_cachep); @@ -954,6 +968,12 @@ init_cifs(void) atomic_set(&tconInfoReconnectCount, 0); atomic_set(&bufAllocCount, 0); + atomic_set(&smBufAllocCount, 0); +#ifdef CONFIG_CIFS_STATS2 + atomic_set(&totBufAllocCount, 0); + atomic_set(&totSmBufAllocCount, 0); +#endif /* CONFIG_CIFS_STATS2 */ + atomic_set(&midCount, 0); GlobalCurrentXid = 0; GlobalTotalActiveXid = 0; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9ec40e0e54fc..821a8eb22559 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.39" +#define CIFS_VERSION "1.40" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1ba08f8c5bc4..7bed27601ce5 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -233,6 +233,8 @@ struct cifsTconInfo { atomic_t num_hardlinks; atomic_t num_symlinks; atomic_t num_locks; + atomic_t num_acl_get; + atomic_t num_acl_set; #ifdef CONFIG_CIFS_STATS2 unsigned long long time_writes; unsigned long long time_reads; @@ -285,6 +287,7 @@ struct cifs_search_info { unsigned endOfSearch:1; unsigned emptyDir:1; unsigned unicode:1; + unsigned smallBuf:1; /* so we know which buf_release function to call */ }; struct cifsFileInfo { @@ -420,7 +423,12 @@ struct dir_notify_req { #define MID_RESPONSE_RECEIVED 4 #define MID_RETRY_NEEDED 8 /* session closed while this request out */ #define MID_NO_RESP_NEEDED 0x10 -#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */ + +/* Types of response buffer returned from SendReceive2 */ +#define CIFS_NO_BUFFER 0 /* Response buffer not returned */ +#define CIFS_SMALL_BUFFER 1 +#define CIFS_LARGE_BUFFER 2 +#define CIFS_IOVEC 4 /* array of response buffers */ /* ***************************************************************** @@ -505,8 +513,12 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount; GLOBAL_EXTERN atomic_t tconInfoReconnectCount; /* Various Debug counters to remove someday (BB) */ -GLOBAL_EXTERN atomic_t bufAllocCount; -GLOBAL_EXTERN atomic_t smBufAllocCount; +GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ +#ifdef CONFIG_CIFS_STATS2 +GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ +GLOBAL_EXTERN atomic_t totSmBufAllocCount; +#endif +GLOBAL_EXTERN atomic_t smBufAllocCount; GLOBAL_EXTERN atomic_t midCount; /* Misc globals */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 33e1859fd2f6..cc2471094ca5 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifspdu.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -80,7 +80,11 @@ #define NT_TRANSACT_GET_USER_QUOTA 0x07 #define NT_TRANSACT_SET_USER_QUOTA 0x08 -#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */ +#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ +/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */ +/* among the requests (NTCreateX response is bigger with wct of 34) */ +#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */ +#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */ /* internal cifs vfs structures */ /***************************************************************** @@ -524,7 +528,7 @@ typedef union smb_com_session_setup_andx { /* STRING PrimaryDomain */ /* STRING NativeOS */ /* STRING NativeLanMan */ - } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */ + } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */ struct { /* default (NTLM) response format */ struct smb_hdr hdr; /* wct = 3 */ @@ -536,7 +540,7 @@ typedef union smb_com_session_setup_andx { unsigned char NativeOS[1]; /* followed by */ /* unsigned char * NativeLanMan; */ /* unsigned char * PrimaryDomain; */ - } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */ + } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */ } __attribute__((packed)) SESSION_SETUP_ANDX; #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" @@ -1003,10 +1007,49 @@ typedef struct smb_com_setattr_rsp { /* empty wct response to setattr */ -/***************************************************/ -/* NT Transact structure defintions follow */ -/* Currently only ioctl and notify are implemented */ -/***************************************************/ +/*******************************************************/ +/* NT Transact structure defintions follow */ +/* Currently only ioctl, acl (get security descriptor) */ +/* and notify are implemented */ +/*******************************************************/ +typedef struct smb_com_ntransact_req { + struct smb_hdr hdr; /* wct >= 19 */ + __u8 MaxSetupCount; + __u16 Reserved; + __le32 TotalParameterCount; + __le32 TotalDataCount; + __le32 MaxParameterCount; + __le32 MaxDataCount; + __le32 ParameterCount; + __le32 ParameterOffset; + __le32 DataCount; + __le32 DataOffset; + __u8 SetupCount; /* four setup words follow subcommand */ + /* SNIA spec incorrectly included spurious pad here */ + __le16 SubCommand; /* 2 = IOCTL/FSCTL */ + /* SetupCount words follow then */ + __le16 ByteCount; + __u8 Pad[3]; + __u8 Parms[0]; +} __attribute__((packed)) NTRANSACT_REQ; + +typedef struct smb_com_ntransact_rsp { + struct smb_hdr hdr; /* wct = 18 */ + __u8 Reserved[3]; + __le32 TotalParameterCount; + __le32 TotalDataCount; + __le32 ParameterCount; + __le32 ParameterOffset; + __le32 ParameterDisplacement; + __le32 DataCount; + __le32 DataOffset; + __le32 DataDisplacement; + __u8 SetupCount; /* 0 */ + __u16 ByteCount; + /* __u8 Pad[3]; */ + /* parms and data follow */ +} __attribute__((packed)) NTRANSACT_RSP; + typedef struct smb_com_transaction_ioctl_req { struct smb_hdr hdr; /* wct = 23 */ __u8 MaxSetupCount; @@ -1021,11 +1064,11 @@ typedef struct smb_com_transaction_ioctl_req { __le32 DataOffset; __u8 SetupCount; /* four setup words follow subcommand */ /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand;/* 2 = IOCTL/FSCTL */ + __le16 SubCommand; /* 2 = IOCTL/FSCTL */ __le32 FunctionCode; __u16 Fid; - __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/ - __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/ + __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */ + __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */ __le16 ByteCount; __u8 Pad[3]; __u8 Data[1]; @@ -1045,9 +1088,35 @@ typedef struct smb_com_transaction_ioctl_rsp { __u8 SetupCount; /* 1 */ __le16 ReturnedDataLen; __u16 ByteCount; - __u8 Pad[3]; } __attribute__((packed)) TRANSACT_IOCTL_RSP; +#define CIFS_ACL_OWNER 1 +#define CIFS_ACL_GROUP 2 +#define CIFS_ACL_DACL 4 +#define CIFS_ACL_SACL 8 + +typedef struct smb_com_transaction_qsec_req { + struct smb_hdr hdr; /* wct = 19 */ + __u8 MaxSetupCount; + __u16 Reserved; + __le32 TotalParameterCount; + __le32 TotalDataCount; + __le32 MaxParameterCount; + __le32 MaxDataCount; + __le32 ParameterCount; + __le32 ParameterOffset; + __le32 DataCount; + __le32 DataOffset; + __u8 SetupCount; /* no setup words follow subcommand */ + /* SNIA spec incorrectly included spurious pad here */ + __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */ + __le16 ByteCount; /* bcc = 3 + 8 */ + __u8 Pad[3]; + __u16 Fid; + __u16 Reserved2; + __le32 AclFlags; +} __attribute__((packed)) QUERY_SEC_DESC_REQ; + typedef struct smb_com_transaction_change_notify_req { struct smb_hdr hdr; /* wct = 23 */ __u8 MaxSetupCount; @@ -1068,10 +1137,12 @@ typedef struct smb_com_transaction_change_notify_req { __u8 WatchTree; /* 1 = Monitor subdirectories */ __u8 Reserved2; __le16 ByteCount; -/* __u8 Pad[3];*/ +/* __u8 Pad[3];*/ /* __u8 Data[1];*/ } __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; +/* BB eventually change to use generic ntransact rsp struct + and validation routine */ typedef struct smb_com_transaction_change_notify_rsp { struct smb_hdr hdr; /* wct = 18 */ __u8 Reserved[3]; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1b73f4f4c5ce..3c03aadaff0c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -48,8 +48,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, struct smb_hdr * /* out */ , int * /* bytes returned */ , const int long_op); extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, - struct kvec *, int /* nvec */, - int * /* bytes returned */ , const int long_op); + struct kvec *, int /* nvec to send */, + int * /* type of buf returned */ , const int long_op); extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); extern int is_valid_oplock_break(struct smb_hdr *smb); @@ -93,11 +93,12 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, const struct nls_table *); extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, - const char *searchName, const struct nls_table *nls_codepage, - __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep); + const char *searchName, const struct nls_table *nls_codepage, + __u16 *searchHandle, struct cifs_search_info * psrch_inf, + int map, const char dirsep); extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, - __u16 searchHandle, struct cifs_search_info * psrch_inf); + __u16 searchHandle, struct cifs_search_info * psrch_inf); extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, const __u16 search_handle); @@ -230,19 +231,18 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, const int smb_file_id); extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, - const int netfid, unsigned int count, - const __u64 lseek, unsigned int *nbytes, char **buf); + const int netfid, unsigned int count, + const __u64 lseek, unsigned int *nbytes, char **buf, + int * return_buf_type); extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 lseek, unsigned int *nbytes, const char *buf, const char __user *ubuf, const int long_op); -#ifdef CONFIG_CIFS_EXPERIMENTAL extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 offset, unsigned int *nbytes, struct kvec *iov, const int nvec, const int long_op); -#endif /* CONFIG_CIFS_EXPERIMENTAL */ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 * inode_number, const struct nls_table *nls_codepage, @@ -269,6 +269,8 @@ extern void tconInfoFree(struct cifsTconInfo *); extern int cifs_reconnect(struct TCP_Server_Info *server); extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); +extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, + __u32 *); extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, __u32 expected_sequence_number); extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); @@ -297,6 +299,9 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, const char * ea_name, const void * ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage, int remap_special_chars); +extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, + __u16 fid, char *acl_inf, const int buflen, + const int acl_type /* ACCESS vs. DEFAULT */); extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char *acl_inf, const int buflen,const int acl_type, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6867e556d37e..217323b0c896 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -37,6 +37,7 @@ #include "cifsproto.h" #include "cifs_unicode.h" #include "cifs_debug.h" +#include "cifsacl.h" #ifdef CONFIG_CIFS_POSIX static struct { @@ -372,8 +373,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc == 0) { - server->secMode = pSMBr->SecurityMode; - server->secType = NTLM; /* BB override default for + server->secMode = pSMBr->SecurityMode; + if((server->secMode & SECMODE_USER) == 0) + cFYI(1,("share mode security")); + server->secType = NTLM; /* BB override default for NTLMv2 or kerberos v5 */ /* one byte - no need to convert this or EncryptionKeyLen from little endian */ @@ -383,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) min(le32_to_cpu(pSMBr->MaxBufferSize), (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); - cFYI(0, ("Max buf = %d ", ses->server->maxBuf)); + cFYI(0, ("Max buf = %d", ses->server->maxBuf)); GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); server->capabilities = le32_to_cpu(pSMBr->Capabilities); server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); @@ -411,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) (server->server_GUID, pSMBr->u.extended_response. GUID, 16) != 0) { - cFYI(1, - ("UID of server does not match previous connection to same ip address")); + cFYI(1, ("server UID changed")); memcpy(server-> server_GUID, pSMBr->u. @@ -958,21 +960,19 @@ openRetry: return rc; } -/* If no buffer passed in, then caller wants to do the copy - as in the case of readpages so the SMB buffer must be - freed by the caller */ - int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, - const int netfid, const unsigned int count, - const __u64 lseek, unsigned int *nbytes, char **buf) + const int netfid, const unsigned int count, + const __u64 lseek, unsigned int *nbytes, char **buf, + int * pbuf_type) { int rc = -EACCES; READ_REQ *pSMB = NULL; READ_RSP *pSMBr = NULL; char *pReadData = NULL; - int bytes_returned; int wct; + int resp_buf_type = 0; + struct kvec iov[1]; cFYI(1,("Reading %d bytes on fid %d",count,netfid)); if(tcon->ses->capabilities & CAP_LARGE_FILES) @@ -981,8 +981,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, wct = 10; /* old style read */ *nbytes = 0; - rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB); if (rc) return rc; @@ -990,13 +989,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, if (tcon->ses->server == NULL) return -ECONNABORTED; - pSMB->AndXCommand = 0xFF; /* none */ + pSMB->AndXCommand = 0xFF; /* none */ pSMB->Fid = netfid; pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); if(wct == 12) pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); - else if((lseek >> 32) > 0) /* can not handle this big offset for old */ - return -EIO; + else if((lseek >> 32) > 0) /* can not handle this big offset for old */ + return -EIO; pSMB->Remaining = 0; pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); @@ -1005,14 +1004,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ else { /* old style read */ - struct smb_com_readx_req * pSMBW = + struct smb_com_readx_req * pSMBW = (struct smb_com_readx_req *)pSMB; - pSMBW->ByteCount = 0; + pSMBW->ByteCount = 0; } - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + + iov[0].iov_base = (char *)pSMB; + iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; + rc = SendReceive2(xid, tcon->ses, iov, + 1 /* num iovecs */, + &resp_buf_type, 0); cifs_stats_inc(&tcon->num_reads); + pSMBr = (READ_RSP *)iov[0].iov_base; if (rc) { cERROR(1, ("Send error in read = %d", rc)); } else { @@ -1022,33 +1025,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, *nbytes = data_length; /*check that DataLength would not go beyond end of SMB */ - if ((data_length > CIFSMaxBufSize) + if ((data_length > CIFSMaxBufSize) || (data_length > count)) { cFYI(1,("bad length %d for count %d",data_length,count)); rc = -EIO; *nbytes = 0; } else { - pReadData = - (char *) (&pSMBr->hdr.Protocol) + + pReadData = (char *) (&pSMBr->hdr.Protocol) + le16_to_cpu(pSMBr->DataOffset); -/* if(rc = copy_to_user(buf, pReadData, data_length)) { - cERROR(1,("Faulting on read rc = %d",rc)); - rc = -EFAULT; - }*/ /* can not use copy_to_user when using page cache*/ +/* if(rc = copy_to_user(buf, pReadData, data_length)) { + cERROR(1,("Faulting on read rc = %d",rc)); + rc = -EFAULT; + }*/ /* can not use copy_to_user when using page cache*/ if(*buf) - memcpy(*buf,pReadData,data_length); + memcpy(*buf,pReadData,data_length); } } - if(*buf) - cifs_buf_release(pSMB); - else - *buf = (char *)pSMB; - /* Note: On -EAGAIN error only caller can retry on handle based calls + cifs_small_buf_release(pSMB); + if(*buf) { + if(resp_buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(iov[0].iov_base); + else if(resp_buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(iov[0].iov_base); + } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ { + *buf = iov[0].iov_base; + if(resp_buf_type == CIFS_SMALL_BUFFER) + *pbuf_type = CIFS_SMALL_BUFFER; + else if(resp_buf_type == CIFS_LARGE_BUFFER) + *pbuf_type = CIFS_LARGE_BUFFER; + } + + /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ return rc; } + int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, @@ -1155,7 +1168,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, return rc; } -#ifdef CONFIG_CIFS_EXPERIMENTAL int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, @@ -1164,10 +1176,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, { int rc = -EACCES; WRITE_REQ *pSMB = NULL; - int bytes_returned, wct; + int wct; int smb_hdr_len; + int resp_buf_type = 0; - /* BB removeme BB */ cFYI(1,("write2 at %lld %d bytes", (long long)offset, count)); if(tcon->ses->capabilities & CAP_LARGE_FILES) @@ -1210,22 +1222,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, pSMBW->ByteCount = cpu_to_le16(count + 5); } iov[0].iov_base = pSMB; - iov[0].iov_len = smb_hdr_len + 4; + if(wct == 14) + iov[0].iov_len = smb_hdr_len + 4; + else /* wct == 12 pad bigger by four bytes */ + iov[0].iov_len = smb_hdr_len + 8; + - rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned, + rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, long_op); cifs_stats_inc(&tcon->num_writes); if (rc) { cFYI(1, ("Send error Write2 = %d", rc)); *nbytes = 0; + } else if(resp_buf_type == 0) { + /* presumably this can not happen, but best to be safe */ + rc = -EIO; + *nbytes = 0; } else { - WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; + WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base; *nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = (*nbytes) << 16; *nbytes += le16_to_cpu(pSMBr->Count); - } + } cifs_small_buf_release(pSMB); + if(resp_buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(iov[0].iov_base); + else if(resp_buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(iov[0].iov_base); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -1234,8 +1258,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, } -#endif /* CIFS_EXPERIMENTAL */ - int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const __u64 len, @@ -1906,6 +1928,90 @@ querySymLinkRetry: return rc; } +/* Initialize NT TRANSACT SMB into small smb request buffer. + This assumes that all NT TRANSACTS that we init here have + total parm and data under about 400 bytes (to fit in small cifs + buffer size), which is the case so far, it easily fits. NB: + Setup words themselves and ByteCount + MaxSetupCount (size of returned setup area) and + MaxParameterCount (returned parms size) must be set by caller */ +static int +smb_init_ntransact(const __u16 sub_command, const int setup_count, + const int parm_len, struct cifsTconInfo *tcon, + void ** ret_buf) +{ + int rc; + __u32 temp_offset; + struct smb_com_ntransact_req * pSMB; + + rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, + (void **)&pSMB); + if (rc) + return rc; + *ret_buf = (void *)pSMB; + pSMB->Reserved = 0; + pSMB->TotalParameterCount = cpu_to_le32(parm_len); + pSMB->TotalDataCount = 0; + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->DataCount = pSMB->TotalDataCount; + temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + + (setup_count * 2) - 4 /* for rfc1001 length itself */; + pSMB->ParameterOffset = cpu_to_le32(temp_offset); + pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); + pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ + pSMB->SubCommand = cpu_to_le16(sub_command); + return 0; +} + +static int +validate_ntransact(char * buf, char ** ppparm, char ** ppdata, + int * pdatalen, int * pparmlen) +{ + char * end_of_smb; + __u32 data_count, data_offset, parm_count, parm_offset; + struct smb_com_ntransact_rsp * pSMBr; + + if(buf == NULL) + return -EINVAL; + + pSMBr = (struct smb_com_ntransact_rsp *)buf; + + /* ByteCount was converted from little endian in SendReceive */ + end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + + (char *)&pSMBr->ByteCount; + + + data_offset = le32_to_cpu(pSMBr->DataOffset); + data_count = le32_to_cpu(pSMBr->DataCount); + parm_offset = le32_to_cpu(pSMBr->ParameterOffset); + parm_count = le32_to_cpu(pSMBr->ParameterCount); + + *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; + *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; + + /* should we also check that parm and data areas do not overlap? */ + if(*ppparm > end_of_smb) { + cFYI(1,("parms start after end of smb")); + return -EINVAL; + } else if(parm_count + *ppparm > end_of_smb) { + cFYI(1,("parm end after end of smb")); + return -EINVAL; + } else if(*ppdata > end_of_smb) { + cFYI(1,("data starts after end of smb")); + return -EINVAL; + } else if(data_count + *ppdata > end_of_smb) { + cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", + *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */ + return -EINVAL; + } else if(parm_count + data_count > pSMBr->ByteCount) { + cFYI(1,("parm count and data count larger than SMB")); + return -EINVAL; + } + return 0; +} + int CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, @@ -1928,7 +2034,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le32(2); /* BB find exact data count max from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le32(4000); + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 4; pSMB->Reserved = 0; pSMB->ParameterOffset = 0; @@ -1955,7 +2062,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, rc = -EIO; /* bad smb */ else { if(data_count && (data_count < 2048)) { - char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount; + char * end_of_smb = 2 /* sizeof byte count */ + + pSMBr->ByteCount + + (char *)&pSMBr->ByteCount; struct reparse_data * reparse_buf = (struct reparse_data *) ((char *)&pSMBr->hdr.Protocol + data_offset); @@ -2199,6 +2308,7 @@ queryAclRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); + cifs_stats_inc(&tcon->num_acl_get); if (rc) { cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); } else { @@ -2386,6 +2496,92 @@ GetExtAttrOut: #endif /* CONFIG_POSIX */ + +/* security id for everyone */ +const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; +/* group users */ +const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; + +/* Convert CIFS ACL to POSIX form */ +static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len) +{ + return 0; +} + +/* Get Security Descriptor (by handle) from remote server for a file or dir */ +int +CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, + /* BB fix up return info */ char *acl_inf, const int buflen, + const int acl_type /* ACCESS/DEFAULT not sure implication */) +{ + int rc = 0; + int buf_type = 0; + QUERY_SEC_DESC_REQ * pSMB; + struct kvec iov[1]; + + cFYI(1, ("GetCifsACL")); + + rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, + 8 /* parm len */, tcon, (void **) &pSMB); + if (rc) + return rc; + + pSMB->MaxParameterCount = cpu_to_le32(4); + /* BB TEST with big acls that might need to be e.g. larger than 16K */ + pSMB->MaxSetupCount = 0; + pSMB->Fid = fid; /* file handle always le */ + pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | + CIFS_ACL_DACL); + pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ + pSMB->hdr.smb_buf_length += 11; + iov[0].iov_base = (char *)pSMB; + iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; + + rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0); + cifs_stats_inc(&tcon->num_acl_get); + if (rc) { + cFYI(1, ("Send error in QuerySecDesc = %d", rc)); + } else { /* decode response */ + struct cifs_sid * psec_desc; + __le32 * parm; + int parm_len; + int data_len; + int acl_len; + struct smb_com_ntransact_rsp * pSMBr; + +/* validate_nttransact */ + rc = validate_ntransact(iov[0].iov_base, (char **)&parm, + (char **)&psec_desc, + &parm_len, &data_len); + + if(rc) + goto qsec_out; + pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; + + cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */ + + if (le32_to_cpu(pSMBr->ParameterCount) != 4) { + rc = -EIO; /* bad smb */ + goto qsec_out; + } + +/* BB check that data area is minimum length and as big as acl_len */ + + acl_len = le32_to_cpu(*(__le32 *)parm); + /* BB check if(acl_len > bufsize) */ + + parse_sec_desc(psec_desc, acl_len); + } +qsec_out: + if(buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(iov[0].iov_base); + else if(buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(iov[0].iov_base); + cifs_small_buf_release(pSMB); + return rc; +} + + /* Legacy Query Path Information call for lookup to old servers such as Win9x/WinME */ int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, @@ -4284,7 +4480,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, { int rc = 0; struct smb_com_transaction_change_notify_req * pSMB = NULL; - struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; + struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL; struct dir_notify_req *dnotify_req; int bytes_returned; @@ -4299,6 +4495,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, pSMB->MaxParameterCount = cpu_to_le32(2); /* BB find exact data count max from sess structure BB */ pSMB->MaxDataCount = 0; /* same in little endian or be */ +/* BB VERIFY verify which is correct for above BB */ + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->MaxSetupCount = 4; pSMB->Reserved = 0; pSMB->ParameterOffset = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c467de857610..e488603fb1e7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -76,12 +76,19 @@ struct smb_vol { unsigned setuids:1; unsigned noperm:1; unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ + unsigned cifs_acl:1; unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ unsigned direct_io:1; unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ unsigned sfu_emul:1; + unsigned krb5:1; + unsigned ntlm:1; + unsigned ntlmv2:1; + unsigned nullauth:1; /* attempt to authenticate with null user */ + unsigned sign:1; + unsigned seal:1; /* encrypt */ unsigned nocase; /* request case insensitive filenames */ unsigned nobrl; /* disable sending byte range locks to srv */ unsigned int rsize; @@ -508,7 +515,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) /* else length ok */ reconnect = 0; - if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { + if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { isLargeBuf = TRUE; memcpy(bigbuf, smallbuf, 4); smb_buffer = bigbuf; @@ -777,7 +784,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ vol->rw = TRUE; - + vol->ntlm = TRUE; /* default is always to request posix paths. */ vol->posix_paths = 1; @@ -903,6 +910,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) printk(KERN_WARNING "CIFS: ip address too long\n"); return 1; } + } else if (strnicmp(data, "sec", 3) == 0) { + if (!value || !*value) { + cERROR(1,("no security value specified")); + continue; + } else if (strnicmp(value, "krb5i", 5) == 0) { + vol->sign = 1; + vol->krb5 = 1; + } else if (strnicmp(value, "krb5p", 5) == 0) { + /* vol->seal = 1; + vol->krb5 = 1; */ + cERROR(1,("Krb5 cifs privacy not supported")); + return 1; + } else if (strnicmp(value, "krb5", 4) == 0) { + vol->krb5 = 1; + } else if (strnicmp(value, "ntlmv2i", 7) == 0) { + vol->ntlmv2 = 1; + vol->sign = 1; + } else if (strnicmp(value, "ntlmv2", 6) == 0) { + vol->ntlmv2 = 1; + } else if (strnicmp(value, "ntlmi", 5) == 0) { + vol->ntlm = 1; + vol->sign = 1; + } else if (strnicmp(value, "ntlm", 4) == 0) { + /* ntlm is default so can be turned off too */ + vol->ntlm = 1; + } else if (strnicmp(value, "nontlm", 6) == 0) { + vol->ntlm = 0; + } else if (strnicmp(value, "none", 4) == 0) { + vol->nullauth = 1; + } else { + cERROR(1,("bad security option: %s", value)); + return 1; + } } else if ((strnicmp(data, "unc", 3) == 0) || (strnicmp(data, "target", 6) == 0) || (strnicmp(data, "path", 4) == 0)) { @@ -1120,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->server_ino = 1; } else if (strnicmp(data, "noserverino",9) == 0) { vol->server_ino = 0; + } else if (strnicmp(data, "cifsacl",7) == 0) { + vol->cifs_acl = 1; + } else if (strnicmp(data, "nocifsacl", 9) == 0) { + vol->cifs_acl = 0; } else if (strnicmp(data, "acl",3) == 0) { vol->no_psx_acl = 0; } else if (strnicmp(data, "noacl",5) == 0) { @@ -1546,7 +1590,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cFYI(1, ("Username: %s ", volume_info.username)); } else { - cifserror("No username specified "); + cifserror("No username specified"); /* In userspace mount helper we can get user name from alternate locations such as env variables and files on disk */ kfree(volume_info.UNC); @@ -1587,7 +1631,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, return -EINVAL; } else /* which servers DFS root would we conect to */ { cERROR(1, - ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); + ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); kfree(volume_info.UNC); kfree(volume_info.password); FreeXid(xid); @@ -1626,7 +1670,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (srvTcp) { - cFYI(1, ("Existing tcp session with server found ")); + cFYI(1, ("Existing tcp session with server found")); } else { /* create socket */ if(volume_info.port) sin_server.sin_port = htons(volume_info.port); @@ -1689,11 +1733,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (existingCifsSes) { pSesInfo = existingCifsSes; - cFYI(1, ("Existing smb sess found ")); + cFYI(1, ("Existing smb sess found")); kfree(volume_info.password); /* volume_info.UNC freed at end of function */ } else if (!rc) { - cFYI(1, ("Existing smb sess not found ")); + cFYI(1, ("Existing smb sess not found")); pSesInfo = sesInfoAlloc(); if (pSesInfo == NULL) rc = -ENOMEM; @@ -1741,7 +1785,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } else if(volume_info.wsize) cifs_sb->wsize = volume_info.wsize; else - cifs_sb->wsize = CIFSMaxBufSize; /* default */ + cifs_sb->wsize = + min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE, + 127*1024); + /* old default of CIFSMaxBufSize was too small now + that SMB Write2 can send multiple pages in kvec. + RFC1001 does not describe what happens when frame + bigger than 128K is sent so use that as max in + conjunction with 52K kvec constraint on arch with 4K + page size */ + if(cifs_sb->rsize < PAGE_CACHE_SIZE) { cifs_sb->rsize = PAGE_CACHE_SIZE; /* Windows ME does this */ @@ -1751,7 +1804,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_gid = volume_info.linux_gid; cifs_sb->mnt_file_mode = volume_info.file_mode; cifs_sb->mnt_dir_mode = volume_info.dir_mode; - cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); + cFYI(1,("file mode: 0x%x dir mode: 0x%x", + cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode)); if(volume_info.noperm) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; @@ -1767,6 +1821,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; if(volume_info.nobrl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; + if(volume_info.cifs_acl) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; if(volume_info.direct_io) { cFYI(1,("mounting share using direct i/o")); @@ -1777,7 +1833,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, volume_info.username); if (tcon) { - cFYI(1, ("Found match on UNC path ")); + cFYI(1, ("Found match on UNC path")); /* we can have only one retry value for a connection to a share so for resources mounted more than once to the same server share the last value passed in @@ -1926,7 +1982,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, __u32 capabilities; __u16 count; - cFYI(1, ("In sesssetup ")); + cFYI(1, ("In sesssetup")); if(ses == NULL) return -EINVAL; user = ses->userName; @@ -3202,9 +3258,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, pSMB->AndXCommand = 0xFF; pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); - pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ bcc_ptr = &pSMB->Password[0]; - bcc_ptr++; /* skip password */ + if((ses->server->secMode) & SECMODE_USER) { + pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ + bcc_ptr++; /* skip password */ + } else { + pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); + /* BB FIXME add code to fail this if NTLMv2 or Kerberos + specified as required (when that support is added to + the vfs in the future) as only NTLM or the much + weaker LANMAN (which we do not send) is accepted + by Samba (not sure whether other servers allow + NTLMv2 password here) */ + SMBNTencrypt(ses->password, + ses->server->cryptKey, + bcc_ptr); + + bcc_ptr += CIFS_SESSION_KEY_SIZE; + *bcc_ptr = 0; + bcc_ptr++; /* align */ + } if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; @@ -3222,7 +3295,6 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ bcc_ptr += 2; /* skip trailing null */ } else { /* ASCII */ - strcpy(bcc_ptr, tree); bcc_ptr += strlen(tree) + 1; } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 32cc96cafa3e..fed55e3c53df 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -3,7 +3,7 @@ * * vfs operations that deal with dentries * - * Copyright (C) International Business Machines Corp., 2002,2003 + * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -200,8 +200,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (oplock & CIFS_CREATE_ACTION)) if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, - (__u64)current->euid, - (__u64)current->egid, + (__u64)current->fsuid, + (__u64)current->fsgid, 0 /* dev */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -325,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, else if (pTcon->ses->capabilities & CAP_UNIX) { if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, - mode,(__u64)current->euid,(__u64)current->egid, + mode,(__u64)current->fsuid,(__u64)current->fsgid, device_number, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5ade53d7bca8..d17c97d07c80 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -553,13 +553,13 @@ int cifs_closedir(struct inode *inode, struct file *file) } ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; if (ptmp) { - /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir")); + cFYI(1, ("closedir free smb buf in srch struct")); pCFileStruct->srch_inf.ntwrk_buf_start = NULL; cifs_buf_release(ptmp); } ptmp = pCFileStruct->search_resume_name; if (ptmp) { - /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir")); + cFYI(1, ("closedir free resume name")); pCFileStruct->search_resume_name = NULL; kfree(ptmp); } @@ -868,10 +868,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data, if (rc != 0) break; } -#ifdef CONFIG_CIFS_EXPERIMENTAL /* BB FIXME We can not sign across two buffers yet */ - if((experimEnabled) && ((pTcon->ses->server->secMode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) { + if((pTcon->ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) { struct kvec iov[2]; unsigned int len; @@ -887,7 +886,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data, iov, 1, long_op); } else /* BB FIXME fixup indentation of line below */ -#endif rc = CIFSSMBWrite(xid, pTcon, open_file->netfid, min_t(const int, cifs_sb->wsize, @@ -1024,7 +1022,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) return rc; } -#ifdef CONFIG_CIFS_EXPERIMENTAL static int cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1193,7 +1190,6 @@ retry: /* BB what if continued retry is requested via mount flags? */ set_bit(AS_EIO, &mapping->flags); - SetPageError(page); } else { cifs_stats_bytes_written(cifs_sb->tcon, bytes_written); @@ -1201,6 +1197,13 @@ retry: } for (i = 0; i < n_iov; i++) { page = pvec.pages[first + i]; + /* Should we also set page error on + success rc but too little data written? */ + /* BB investigate retry logic on temporary + server crash cases and how recovery works + when page marked as error */ + if(rc) + SetPageError(page); kunmap(page); unlock_page(page); page_cache_release(page); @@ -1227,7 +1230,6 @@ retry: return rc; } -#endif static int cifs_writepage(struct page* page, struct writeback_control *wbc) { @@ -1426,6 +1428,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, rc = -EAGAIN; smb_read_data = NULL; while (rc == -EAGAIN) { + int buf_type = CIFS_NO_BUFFER; if ((open_file->invalidHandle) && (!open_file->closePend)) { rc = cifs_reopen_file(file->f_dentry->d_inode, @@ -1434,20 +1437,22 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, break; } rc = CIFSSMBRead(xid, pTcon, - open_file->netfid, - current_read_size, *poffset, - &bytes_read, &smb_read_data); + open_file->netfid, + current_read_size, *poffset, + &bytes_read, &smb_read_data, + &buf_type); pSMBr = (struct smb_com_read_rsp *)smb_read_data; if (copy_to_user(current_offset, smb_read_data + 4 /* RFC1001 hdr */ + le16_to_cpu(pSMBr->DataOffset), bytes_read)) { rc = -EFAULT; - FreeXid(xid); - return rc; - } + } if (smb_read_data) { - cifs_buf_release(smb_read_data); + if(buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if(buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); smb_read_data = NULL; } } @@ -1480,6 +1485,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, int xid; char *current_offset; struct cifsFileInfo *open_file; + int buf_type = CIFS_NO_BUFFER; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -1516,9 +1522,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, break; } rc = CIFSSMBRead(xid, pTcon, - open_file->netfid, - current_read_size, *poffset, - &bytes_read, ¤t_offset); + open_file->netfid, + current_read_size, *poffset, + &bytes_read, ¤t_offset, + &buf_type); } if (rc || (bytes_read == 0)) { if (total_read) { @@ -1616,6 +1623,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, struct smb_com_read_rsp *pSMBr; struct pagevec lru_pvec; struct cifsFileInfo *open_file; + int buf_type = CIFS_NO_BUFFER; xid = GetXid(); if (file->private_data == NULL) { @@ -1672,14 +1680,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } rc = CIFSSMBRead(xid, pTcon, - open_file->netfid, - read_size, offset, - &bytes_read, &smb_read_data); - + open_file->netfid, + read_size, offset, + &bytes_read, &smb_read_data, + &buf_type); /* BB more RC checks ? */ if (rc== -EAGAIN) { if (smb_read_data) { - cifs_buf_release(smb_read_data); + if(buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if(buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); smb_read_data = NULL; } } @@ -1736,7 +1747,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, break; } if (smb_read_data) { - cifs_buf_release(smb_read_data); + if(buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if(buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); smb_read_data = NULL; } bytes_read = 0; @@ -1746,7 +1760,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, /* need to free smb_read_data buf before exit */ if (smb_read_data) { - cifs_buf_release(smb_read_data); + if(buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if(buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); smb_read_data = NULL; } @@ -1825,10 +1842,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) open_file = find_writable_file(cifsInode); if(open_file) { + struct cifs_sb_info *cifs_sb; + /* there is not actually a write pending so let this handle go free and allow it to be closable if needed */ atomic_dec(&open_file->wrtPending); + + cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb); + if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) { + /* since no page cache to corrupt on directio + we can change size safely */ + return 1; + } + return 0; } else return 1; @@ -1873,9 +1900,7 @@ struct address_space_operations cifs_addr_ops = { .readpage = cifs_readpage, .readpages = cifs_readpages, .writepage = cifs_writepage, -#ifdef CONFIG_CIFS_EXPERIMENTAL .writepages = cifs_writepages, -#endif .prepare_write = cifs_prepare_write, .commit_write = cifs_commit_write, .set_page_dirty = __set_page_dirty_nobuffers, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3ebce9430f4a..59359911f481 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { + int buf_type = CIFS_NO_BUFFER; /* Read header */ rc = CIFSSMBRead(xid, pTcon, netfid, 24 /* length */, 0 /* offset */, - &bytes_read, &pbuf); + &bytes_read, &pbuf, &buf_type); if((rc == 0) && (bytes_read >= 8)) { if(memcmp("IntxBLK", pbuf, 8) == 0) { cFYI(1,("Block device")); @@ -267,7 +268,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, } else { inode->i_mode |= S_IFREG; /* then it is a file */ rc = -EOPNOTSUPP; /* or some unknown SFU type */ - } + } CIFSSMBClose(xid, pTcon, netfid); } return rc; @@ -750,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, - (__u64)current->euid, - (__u64)current->egid, + (__u64)current->fsuid, + (__u64)current->fsgid, 0 /* dev_t */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 94baf6c8ecbd..812c6bb0fe38 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1,7 +1,7 @@ /* * fs/cifs/misc.c * - * Copyright (C) International Business Machines Corp., 2002,2004 + * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -161,6 +161,9 @@ cifs_buf_get(void) if (ret_buf) { memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); atomic_inc(&bufAllocCount); +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&totBufAllocCount); +#endif /* CONFIG_CIFS_STATS2 */ } return ret_buf; @@ -195,6 +198,10 @@ cifs_small_buf_get(void) /* No need to clear memory here, cleared in header assemble */ /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ atomic_inc(&smBufAllocCount); +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&totSmBufAllocCount); +#endif /* CONFIG_CIFS_STATS2 */ + } return ret_buf; } @@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , struct cifsSesInfo * ses; char *temp = (char *) buffer; - memset(temp,0,MAX_CIFS_HDR_SIZE); + memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */ buffer->smb_buf_length = (2 * word_count) + sizeof (struct smb_hdr) - @@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , /* BB Add support for establishing new tCon and SMB Session */ /* with userid/password pairs found on the smb session */ /* for other target tcp/ip addresses BB */ - if(current->uid != treeCon->ses->linux_uid) { - cFYI(1,("Multiuser mode and UID did not match tcon uid ")); + if(current->fsuid != treeCon->ses->linux_uid) { + cFYI(1,("Multiuser mode and UID did not match tcon uid")); read_lock(&GlobalSMBSeslock); list_for_each(temp_item, &GlobalSMBSessionList) { ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); - if(ses->linux_uid == current->uid) { + if(ses->linux_uid == current->fsuid) { if(ses->server == treeCon->ses->server) { cFYI(1,("found matching uid substitute right smb_uid")); buffer->Uid = ses->Suid; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 9bdaaecae36f..288cc048d37f 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -214,8 +214,7 @@ static void fill_in_inode(struct inode *tmp_inode, tmp_inode->i_fop = &cifs_file_nobrl_ops; else tmp_inode->i_fop = &cifs_file_ops; - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop->lock = NULL; + tmp_inode->i_data.a_ops = &cifs_addr_ops; if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server->maxBuf < @@ -327,12 +326,18 @@ static void unix_fill_in_inode(struct inode *tmp_inode, if (S_ISREG(tmp_inode->i_mode)) { cFYI(1, ("File inode")); tmp_inode->i_op = &cifs_file_inode_ops; - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) - tmp_inode->i_fop = &cifs_file_direct_ops; + + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) + tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; + else + tmp_inode->i_fop = &cifs_file_direct_ops; + + } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) + tmp_inode->i_fop = &cifs_file_nobrl_ops; else tmp_inode->i_fop = &cifs_file_ops; - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop->lock = NULL; + tmp_inode->i_data.a_ops = &cifs_addr_ops; if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server->maxBuf < diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h index 9222033cad8e..aede606132aa 100644 --- a/fs/cifs/rfc1002pdu.h +++ b/fs/cifs/rfc1002pdu.h @@ -24,11 +24,11 @@ /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ /* RFC 1002 session packet types */ -#define RFC1002_SESSION_MESASAGE 0x00 +#define RFC1002_SESSION_MESSAGE 0x00 #define RFC1002_SESSION_REQUEST 0x81 #define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 #define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 -#define RFC1002_RETARGET_SESSION_RESPONSE 0x83 +#define RFC1002_RETARGET_SESSION_RESPONSE 0x84 #define RFC1002_SESSION_KEEP_ALIVE 0x85 /* RFC 1002 flags (only one defined */ diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index f8871196098c..b12cb8a7da7c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -206,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, return rc; } -#ifdef CONFIG_CIFS_EXPERIMENTAL static int smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, struct sockaddr *sin) @@ -299,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, int SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, - struct kvec *iov, int n_vec, int *pbytes_returned, + struct kvec *iov, int n_vec, int * pRespBufType /* ret */, const int long_op) { int rc = 0; @@ -307,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, unsigned long timeout; struct mid_q_entry *midQ; struct smb_hdr *in_buf = iov[0].iov_base; + + *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ if (ses == NULL) { cERROR(1,("Null smb session")); @@ -392,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, return -ENOMEM; } -/* BB FIXME */ -/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */ + rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); midQ->midState = MID_REQUEST_SUBMITTED; #ifdef CONFIG_CIFS_STATS2 @@ -489,21 +489,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, receive_len, xid)); rc = -EIO; } else { /* rcvd frame is ok */ - if (midQ->resp_buf && (midQ->midState == MID_RESPONSE_RECEIVED)) { - in_buf->smb_buf_length = receive_len; - /* BB verify that length would not overrun small buf */ - memcpy((char *)in_buf + 4, - (char *)midQ->resp_buf + 4, - receive_len); - dump_smb(in_buf, 80); + iov[0].iov_base = (char *)midQ->resp_buf; + if(midQ->largeBuf) + *pRespBufType = CIFS_LARGE_BUFFER; + else + *pRespBufType = CIFS_SMALL_BUFFER; + iov[0].iov_len = receive_len + 4; + + dump_smb(midQ->resp_buf, 80); /* convert the length into a more usable form */ if((receive_len > 24) && (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { - rc = cifs_verify_signature(in_buf, + rc = cifs_verify_signature(midQ->resp_buf, ses->server->mac_signing_key, midQ->sequence_number+1); if(rc) { @@ -512,18 +513,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } } - *pbytes_returned = in_buf->smb_buf_length; - /* BB special case reconnect tid and uid here? */ /* BB special case Errbadpassword and pwdexpired here */ - rc = map_smb_to_linux_error(in_buf); + rc = map_smb_to_linux_error(midQ->resp_buf); /* convert ByteCount if necessary */ if (receive_len >= sizeof (struct smb_hdr) - 4 /* do not count RFC1001 header */ + - (2 * in_buf->WordCount) + 2 /* bcc */ ) - BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf)); + (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) + BCC(midQ->resp_buf) = + le16_to_cpu(BCC_LE(midQ->resp_buf)); + midQ->resp_buf = NULL; /* mark it so will not be freed + by DeleteMidQEntry */ } else { rc = -EIO; cFYI(1,("Bad MID state?")); @@ -549,7 +551,6 @@ out_unlock2: return rc; } -#endif /* CIFS_EXPERIMENTAL */ int SendReceive(const unsigned int xid, struct cifsSesInfo *ses, @@ -790,7 +791,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); } else { rc = -EIO; - cERROR(1,("Bad MID state? ")); + cERROR(1,("Bad MID state?")); } } cifs_no_response_exit: diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index f375f87c7dbd..777e3363c2a4 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -254,7 +254,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, buf_size, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { + } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, + strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { #ifdef CONFIG_CIFS_POSIX if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, @@ -262,10 +263,27 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); +/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + __u16 fid; + int oplock = FALSE; + rc = CIFSSMBOpen(xid, pTcon, full_path, + FILE_OPEN, GENERIC_READ, 0, &fid, + &oplock, NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if(rc == 0) { + rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, + ea_value, buf_size, + ACL_TYPE_ACCESS); + CIFSSMBClose(xid, pTcon, fid) + } + } */ /* BB enable after fixing up return data */ + #else cFYI(1,("query POSIX ACL not supported yet")); #endif /* CONFIG_CIFS_POSIX */ - } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { + } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT, + strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { #ifdef CONFIG_CIFS_POSIX if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, diff --git a/fs/compat.c b/fs/compat.c index 2468ac1df2f0..a2ba78bdf7f7 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -53,6 +53,8 @@ #include <asm/mmu_context.h> #include <asm/ioctls.h> +extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); + /* * Not all architectures have sys_utime, so implement this in terms * of sys_utimes. @@ -68,28 +70,33 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __ tv[0].tv_usec = 0; tv[1].tv_usec = 0; } - return do_utimes(filename, t ? tv : NULL); + return do_utimes(AT_FDCWD, filename, t ? tv : NULL); } -asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) +asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) { struct timeval tv[2]; - if (t) { + if (t) { if (get_user(tv[0].tv_sec, &t[0].tv_sec) || get_user(tv[0].tv_usec, &t[0].tv_usec) || get_user(tv[1].tv_sec, &t[1].tv_sec) || get_user(tv[1].tv_usec, &t[1].tv_usec)) - return -EFAULT; - } - return do_utimes(filename, t ? tv : NULL); + return -EFAULT; + } + return do_utimes(dfd, filename, t ? tv : NULL); +} + +asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) +{ + return compat_sys_futimesat(AT_FDCWD, filename, t); } asmlinkage long compat_sys_newstat(char __user * filename, struct compat_stat __user *statbuf) { struct kstat stat; - int error = vfs_stat(filename, &stat); + int error = vfs_stat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_compat_stat(&stat, statbuf); @@ -100,13 +107,34 @@ asmlinkage long compat_sys_newlstat(char __user * filename, struct compat_stat __user *statbuf) { struct kstat stat; - int error = vfs_lstat(filename, &stat); + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_compat_stat(&stat, statbuf); return error; } +asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, + struct compat_stat __user *statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_compat_stat(&stat, statbuf); + +out: + return error; +} + asmlinkage long compat_sys_newfstat(unsigned int fd, struct compat_stat __user * statbuf) { @@ -1290,7 +1318,17 @@ out: asmlinkage long compat_sys_open(const char __user *filename, int flags, int mode) { - return do_sys_open(filename, flags, mode); + return do_sys_open(AT_FDCWD, filename, flags, mode); +} + +/* + * Exactly like fs/open.c:sys_openat(), except that it doesn't set the + * O_LARGEFILE flag. + */ +asmlinkage long +compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode) +{ + return do_sys_open(dfd, filename, flags, mode); } /* @@ -1621,36 +1659,14 @@ static void select_bits_free(void *bits, int size) #define MAX_SELECT_SECONDS \ ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) -asmlinkage long -compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, - compat_ulong_t __user *exp, struct compat_timeval __user *tvp) +int compat_core_sys_select(int n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) { fd_set_bits fds; char *bits; - long timeout; int size, max_fdset, ret = -EINVAL; struct fdtable *fdt; - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - time_t sec, usec; - - if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp)) - || __get_user(sec, &tvp->tv_sec) - || __get_user(usec, &tvp->tv_usec)) { - ret = -EFAULT; - goto out_nofds; - } - - if (sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = ROUND_UP(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - if (n < 0) goto out_nofds; @@ -1687,19 +1703,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp zero_fd_set(n, fds.res_out); zero_fd_set(n, fds.res_ex); - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - if (put_user(sec, &tvp->tv_sec) || - put_user(usec, &tvp->tv_usec)) - ret = -EFAULT; - } + ret = do_select(n, &fds, timeout); if (ret < 0) goto out; @@ -1720,6 +1724,237 @@ out_nofds: return ret; } +asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, compat_ulong_t __user *exp, + struct compat_timeval __user *tvp) +{ + s64 timeout = -1; + struct compat_timeval tv; + int ret; + + if (tvp) { + if (copy_from_user(&tv, tvp, sizeof(tv))) + return -EFAULT; + + if (tv.tv_sec < 0 || tv.tv_usec < 0) + return -EINVAL; + + /* Cast to u64 to make GCC stop complaining */ + if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS) + timeout = -1; /* infinite */ + else { + timeout = ROUND_UP(tv.tv_usec, 1000000/HZ); + timeout += tv.tv_sec * HZ; + } + } + + ret = compat_core_sys_select(n, inp, outp, exp, &timeout); + + if (tvp) { + struct compat_timeval rtv; + + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)); + rtv.tv_sec = timeout; + if (compat_timeval_compare(&rtv, &tv) < 0) + rtv = tv; + if (copy_to_user(tvp, &rtv, sizeof(rtv))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND) + ret = -EINTR; + } + } + + return ret; +} + +#ifdef TIF_RESTORE_SIGMASK +asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, compat_ulong_t __user *exp, + struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, + compat_size_t sigsetsize) +{ + compat_sigset_t ss32; + sigset_t ksigmask, sigsaved; + s64 timeout = MAX_SCHEDULE_TIMEOUT; + struct compat_timespec ts; + int ret; + + if (tsp) { + if (copy_from_user(&ts, tsp, sizeof(ts))) + return -EFAULT; + + if (ts.tv_sec < 0 || ts.tv_nsec < 0) + return -EINVAL; + } + + if (sigmask) { + if (sigsetsize != sizeof(compat_sigset_t)) + return -EINVAL; + if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + return -EFAULT; + sigset_from_compat(&ksigmask, &ss32); + + sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + + do { + if (tsp) { + if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) { + timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ); + timeout += ts.tv_sec * (unsigned long)HZ; + ts.tv_sec = 0; + ts.tv_nsec = 0; + } else { + ts.tv_sec -= MAX_SELECT_SECONDS; + timeout = MAX_SELECT_SECONDS * HZ; + } + } + + ret = compat_core_sys_select(n, inp, outp, exp, &timeout); + + } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); + + if (tsp && !(current->personality & STICKY_TIMEOUTS)) { + struct compat_timespec rts; + + rts.tv_sec = timeout / HZ; + rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); + if (rts.tv_nsec >= NSEC_PER_SEC) { + rts.tv_sec++; + rts.tv_nsec -= NSEC_PER_SEC; + } + if (compat_timespec_compare(&rts, &ts) < 0) + rts = ts; + copy_to_user(tsp, &rts, sizeof(rts)); + } + + if (ret == -ERESTARTNOHAND) { + /* + * Don't restore the signal mask yet. Let do_signal() deliver + * the signal on the way back to userspace, before the signal + * mask is restored. + */ + if (sigmask) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } + } else if (sigmask) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + return ret; +} + +asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, + compat_ulong_t __user *outp, compat_ulong_t __user *exp, + struct compat_timespec __user *tsp, void __user *sig) +{ + compat_size_t sigsetsize = 0; + compat_uptr_t up = 0; + + if (sig) { + if (!access_ok(VERIFY_READ, sig, + sizeof(compat_uptr_t)+sizeof(compat_size_t)) || + __get_user(up, (compat_uptr_t __user *)sig) || + __get_user(sigsetsize, + (compat_size_t __user *)(sig+sizeof(up)))) + return -EFAULT; + } + return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up), + sigsetsize); +} + +asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, + unsigned int nfds, struct compat_timespec __user *tsp, + const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) +{ + compat_sigset_t ss32; + sigset_t ksigmask, sigsaved; + struct compat_timespec ts; + s64 timeout = -1; + int ret; + + if (tsp) { + if (copy_from_user(&ts, tsp, sizeof(ts))) + return -EFAULT; + + /* We assume that ts.tv_sec is always lower than + the number of seconds that can be expressed in + an s64. Otherwise the compiler bitches at us */ + timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ); + timeout += ts.tv_sec * HZ; + } + + if (sigmask) { + if (sigsetsize |= sizeof(compat_sigset_t)) + return -EINVAL; + if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + return -EFAULT; + sigset_from_compat(&ksigmask, &ss32); + + sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + + ret = do_sys_poll(ufds, nfds, &timeout); + + /* We can restart this syscall, usually */ + if (ret == -EINTR) { + /* + * Don't restore the signal mask yet. Let do_signal() deliver + * the signal on the way back to userspace, before the signal + * mask is restored. + */ + if (sigmask) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } + ret = -ERESTARTNOHAND; + } else if (sigmask) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + if (tsp && timeout >= 0) { + struct compat_timespec rts; + + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + /* Yes, we know it's actually an s64, but it's also positive. */ + rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * + 1000; + rts.tv_sec = timeout; + if (compat_timespec_compare(&rts, &ts) < 0) + rts = ts; + if (copy_to_user(tsp, &rts, sizeof(rts))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND && timeout >= 0) + ret = -EINTR; + } + } + + return ret; +} +#endif /* TIF_RESTORE_SIGMASK */ + #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) /* Stuff for NFS server syscalls... */ struct compat_nfsctl_svc { diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 5dd0207ffd46..057e60217fc5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -931,8 +931,8 @@ struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { int err, i; - sg_req_info_t *r; - struct compat_sg_req_info *o = (struct compat_sg_req_info *)arg; + sg_req_info_t __user *r; + struct compat_sg_req_info __user *o = (void __user *)arg; r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE); err = sys_ioctl(fd,cmd,(unsigned long)r); if (err < 0) @@ -2739,8 +2739,8 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon static int lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct compat_timeval *tc = (struct compat_timeval *)arg; - struct timeval *tn = compat_alloc_user_space(sizeof(struct timeval)); + struct compat_timeval __user *tc = (struct compat_timeval __user *)arg; + struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval)); struct timeval ts; if (get_user(ts.tv_sec, &tc->tv_sec) || get_user(ts.tv_usec, &tc->tv_usec) || diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index 8899d9c5f6bf..f70e46951b37 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h @@ -36,6 +36,7 @@ struct configfs_dirent { int s_type; umode_t s_mode; struct dentry * s_dentry; + struct iattr * s_iattr; }; #define CONFIGFS_ROOT 0x0001 @@ -48,10 +49,11 @@ struct configfs_dirent { #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) extern struct vfsmount * configfs_mount; +extern kmem_cache_t *configfs_dir_cachep; extern int configfs_is_root(struct config_item *item); -extern struct inode * configfs_new_inode(mode_t mode); +extern struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent *); extern int configfs_create(struct dentry *, int mode, int (*init)(struct inode *)); extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); @@ -63,6 +65,7 @@ extern void configfs_hash_and_remove(struct dentry * dir, const char * name); extern const unsigned char * configfs_get_name(struct configfs_dirent *sd); extern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent); +extern int configfs_setattr(struct dentry *dentry, struct iattr *iattr); extern int configfs_pin_fs(void); extern void configfs_release_fs(void); @@ -120,8 +123,10 @@ static inline struct config_item *configfs_get_config_item(struct dentry *dentry static inline void release_configfs_dirent(struct configfs_dirent * sd) { - if (!(sd->s_type & CONFIGFS_ROOT)) - kfree(sd); + if (!(sd->s_type & CONFIGFS_ROOT)) { + kfree(sd->s_iattr); + kmem_cache_free(configfs_dir_cachep, sd); + } } static inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index b668ec61527e..ca60e3abef45 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -72,7 +72,7 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare { struct configfs_dirent * sd; - sd = kmalloc(sizeof(*sd), GFP_KERNEL); + sd = kmem_cache_alloc(configfs_dir_cachep, GFP_KERNEL); if (!sd) return NULL; @@ -136,13 +136,19 @@ static int create_dir(struct config_item * k, struct dentry * p, int error; umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; - error = configfs_create(d, mode, init_dir); + error = configfs_make_dirent(p->d_fsdata, d, k, mode, + CONFIGFS_DIR); if (!error) { - error = configfs_make_dirent(p->d_fsdata, d, k, mode, - CONFIGFS_DIR); + error = configfs_create(d, mode, init_dir); if (!error) { p->d_inode->i_nlink++; (d)->d_op = &configfs_dentry_ops; + } else { + struct configfs_dirent *sd = d->d_fsdata; + if (sd) { + list_del_init(&sd->s_sibling); + configfs_put(sd); + } } } return error; @@ -182,12 +188,19 @@ int configfs_create_link(struct configfs_symlink *sl, int err = 0; umode_t mode = S_IFLNK | S_IRWXUGO; - err = configfs_create(dentry, mode, init_symlink); + err = configfs_make_dirent(parent->d_fsdata, dentry, sl, mode, + CONFIGFS_ITEM_LINK); if (!err) { - err = configfs_make_dirent(parent->d_fsdata, dentry, sl, - mode, CONFIGFS_ITEM_LINK); + err = configfs_create(dentry, mode, init_symlink); if (!err) dentry->d_op = &configfs_dentry_ops; + else { + struct configfs_dirent *sd = dentry->d_fsdata; + if (sd) { + list_del_init(&sd->s_sibling); + configfs_put(sd); + } + } } return err; } @@ -241,13 +254,15 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den struct configfs_attribute * attr = sd->s_element; int error; + dentry->d_fsdata = configfs_get(sd); + sd->s_dentry = dentry; error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file); - if (error) + if (error) { + configfs_put(sd); return error; + } dentry->d_op = &configfs_dentry_ops; - dentry->d_fsdata = configfs_get(sd); - sd->s_dentry = dentry; d_rehash(dentry); return 0; @@ -839,6 +854,7 @@ struct inode_operations configfs_dir_inode_operations = { .symlink = configfs_symlink, .unlink = configfs_unlink, .lookup = configfs_lookup, + .setattr = configfs_setattr, }; #if 0 diff --git a/fs/configfs/file.c b/fs/configfs/file.c index c26cd61f13af..3921920d8716 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -26,7 +26,6 @@ #include <linux/fs.h> #include <linux/module.h> -#include <linux/dnotify.h> #include <linux/slab.h> #include <asm/uaccess.h> #include <asm/semaphore.h> @@ -150,7 +149,7 @@ out: /** * fill_write_buffer - copy buffer from userspace. * @buffer: data buffer for file. - * @userbuf: data from user. + * @buf: data from user. * @count: number of bytes in @userbuf. * * Allocate @buffer->page if it hasn't been already, then @@ -177,8 +176,9 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size /** * flush_write_buffer - push buffer to config_item. - * @file: file pointer. + * @dentry: dentry to the attribute * @buffer: data buffer for file. + * @count: number of bytes * * Get the correct pointers for the config_item and the attribute we're * dealing with, then call the store() method for the attribute, @@ -217,15 +217,16 @@ static ssize_t configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct configfs_buffer * buffer = file->private_data; + ssize_t len; down(&buffer->sem); - count = fill_write_buffer(buffer,buf,count); - if (count > 0) - count = flush_write_buffer(file->f_dentry,buffer,count); - if (count > 0) - *ppos += count; + len = fill_write_buffer(buffer, buf, count); + if (len > 0) + len = flush_write_buffer(file->f_dentry, buffer, count); + if (len > 0) + *ppos += len; up(&buffer->sem); - return count; + return len; } static int check_perm(struct inode * inode, struct file * file) diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index 6577c588de9d..c153bd9534cb 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -31,6 +31,7 @@ #include <linux/pagemap.h> #include <linux/namei.h> #include <linux/backing-dev.h> +#include <linux/capability.h> #include <linux/configfs.h> #include "configfs_internal.h" @@ -48,18 +49,107 @@ static struct backing_dev_info configfs_backing_dev_info = { .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, }; -struct inode * configfs_new_inode(mode_t mode) +static struct inode_operations configfs_inode_operations ={ + .setattr = configfs_setattr, +}; + +int configfs_setattr(struct dentry * dentry, struct iattr * iattr) +{ + struct inode * inode = dentry->d_inode; + struct configfs_dirent * sd = dentry->d_fsdata; + struct iattr * sd_iattr; + unsigned int ia_valid = iattr->ia_valid; + int error; + + if (!sd) + return -EINVAL; + + sd_iattr = sd->s_iattr; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + error = inode_setattr(inode, iattr); + if (error) + return error; + + if (!sd_iattr) { + /* setting attributes for the first time, allocate now */ + sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL); + if (!sd_iattr) + return -ENOMEM; + /* assign default attributes */ + memset(sd_iattr, 0, sizeof(struct iattr)); + sd_iattr->ia_mode = sd->s_mode; + sd_iattr->ia_uid = 0; + sd_iattr->ia_gid = 0; + sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; + sd->s_iattr = sd_iattr; + } + + /* attributes were changed atleast once in past */ + + if (ia_valid & ATTR_UID) + sd_iattr->ia_uid = iattr->ia_uid; + if (ia_valid & ATTR_GID) + sd_iattr->ia_gid = iattr->ia_gid; + if (ia_valid & ATTR_ATIME) + sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MTIME) + sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_CTIME) + sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MODE) { + umode_t mode = iattr->ia_mode; + + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + mode &= ~S_ISGID; + sd_iattr->ia_mode = sd->s_mode = mode; + } + + return error; +} + +static inline void set_default_inode_attr(struct inode * inode, mode_t mode) +{ + inode->i_mode = mode; + inode->i_uid = 0; + inode->i_gid = 0; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +} + +static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) +{ + inode->i_mode = iattr->ia_mode; + inode->i_uid = iattr->ia_uid; + inode->i_gid = iattr->ia_gid; + inode->i_atime = iattr->ia_atime; + inode->i_mtime = iattr->ia_mtime; + inode->i_ctime = iattr->ia_ctime; +} + +struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd) { struct inode * inode = new_inode(configfs_sb); if (inode) { - inode->i_mode = mode; - inode->i_uid = 0; - inode->i_gid = 0; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mapping->a_ops = &configfs_aops; inode->i_mapping->backing_dev_info = &configfs_backing_dev_info; + inode->i_op = &configfs_inode_operations; + + if (sd->s_iattr) { + /* sysfs_dirent has non-default attributes + * get them for the new inode from persistent copy + * in sysfs_dirent + */ + set_inode_attr(inode, sd->s_iattr); + } else + set_default_inode_attr(inode, mode); } return inode; } @@ -70,7 +160,8 @@ int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode * struct inode * inode = NULL; if (dentry) { if (!dentry->d_inode) { - if ((inode = configfs_new_inode(mode))) { + struct configfs_dirent *sd = dentry->d_fsdata; + if ((inode = configfs_new_inode(mode, sd))) { if (dentry->d_parent && dentry->d_parent->d_inode) { struct inode *p_inode = dentry->d_parent->d_inode; p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; @@ -103,10 +194,9 @@ int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode * */ const unsigned char * configfs_get_name(struct configfs_dirent *sd) { - struct attribute * attr; + struct configfs_attribute *attr; - if (!sd || !sd->s_element) - BUG(); + BUG_ON(!sd || !sd->s_element); /* These always have a dentry, so use that */ if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) @@ -114,7 +204,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd) if (sd->s_type & CONFIGFS_ITEM_ATTR) { attr = sd->s_element; - return attr->name; + return attr->ca_name; } return NULL; } @@ -130,13 +220,17 @@ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) if (dentry) { spin_lock(&dcache_lock); + spin_lock(&dentry->d_lock); if (!(d_unhashed(dentry) && dentry->d_inode)) { dget_locked(dentry); __d_drop(dentry); + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); simple_unlink(parent->d_inode, dentry); - } else + } else { + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + } } } @@ -145,6 +239,10 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name) struct configfs_dirent * sd; struct configfs_dirent * parent_sd = dir->d_fsdata; + if (dir->d_inode == NULL) + /* no inode means this hasn't been made visible yet */ + return; + mutex_lock(&dir->d_inode->i_mutex); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index 1a2f6f6a4d91..f920d30478e5 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -38,6 +38,7 @@ struct vfsmount * configfs_mount = NULL; struct super_block * configfs_sb = NULL; +kmem_cache_t *configfs_dir_cachep; static int configfs_mnt_count = 0; static struct super_operations configfs_ops = { @@ -62,6 +63,7 @@ static struct configfs_dirent configfs_root = { .s_children = LIST_HEAD_INIT(configfs_root.s_children), .s_element = &configfs_root_group.cg_item, .s_type = CONFIGFS_ROOT, + .s_iattr = NULL, }; static int configfs_fill_super(struct super_block *sb, void *data, int silent) @@ -73,9 +75,11 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = CONFIGFS_MAGIC; sb->s_op = &configfs_ops; + sb->s_time_gran = 1; configfs_sb = sb; - inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); + inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, + &configfs_root); if (inode) { inode->i_op = &configfs_dir_inode_operations; inode->i_fop = &configfs_dir_operations; @@ -128,19 +132,31 @@ static decl_subsys(config, NULL, NULL); static int __init configfs_init(void) { - int err; + int err = -ENOMEM; + + configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", + sizeof(struct configfs_dirent), + 0, 0, NULL, NULL); + if (!configfs_dir_cachep) + goto out; kset_set_kset_s(&config_subsys, kernel_subsys); err = subsystem_register(&config_subsys); - if (err) - return err; + if (err) { + kmem_cache_destroy(configfs_dir_cachep); + configfs_dir_cachep = NULL; + goto out; + } err = register_filesystem(&configfs_fs_type); if (err) { printk(KERN_ERR "configfs: Unable to register filesystem!\n"); subsystem_unregister(&config_subsys); + kmem_cache_destroy(configfs_dir_cachep); + configfs_dir_cachep = NULL; } +out: return err; } @@ -148,11 +164,13 @@ static void __exit configfs_exit(void) { unregister_filesystem(&configfs_fs_type); subsystem_unregister(&config_subsys); + kmem_cache_destroy(configfs_dir_cachep); + configfs_dir_cachep = NULL; } MODULE_AUTHOR("Oracle"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.1"); +MODULE_VERSION("0.0.2"); MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); module_init(configfs_init); diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 50f5840521a9..e5512e295cf2 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -162,8 +162,7 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry) if (!(sd->s_type & CONFIGFS_ITEM_LINK)) goto out; - if (dentry->d_parent == configfs_sb->s_root) - BUG(); + BUG_ON(dentry->d_parent == configfs_sb->s_root); sl = sd->s_element; @@ -277,5 +276,6 @@ struct inode_operations configfs_symlink_inode_operations = { .follow_link = configfs_follow_link, .readlink = generic_readlink, .put_link = configfs_put_link, + .setattr = configfs_setattr, }; diff --git a/fs/dcache.c b/fs/dcache.c index 86bdb93789c6..a173bba32666 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -743,7 +743,9 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) dentry->d_op = NULL; dentry->d_fsdata = NULL; dentry->d_mounted = 0; +#ifdef CONFIG_PROFILING dentry->d_cookie = NULL; +#endif INIT_HLIST_NODE(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index efc97d9b7860..d575452cd9f7 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -56,7 +56,7 @@ static u64 debugfs_u8_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); /** - * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. + * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write an unsigned 8 bit value. * * @name: a pointer to a string containing the name of the file to create. * @mode: the permission that the file should have @@ -98,7 +98,7 @@ static u64 debugfs_u16_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); /** - * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. + * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write an unsigned 16 bit value. * * @name: a pointer to a string containing the name of the file to create. * @mode: the permission that the file should have @@ -140,7 +140,7 @@ static u64 debugfs_u32_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); /** - * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. + * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write an unsigned 32 bit value. * * @name: a pointer to a string containing the name of the file to create. * @mode: the permission that the file should have diff --git a/fs/direct-io.c b/fs/direct-io.c index 30dbbd1df511..848044af7e16 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -857,6 +857,7 @@ do_holes: /* Handle holes */ if (!buffer_mapped(map_bh)) { char *kaddr; + loff_t i_size_aligned; /* AKPM: eargh, -ENOTBLK is a hack */ if (dio->rw == WRITE) { @@ -864,8 +865,14 @@ do_holes: return -ENOTBLK; } + /* + * Be sure to account for a partial block as the + * last block in the file + */ + i_size_aligned = ALIGN(i_size_read(dio->inode), + 1 << blkbits); if (dio->block_in_file >= - i_size_read(dio->inode)>>blkbits) { + i_size_aligned >> blkbits) { /* We hit eof */ page_cache_release(page); goto out; diff --git a/fs/exec.c b/fs/exec.c index 62b40af68cc4..055378d2513e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -477,7 +477,7 @@ struct file *open_exec(const char *name) int err; struct file *file; - err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ); + err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ); file = ERR_PTR(err); if (!err) { diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 5bfe40085fbc..b06b54f1bbbb 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -11,6 +11,33 @@ struct export_operations export_op_default; #define dprintk(fmt, args...) do{}while(0) +static struct dentry * +find_acceptable_alias(struct dentry *result, + int (*acceptable)(void *context, struct dentry *dentry), + void *context) +{ + struct dentry *dentry, *toput = NULL; + + spin_lock(&dcache_lock); + list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { + dget_locked(dentry); + spin_unlock(&dcache_lock); + if (toput) + dput(toput); + if (dentry != result && acceptable(context, dentry)) { + dput(result); + return dentry; + } + spin_lock(&dcache_lock); + toput = dentry; + } + spin_unlock(&dcache_lock); + + if (toput) + dput(toput); + return NULL; +} + /** * find_exported_dentry - helper routine to implement export_operations->decode_fh * @sb: The &super_block identifying the filesystem @@ -52,8 +79,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, struct dentry *target_dir; int err; struct export_operations *nops = sb->s_export_op; - struct list_head *le, *head; - struct dentry *toput = NULL; + struct dentry *alias; int noprogress; char nbuf[NAME_MAX+1]; @@ -79,27 +105,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, /* there is no other dentry, so fail */ goto err_result; } - /* try any other aliases */ - spin_lock(&dcache_lock); - head = &result->d_inode->i_dentry; - list_for_each(le, head) { - struct dentry *dentry = list_entry(le, struct dentry, d_alias); - dget_locked(dentry); - spin_unlock(&dcache_lock); - if (toput) - dput(toput); - toput = NULL; - if (dentry != result && - acceptable(context, dentry)) { - dput(result); - return dentry; - } - spin_lock(&dcache_lock); - toput = dentry; - } - spin_unlock(&dcache_lock); - if (toput) - dput(toput); + + alias = find_acceptable_alias(result, acceptable, context); + if (alias) + return alias; } /* It's a directory, or we are required to confirm the file's @@ -258,26 +267,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, /* now result is properly connected, it is our best bet */ if (acceptable(context, result)) return result; - /* one last try of the aliases.. */ - spin_lock(&dcache_lock); - toput = NULL; - head = &result->d_inode->i_dentry; - list_for_each(le, head) { - struct dentry *dentry = list_entry(le, struct dentry, d_alias); - dget_locked(dentry); - spin_unlock(&dcache_lock); - if (toput) dput(toput); - if (dentry != result && - acceptable(context, dentry)) { - dput(result); - return dentry; - } - spin_lock(&dcache_lock); - toput = dentry; - } - spin_unlock(&dcache_lock); - if (toput) - dput(toput); + + alias = find_acceptable_alias(result, acceptable, context); + if (alias) + return alias; /* drat - I just cannot find anything acceptable */ dput(result); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 35acc43b897f..da52b4a5db64 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -220,7 +220,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) struct ext2_inode_info *ei = EXT2_I(inode); int name_index; void *value = NULL; - size_t size; + size_t size = 0; int error; if (S_ISLNK(inode->i_mode)) diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 74714af4ae69..e52765219e16 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -605,7 +605,7 @@ got: insert_inode_hash(inode); if (DQUOT_ALLOC_INODE(inode)) { - err = -ENOSPC; + err = -EDQUOT; goto fail_drop; } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index e7d3f0522d01..a717837f272e 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -706,6 +706,7 @@ struct address_space_operations ext2_aops = { .bmap = ext2_bmap, .direct_IO = ext2_direct_IO, .writepages = ext2_writepages, + .migratepage = buffer_migrate_page, }; struct address_space_operations ext2_aops_xip = { @@ -723,6 +724,7 @@ struct address_space_operations ext2_nobh_aops = { .bmap = ext2_bmap, .direct_IO = ext2_direct_IO, .writepages = ext2_writepages, + .migratepage = buffer_migrate_page, }; /* diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 8d6819846fc9..cb6f9bd658de 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -221,6 +221,11 @@ static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",grpquota"); #endif +#if defined(CONFIG_EXT2_FS_XIP) + if (sbi->s_mount_opt & EXT2_MOUNT_XIP) + seq_puts(seq, ",xip"); +#endif + return 0; } diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 47a9da2dfb4f..0d21d558b87a 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -226,7 +226,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, struct ext3_inode_info *ei = EXT3_I(inode); int name_index; void *value = NULL; - size_t size; + size_t size = 0; int error; if (S_ISLNK(inode->i_mode)) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 8824e84f8a56..3fc4238e9703 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1559,6 +1559,7 @@ static struct address_space_operations ext3_ordered_aops = { .invalidatepage = ext3_invalidatepage, .releasepage = ext3_releasepage, .direct_IO = ext3_direct_IO, + .migratepage = buffer_migrate_page, }; static struct address_space_operations ext3_writeback_aops = { @@ -1572,6 +1573,7 @@ static struct address_space_operations ext3_writeback_aops = { .invalidatepage = ext3_invalidatepage, .releasepage = ext3_releasepage, .direct_IO = ext3_direct_IO, + .migratepage = buffer_migrate_page, }; static struct address_space_operations ext3_journalled_aops = { diff --git a/fs/fat/file.c b/fs/fat/file.c index e99c5a73b39e..88aa1ae13f9f 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -210,10 +210,30 @@ static int fat_free(struct inode *inode, int skip) if (MSDOS_I(inode)->i_start == 0) return 0; - /* - * Write a new EOF, and get the remaining cluster chain for freeing. - */ + fat_cache_inval_inode(inode); + wait = IS_DIRSYNC(inode); + i_start = free_start = MSDOS_I(inode)->i_start; + i_logstart = MSDOS_I(inode)->i_logstart; + + /* First, we write the new file size. */ + if (!skip) { + MSDOS_I(inode)->i_start = 0; + MSDOS_I(inode)->i_logstart = 0; + } + MSDOS_I(inode)->i_attrs |= ATTR_ARCH; + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + if (wait) { + err = fat_sync_inode(inode); + if (err) { + MSDOS_I(inode)->i_start = i_start; + MSDOS_I(inode)->i_logstart = i_logstart; + return err; + } + } else + mark_inode_dirty(inode); + + /* Write a new EOF, and get the remaining cluster chain for freeing. */ if (skip) { struct fat_entry fatent; int ret, fclus, dclus; @@ -244,35 +264,11 @@ static int fat_free(struct inode *inode, int skip) return ret; free_start = ret; - i_start = i_logstart = 0; - fat_cache_inval_inode(inode); - } else { - fat_cache_inval_inode(inode); - - i_start = free_start = MSDOS_I(inode)->i_start; - i_logstart = MSDOS_I(inode)->i_logstart; - MSDOS_I(inode)->i_start = 0; - MSDOS_I(inode)->i_logstart = 0; } - MSDOS_I(inode)->i_attrs |= ATTR_ARCH; - inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; - if (wait) { - err = fat_sync_inode(inode); - if (err) - goto error; - } else - mark_inode_dirty(inode); inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9); /* Freeing the remained cluster chain */ return fat_free_clusters(inode, free_start); - -error: - if (i_start) { - MSDOS_I(inode)->i_start = i_start; - MSDOS_I(inode)->i_logstart = i_logstart; - } - return err; } void fat_truncate(struct inode *inode) diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 32fb0a3f1da4..944652e9dde1 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -196,19 +196,9 @@ EXPORT_SYMBOL_GPL(fat_date_unix2dos); int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) { - int i, e, err = 0; + int i, err = 0; - for (i = 0; i < nr_bhs; i++) { - lock_buffer(bhs[i]); - if (test_clear_buffer_dirty(bhs[i])) { - get_bh(bhs[i]); - bhs[i]->b_end_io = end_buffer_write_sync; - e = submit_bh(WRITE, bhs[i]); - if (!err && e) - err = e; - } else - unlock_buffer(bhs[i]); - } + ll_rw_block(SWRITE, nr_bhs, bhs); for (i = 0; i < nr_bhs; i++) { wait_on_buffer(bhs[i]); if (buffer_eopnotsupp(bhs[i])) { diff --git a/fs/fcntl.c b/fs/fcntl.c index 5f96786d1c73..dc4a7007f4e7 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -208,8 +208,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) struct inode * inode = filp->f_dentry->d_inode; int error = 0; - /* O_APPEND cannot be cleared if the file is marked as append-only */ - if (!(arg & O_APPEND) && IS_APPEND(inode)) + /* + * O_APPEND cannot be cleared if the file is marked as append-only + * and the file is open for write. + */ + if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode)) return -EPERM; /* O_NOATIME can only be set by the owner or superuser */ diff --git a/fs/file.c b/fs/file.c index fd066b261c75..cea7cbea11d0 100644 --- a/fs/file.c +++ b/fs/file.c @@ -379,7 +379,6 @@ static void __devinit fdtable_defer_list_init(int cpu) void __init files_defer_init(void) { int i; - /* Really early - can't use for_each_cpu */ - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) fdtable_defer_list_init(i); } diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 4526da8907c6..f556a0d5c0d3 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -120,9 +120,9 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc) return do_get_request(fc); } +/* Must be called with fuse_lock held */ static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) { - spin_lock(&fuse_lock); if (req->preallocated) { atomic_dec(&fc->num_waiting); list_add(&req->list, &fc->unused_list); @@ -134,11 +134,19 @@ static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) fc->outstanding_debt--; else up(&fc->outstanding_sem); - spin_unlock(&fuse_lock); } void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) { + if (atomic_dec_and_test(&req->count)) { + spin_lock(&fuse_lock); + fuse_putback_request(fc, req); + spin_unlock(&fuse_lock); + } +} + +static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req) +{ if (atomic_dec_and_test(&req->count)) fuse_putback_request(fc, req); } @@ -163,26 +171,36 @@ void fuse_release_background(struct fuse_req *req) * still waiting), the 'end' callback is called if given, else the * reference to the request is released * + * Releasing extra reference for foreground requests must be done + * within the same locked region as setting state to finished. This + * is because fuse_reset_request() may be called after request is + * finished and it must be the sole possessor. If request is + * interrupted and put in the background, it will return with an error + * and hence never be reset and reused. + * * Called with fuse_lock, unlocks it */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { - void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; - req->end = NULL; list_del(&req->list); req->state = FUSE_REQ_FINISHED; - spin_unlock(&fuse_lock); - if (req->background) { + if (!req->background) { + wake_up(&req->waitq); + fuse_put_request_locked(fc, req); + spin_unlock(&fuse_lock); + } else { + void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; + req->end = NULL; + spin_unlock(&fuse_lock); down_read(&fc->sbput_sem); if (fc->mounted) fuse_release_background(req); up_read(&fc->sbput_sem); + if (end) + end(fc, req); + else + fuse_put_request(fc, req); } - wake_up(&req->waitq); - if (end) - end(fc, req); - else - fuse_put_request(fc, req); } /* diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a7ef5e716f3c..296351615b00 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -335,9 +335,14 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, loff_t pos = page_offset(req->pages[0]); size_t count = req->num_pages << PAGE_CACHE_SHIFT; req->out.page_zeroing = 1; - req->end = fuse_readpages_end; fuse_read_fill(req, file, inode, pos, count, FUSE_READ); - request_send_background(fc, req); + if (fc->async_read) { + req->end = fuse_readpages_end; + request_send_background(fc, req); + } else { + request_send(fc, req); + fuse_readpages_end(fc, req); + } } struct fuse_readpages_data { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 46cf933aa3bf..4a83adfec968 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -272,6 +272,9 @@ struct fuse_conn { reply, before any other request, and never cleared */ unsigned conn_error : 1; + /** Do readpages asynchronously? Only set in INIT */ + unsigned async_read : 1; + /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index c755a0440a66..879e6fba9480 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -473,6 +473,16 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) fc->conn_error = 1; else { + unsigned long ra_pages; + + if (arg->minor >= 6) { + ra_pages = arg->max_readahead / PAGE_CACHE_SIZE; + if (arg->flags & FUSE_ASYNC_READ) + fc->async_read = 1; + } else + ra_pages = fc->max_read / PAGE_CACHE_SIZE; + + fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); fc->minor = arg->minor; fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; } @@ -496,6 +506,8 @@ static void fuse_send_init(struct fuse_conn *fc) arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; + arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; + arg->flags |= FUSE_ASYNC_READ; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); @@ -552,8 +564,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) fc->user_id = d.user_id; fc->group_id = d.group_id; fc->max_read = d.max_read; - if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) - fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; /* Used by get_root_inode() */ sb->s_fs_info = fc; diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c index 89450ae32228..f13f1494d4fe 100644 --- a/fs/hfs/bfind.c +++ b/fs/hfs/bfind.c @@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) else e = rec - 1; } while (b <= e); - //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec); if (rec != e && e >= 0) { len = hfs_brec_lenoff(bnode, e, &off); keylen = hfs_brec_keylen(bnode, e); @@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd) return res; invalid: - printk("HFS: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", + printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", height, bnode->height, bnode->type, nidx, parent); res = -EIO; release: diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 3d5cdc6847c0..a7a7d77f3fd3 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -198,7 +198,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node) // move down? if (!node->prev && !node->next) { - printk("hfs_btree_del_level\n"); + printk(KERN_DEBUG "hfs_btree_del_level\n"); } if (!node->parent) { tree->root = 0; @@ -219,7 +219,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid) struct hfs_bnode *node; if (cnid >= tree->node_count) { - printk("HFS: request for non-existent node %d in B*Tree\n", cnid); + printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); return NULL; } @@ -242,7 +242,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) loff_t off; if (cnid >= tree->node_count) { - printk("HFS: request for non-existent node %d in B*Tree\n", cnid); + printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); return NULL; } diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c index 7d8fff2c25fc..5c87cf4801fc 100644 --- a/fs/hfs/brec.c +++ b/fs/hfs/brec.c @@ -362,7 +362,7 @@ again: end_off = hfs_bnode_read_u16(parent, end_rec_off); if (end_rec_off - end_off < diff) { - printk("splitting index node...\n"); + printk(KERN_DEBUG "hfs: splitting index node...\n"); fd->bnode = parent; new_node = hfs_bnode_split(fd); if (IS_ERR(new_node)) diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c index 394725efa1c8..7bb11edd1488 100644 --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c @@ -111,7 +111,7 @@ void hfs_btree_close(struct hfs_btree *tree) while ((node = tree->node_hash[i])) { tree->node_hash[i] = node->next_hash; if (atomic_read(&node->refcnt)) - printk("HFS: node %d:%d still has %d user(s)!\n", + printk(KERN_ERR "hfs: node %d:%d still has %d user(s)!\n", node->tree->cnid, node->this, atomic_read(&node->refcnt)); hfs_bnode_free(node); tree->node_hash_cnt--; @@ -252,7 +252,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) kunmap(*pagep); nidx = node->next; if (!nidx) { - printk("create new bmap node...\n"); + printk(KERN_DEBUG "hfs: create new bmap node...\n"); next_node = hfs_bmap_new_bmap(node, idx); } else next_node = hfs_bnode_find(tree, nidx); @@ -292,7 +292,7 @@ void hfs_bmap_free(struct hfs_bnode *node) hfs_bnode_put(node); if (!i) { /* panic */; - printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); + printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this); return; } node = hfs_bnode_find(tree, i); @@ -300,7 +300,7 @@ void hfs_bmap_free(struct hfs_bnode *node) return; if (node->type != HFS_NODE_MAP) { /* panic */; - printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); + printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type); hfs_bnode_put(node); return; } @@ -313,7 +313,7 @@ void hfs_bmap_free(struct hfs_bnode *node) m = 1 << (~nidx & 7); byte = data[off]; if (!(byte & m)) { - printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); + printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type); kunmap(page); hfs_bnode_put(node); return; diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 2fcd679f0238..ba851576ebb1 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c @@ -184,7 +184,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid, type = rec.type; if (type != HFS_CDR_THD && type != HFS_CDR_FTH) { - printk("HFS-fs: Found bad thread record in catalog\n"); + printk(KERN_ERR "hfs: found bad thread record in catalog\n"); return -EIO; } diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index e1f24befba58..534e5a7480ef 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -81,12 +81,12 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) case 1: hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); if (entry.type != HFS_CDR_THD) { - printk("HFS: bad catalog folder thread\n"); + printk(KERN_ERR "hfs: bad catalog folder thread\n"); err = -EIO; goto out; } //if (fd.entrylength < HFS_MIN_THREAD_SZ) { - // printk("HFS: truncated catalog thread\n"); + // printk(KERN_ERR "hfs: truncated catalog thread\n"); // err = -EIO; // goto out; //} @@ -105,7 +105,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) for (;;) { if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) { - printk("HFS: walked past end of dir\n"); + printk(KERN_ERR "hfs: walked past end of dir\n"); err = -EIO; goto out; } @@ -114,7 +114,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); if (type == HFS_CDR_DIR) { if (fd.entrylength < sizeof(struct hfs_cat_dir)) { - printk("HFS: small dir entry\n"); + printk(KERN_ERR "hfs: small dir entry\n"); err = -EIO; goto out; } @@ -123,7 +123,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) break; } else if (type == HFS_CDR_FIL) { if (fd.entrylength < sizeof(struct hfs_cat_file)) { - printk("HFS: small file entry\n"); + printk(KERN_ERR "hfs: small file entry\n"); err = -EIO; goto out; } @@ -131,7 +131,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) be32_to_cpu(entry.file.FlNum), DT_REG)) break; } else { - printk("HFS: bad catalog entry type %d\n", type); + printk(KERN_ERR "hfs: bad catalog entry type %d\n", type); err = -EIO; goto out; } diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index cc5dcd52e23d..18ce47ab1b71 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -35,9 +35,6 @@ #define dprint(flg, fmt, args...) \ if (flg & DBG_MASK) printk(fmt , ## args) -#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args) -#define hfs_error(format, args...) printk(KERN_ERR format , ## args) - /* * struct hfs_inode_info * diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 050a49276499..39fd85b9b916 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -95,7 +95,6 @@ static int hfs_releasepage(struct page *page, gfp_t mask) } while (--i && nidx < tree->node_count); spin_unlock(&tree->hash_lock); } - //printk("releasepage: %lu,%x = %d\n", page->index, mask, res); return res ? try_to_free_buffers(page) : 0; } diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 0a473f79c89f..b4651e128d7f 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -47,7 +47,7 @@ static int hfs_get_last_session(struct super_block *sb, *start = (sector_t)te.cdte_addr.lba << 2; return 0; } - printk(KERN_ERR "HFS: Invalid session number or type of track\n"); + printk(KERN_ERR "hfs: invalid session number or type of track\n"); return -EINVAL; } ms_info.addr_format = CDROM_LBA; @@ -100,7 +100,7 @@ int hfs_mdb_get(struct super_block *sb) HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz); if (!size || (size & (HFS_SECTOR_SIZE - 1))) { - hfs_warn("hfs_fs: bad allocation block size %d\n", size); + printk(KERN_ERR "hfs: bad allocation block size %d\n", size); goto out_bh; } @@ -117,7 +117,7 @@ int hfs_mdb_get(struct super_block *sb) size >>= 1; brelse(bh); if (!sb_set_blocksize(sb, size)) { - printk("hfs_fs: unable to set blocksize to %u\n", size); + printk(KERN_ERR "hfs: unable to set blocksize to %u\n", size); goto out; } @@ -161,8 +161,8 @@ int hfs_mdb_get(struct super_block *sb) } if (!HFS_SB(sb)->alt_mdb) { - hfs_warn("hfs_fs: unable to locate alternate MDB\n"); - hfs_warn("hfs_fs: continuing without an alternate MDB\n"); + printk(KERN_WARNING "hfs: unable to locate alternate MDB\n"); + printk(KERN_WARNING "hfs: continuing without an alternate MDB\n"); } HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0); @@ -177,7 +177,7 @@ int hfs_mdb_get(struct super_block *sb) while (size) { bh = sb_bread(sb, off >> sb->s_blocksize_bits); if (!bh) { - hfs_warn("hfs_fs: unable to read volume bitmap\n"); + printk(KERN_ERR "hfs: unable to read volume bitmap\n"); goto out; } off2 = off & (sb->s_blocksize - 1); @@ -191,23 +191,23 @@ int hfs_mdb_get(struct super_block *sb) HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp); if (!HFS_SB(sb)->ext_tree) { - hfs_warn("hfs_fs: unable to open extent tree\n"); + printk(KERN_ERR "hfs: unable to open extent tree\n"); goto out; } HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp); if (!HFS_SB(sb)->cat_tree) { - hfs_warn("hfs_fs: unable to open catalog tree\n"); + printk(KERN_ERR "hfs: unable to open catalog tree\n"); goto out; } attrib = mdb->drAtrb; if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { - hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, " + printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, " "running fsck.hfs is recommended. mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) { - hfs_warn("HFS-fs: Filesystem is marked locked, mounting read-only.\n"); + printk(KERN_WARNING "hfs: filesystem is marked locked, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } if (!(sb->s_flags & MS_RDONLY)) { @@ -303,7 +303,7 @@ void hfs_mdb_commit(struct super_block *sb) while (size) { bh = sb_bread(sb, block); if (!bh) { - hfs_warn("hfs_fs: unable to read volume bitmap\n"); + printk(KERN_ERR "hfs: unable to read volume bitmap\n"); break; } len = min((int)sb->s_blocksize - off, size); diff --git a/fs/hfs/super.c b/fs/hfs/super.c index c5074aeafcae..1181d116117d 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -101,12 +101,12 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data) return 0; if (!(*flags & MS_RDONLY)) { if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { - printk("HFS-fs warning: Filesystem was not cleanly unmounted, " + printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, " "running fsck.hfs is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; } else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) { - printk("HFS-fs: Filesystem is marked locked, leaving read-only.\n"); + printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; } @@ -229,21 +229,21 @@ static int parse_options(char *options, struct hfs_sb_info *hsb) switch (token) { case opt_uid: if (match_int(&args[0], &tmp)) { - printk("HFS: uid requires an argument\n"); + printk(KERN_ERR "hfs: uid requires an argument\n"); return 0; } hsb->s_uid = (uid_t)tmp; break; case opt_gid: if (match_int(&args[0], &tmp)) { - printk("HFS: gid requires an argument\n"); + printk(KERN_ERR "hfs: gid requires an argument\n"); return 0; } hsb->s_gid = (gid_t)tmp; break; case opt_umask: if (match_octal(&args[0], &tmp)) { - printk("HFS: umask requires a value\n"); + printk(KERN_ERR "hfs: umask requires a value\n"); return 0; } hsb->s_file_umask = (umode_t)tmp; @@ -251,39 +251,39 @@ static int parse_options(char *options, struct hfs_sb_info *hsb) break; case opt_file_umask: if (match_octal(&args[0], &tmp)) { - printk("HFS: file_umask requires a value\n"); + printk(KERN_ERR "hfs: file_umask requires a value\n"); return 0; } hsb->s_file_umask = (umode_t)tmp; break; case opt_dir_umask: if (match_octal(&args[0], &tmp)) { - printk("HFS: dir_umask requires a value\n"); + printk(KERN_ERR "hfs: dir_umask requires a value\n"); return 0; } hsb->s_dir_umask = (umode_t)tmp; break; case opt_part: if (match_int(&args[0], &hsb->part)) { - printk("HFS: part requires an argument\n"); + printk(KERN_ERR "hfs: part requires an argument\n"); return 0; } break; case opt_session: if (match_int(&args[0], &hsb->session)) { - printk("HFS: session requires an argument\n"); + printk(KERN_ERR "hfs: session requires an argument\n"); return 0; } break; case opt_type: if (match_fourchar(&args[0], &hsb->s_type)) { - printk("HFS+-fs: type requires a 4 character value\n"); + printk(KERN_ERR "hfs: type requires a 4 character value\n"); return 0; } break; case opt_creator: if (match_fourchar(&args[0], &hsb->s_creator)) { - printk("HFS+-fs: creator requires a 4 character value\n"); + printk(KERN_ERR "hfs: creator requires a 4 character value\n"); return 0; } break; @@ -292,13 +292,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb) break; case opt_codepage: if (hsb->nls_disk) { - printk("HFS+-fs: unable to change codepage\n"); + printk(KERN_ERR "hfs: unable to change codepage\n"); return 0; } p = match_strdup(&args[0]); hsb->nls_disk = load_nls(p); if (!hsb->nls_disk) { - printk("HFS+-fs: unable to load codepage \"%s\"\n", p); + printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p); kfree(p); return 0; } @@ -306,13 +306,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb) break; case opt_iocharset: if (hsb->nls_io) { - printk("HFS: unable to change iocharset\n"); + printk(KERN_ERR "hfs: unable to change iocharset\n"); return 0; } p = match_strdup(&args[0]); hsb->nls_io = load_nls(p); if (!hsb->nls_io) { - printk("HFS: unable to load iocharset \"%s\"\n", p); + printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p); kfree(p); return 0; } @@ -326,7 +326,7 @@ static int parse_options(char *options, struct hfs_sb_info *hsb) if (hsb->nls_disk && !hsb->nls_io) { hsb->nls_io = load_nls_default(); if (!hsb->nls_io) { - printk("HFS: unable to load default iocharset\n"); + printk(KERN_ERR "hfs: unable to load default iocharset\n"); return 0; } } @@ -364,7 +364,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) res = -EINVAL; if (!parse_options((char *)data, sbi)) { - hfs_warn("hfs_fs: unable to parse mount options.\n"); + printk(KERN_ERR "hfs: unable to parse mount options.\n"); goto bail; } @@ -375,7 +375,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) res = hfs_mdb_get(sb); if (res) { if (!silent) - hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", + printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.\n", hfs_mdb_name(sb)); res = -EINVAL; goto bail; @@ -407,7 +407,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) bail_iput: iput(root_inode); bail_no_root: - hfs_warn("hfs_fs: get root inode failed.\n"); + printk(KERN_ERR "hfs: get root inode failed.\n"); bail: hfs_mdb_put(sb); return res; @@ -454,7 +454,7 @@ static void __exit exit_hfs_fs(void) { unregister_filesystem(&hfs_fs_type); if (kmem_cache_destroy(hfs_inode_cachep)) - printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n"); + printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n"); } module_init(init_hfs_fs) diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c index 257cdde0514b..5007a41f1be9 100644 --- a/fs/hfsplus/bfind.c +++ b/fs/hfsplus/bfind.c @@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) else e = rec - 1; } while (b <= e); - //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec); if (rec != e && e >= 0) { len = hfs_brec_lenoff(bnode, e, &off); keylen = hfs_brec_keylen(bnode, e); @@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd) return res; invalid: - printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", + printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", height, bnode->height, bnode->type, nidx, parent); res = -EIO; release: diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 930cd9212de8..8f07e8fbd03d 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -358,7 +358,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node) // move down? if (!node->prev && !node->next) { - printk("hfs_btree_del_level\n"); + printk(KERN_DEBUG "hfs_btree_del_level\n"); } if (!node->parent) { tree->root = 0; @@ -379,7 +379,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid) struct hfs_bnode *node; if (cnid >= tree->node_count) { - printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); + printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); return NULL; } @@ -402,7 +402,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) loff_t off; if (cnid >= tree->node_count) { - printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); + printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid); return NULL; } @@ -576,8 +576,9 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num) node = hfs_bnode_findhash(tree, num); spin_unlock(&tree->hash_lock); if (node) { - printk("new node %u already hashed?\n", num); - BUG(); + printk(KERN_CRIT "new node %u already hashed?\n", num); + WARN_ON(1); + return node; } node = __hfs_bnode_create(tree, num); if (!node) diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index 0ccef2ab790c..c88e5d72a402 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c @@ -360,7 +360,7 @@ again: end_off = hfs_bnode_read_u16(parent, end_rec_off); if (end_rec_off - end_off < diff) { - printk("splitting index node...\n"); + printk(KERN_DEBUG "hfs: splitting index node...\n"); fd->bnode = parent; new_node = hfs_bnode_split(fd); if (IS_ERR(new_node)) diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 44326aa2bd34..a67edfa34e9e 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c @@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) init_MUTEX(&tree->tree_lock); spin_lock_init(&tree->hash_lock); - /* Set the correct compare function */ tree->sb = sb; tree->cnid = id; - if (id == HFSPLUS_EXT_CNID) { - tree->keycmp = hfsplus_ext_cmp_key; - } else if (id == HFSPLUS_CAT_CNID) { - tree->keycmp = hfsplus_cat_cmp_key; - } else { - printk("HFS+-fs: unknown B*Tree requested\n"); - goto free_tree; - } tree->inode = iget(sb, id); if (!tree->inode) goto free_tree; @@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) tree->max_key_len = be16_to_cpu(head->max_key_len); tree->depth = be16_to_cpu(head->depth); + /* Set the correct compare function */ + if (id == HFSPLUS_EXT_CNID) { + tree->keycmp = hfsplus_ext_cmp_key; + } else if (id == HFSPLUS_CAT_CNID) { + if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && + (head->key_type == HFSPLUS_KEY_BINARY)) + tree->keycmp = hfsplus_cat_bin_cmp_key; + else + tree->keycmp = hfsplus_cat_case_cmp_key; + } else { + printk(KERN_ERR "hfs: unknown B*Tree requested\n"); + goto fail_page; + } + size = tree->node_size; if (!size || size & (size - 1)) goto fail_page; @@ -99,7 +104,7 @@ void hfs_btree_close(struct hfs_btree *tree) while ((node = tree->node_hash[i])) { tree->node_hash[i] = node->next_hash; if (atomic_read(&node->refcnt)) - printk("HFS+: node %d:%d still has %d user(s)!\n", + printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n", node->tree->cnid, node->this, atomic_read(&node->refcnt)); hfs_bnode_free(node); tree->node_hash_cnt--; @@ -223,10 +228,6 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) tree->free_nodes--; mark_inode_dirty(tree->inode); hfs_bnode_put(node); - if (!idx) { - printk("unexpected idx %u (%u)\n", idx, node->this); - BUG(); - } return hfs_bnode_create(tree, idx); } } @@ -242,7 +243,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) kunmap(*pagep); nidx = node->next; if (!nidx) { - printk("create new bmap node...\n"); + printk(KERN_DEBUG "hfs: create new bmap node...\n"); next_node = hfs_bmap_new_bmap(node, idx); } else next_node = hfs_bnode_find(tree, nidx); @@ -284,7 +285,7 @@ void hfs_bmap_free(struct hfs_bnode *node) hfs_bnode_put(node); if (!i) { /* panic */; - printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); + printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this); return; } node = hfs_bnode_find(tree, i); @@ -292,7 +293,7 @@ void hfs_bmap_free(struct hfs_bnode *node) return; if (node->type != HFS_NODE_MAP) { /* panic */; - printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); + printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type); hfs_bnode_put(node); return; } @@ -305,7 +306,7 @@ void hfs_bmap_free(struct hfs_bnode *node) m = 1 << (~nidx & 7); byte = data[off]; if (!(byte & m)) { - printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); + printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type); kunmap(page); hfs_bnode_put(node); return; diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 94712790c8b3..f2d7c49ce759 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c @@ -13,7 +13,8 @@ #include "hfsplus_fs.h" #include "hfsplus_raw.h" -int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) +int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1, + const hfsplus_btree_key *k2) { __be32 k1p, k2p; @@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) if (k1p != k2p) return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; - return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name); + return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name); +} + +int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1, + const hfsplus_btree_key *k2) +{ + __be32 k1p, k2p; + + k1p = k1->cat.parent; + k2p = k2->cat.parent; + if (k1p != k2p) + return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; + + return hfsplus_strcmp(&k1->cat.name, &k2->cat.name); } void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, @@ -80,8 +94,11 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i memset(folder, 0, sizeof(*folder)); folder->type = cpu_to_be16(HFSPLUS_FOLDER); folder->id = cpu_to_be32(inode->i_ino); - folder->create_date = folder->content_mod_date = - folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); + HFSPLUS_I(inode).create_date = + folder->create_date = + folder->content_mod_date = + folder->attribute_mod_date = + folder->access_date = hfsp_now2mt(); hfsplus_set_perms(inode, &folder->permissions); if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) /* invisible and namelocked */ @@ -95,18 +112,27 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i file->type = cpu_to_be16(HFSPLUS_FILE); file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); file->id = cpu_to_be32(cnid); - file->create_date = file->content_mod_date = - file->attribute_mod_date = file->access_date = hfsp_now2mt(); + HFSPLUS_I(inode).create_date = + file->create_date = + file->content_mod_date = + file->attribute_mod_date = + file->access_date = hfsp_now2mt(); if (cnid == inode->i_ino) { hfsplus_set_perms(inode, &file->permissions); - file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); - file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); + if (S_ISLNK(inode->i_mode)) { + file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); + file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); + } else { + file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); + file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); + } if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); } else { file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); file->user_info.fdFlags = cpu_to_be16(0x100); + file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); } return sizeof(*file); @@ -139,7 +165,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, type = be16_to_cpu(tmp.type); if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { - printk("HFS+-fs: Found bad thread record in catalog\n"); + printk(KERN_ERR "hfs: found bad thread record in catalog\n"); return -EIO; } diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 50c8f44b6c66..01a6fe3a395c 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -66,25 +66,32 @@ again: } cnid = be32_to_cpu(entry.file.id); if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && - entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { + entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && + (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || + entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && + HFSPLUS_SB(sb).hidden_dir) { struct qstr str; char name[32]; if (dentry->d_fsdata) { - err = -ENOENT; - inode = NULL; - goto out; + /* + * We found a link pointing to another link, + * so ignore it and treat it as regular file. + */ + cnid = (unsigned long)dentry->d_fsdata; + linkid = 0; + } else { + dentry->d_fsdata = (void *)(unsigned long)cnid; + linkid = be32_to_cpu(entry.file.permissions.dev); + str.len = sprintf(name, "iNode%d", linkid); + str.name = name; + hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); + goto again; } - dentry->d_fsdata = (void *)(unsigned long)cnid; - linkid = be32_to_cpu(entry.file.permissions.dev); - str.len = sprintf(name, "iNode%d", linkid); - str.name = name; - hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); - goto again; } else if (!dentry->d_fsdata) dentry->d_fsdata = (void *)(unsigned long)cnid; } else { - printk("HFS+-fs: Illegal catalog entry type in lookup\n"); + printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n"); err = -EIO; goto fail; } @@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) case 1: hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { - printk("HFS+-fs: bad catalog folder thread\n"); + printk(KERN_ERR "hfs: bad catalog folder thread\n"); err = -EIO; goto out; } if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { - printk("HFS+-fs: truncated catalog thread\n"); + printk(KERN_ERR "hfs: truncated catalog thread\n"); err = -EIO; goto out; } @@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) for (;;) { if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { - printk("HFS+-fs: walked past end of dir\n"); + printk(KERN_ERR "hfs: walked past end of dir\n"); err = -EIO; goto out; } @@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) goto out; if (type == HFSPLUS_FOLDER) { if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { - printk("HFS+-fs: small dir entry\n"); + printk(KERN_ERR "hfs: small dir entry\n"); err = -EIO; goto out; } @@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) break; } else if (type == HFSPLUS_FILE) { if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { - printk("HFS+-fs: small file entry\n"); + printk(KERN_ERR "hfs: small file entry\n"); err = -EIO; goto out; } @@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) be32_to_cpu(entry.file.id), DT_REG)) break; } else { - printk("HFS+-fs: bad catalog entry type\n"); + printk(KERN_ERR "hfs: bad catalog entry type\n"); err = -EIO; goto out; } @@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) if (res) return res; - inode->i_nlink--; + if (inode->i_nlink > 0) + inode->i_nlink--; hfsplus_delete_inode(inode); if (inode->i_ino != cnid && !inode->i_nlink) { if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { @@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) hfsplus_delete_inode(inode); } else inode->i_flags |= S_DEAD; - } + } else + inode->i_nlink = 0; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e3ff56a03011..1a7480089e82 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -16,7 +16,8 @@ #include "hfsplus_raw.h" /* Compare two extents keys, returns 0 on same, pos/neg for difference */ -int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) +int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1, + const hfsplus_btree_key *k2) { __be32 k1id, k2id; __be32 k1s, k2s; @@ -349,10 +350,9 @@ int hfsplus_file_extend(struct inode *inode) if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { // extend alloc file - printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, + printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); return -ENOSPC; - //BUG(); } down(&HFSPLUS_I(inode).extents_lock); diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 0fa1ab6250bf..7ae393637a0c 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -36,7 +36,7 @@ #define HFSPLUS_TYPE_DATA 0x00 #define HFSPLUS_TYPE_RSRC 0xFF -typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *); +typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *); #define NODE_HASH_SIZE 256 @@ -149,6 +149,7 @@ struct hfsplus_sb_info { #define HFSPLUS_SB_WRITEBACKUP 0x0001 #define HFSPLUS_SB_NODECOMPOSE 0x0002 #define HFSPLUS_SB_FORCE 0x0004 +#define HFSPLUS_SB_HFSX 0x0008 struct hfsplus_inode_info { @@ -165,6 +166,7 @@ struct hfsplus_inode_info { struct inode *rsrc_inode; unsigned long flags; + __be32 create_date; /* Device number in hfsplus_permissions in catalog */ u32 dev; /* BSD system and user file flags */ @@ -303,7 +305,8 @@ int hfs_brec_read(struct hfs_find_data *, void *, int); int hfs_brec_goto(struct hfs_find_data *, int); /* catalog.c */ -int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); +int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); +int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); @@ -312,7 +315,7 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *, struct inode *, struct qstr *); /* extents.c */ -int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); +int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *); void hfsplus_ext_write_extent(struct inode *); int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); @@ -350,7 +353,8 @@ extern u16 hfsplus_decompose_table[]; extern u16 hfsplus_compose_table[]; /* unicode.c */ -int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); +int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); +int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index b4fbed633219..49205531a500 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h @@ -22,8 +22,10 @@ #define HFSPLUS_SECTOR_SHIFT 9 #define HFSPLUS_VOLHEAD_SECTOR 2 #define HFSPLUS_VOLHEAD_SIG 0x482b +#define HFSPLUS_VOLHEAD_SIGX 0x4858 #define HFSPLUS_SUPER_MAGIC 0x482b -#define HFSPLUS_CURRENT_VERSION 4 +#define HFSPLUS_MIN_VERSION 4 +#define HFSPLUS_CURRENT_VERSION 5 #define HFSP_WRAP_MAGIC 0x4244 #define HFSP_WRAP_ATTRIB_SLOCK 0x8000 @@ -41,6 +43,9 @@ #define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ #define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ +#define HFSP_SYMLINK_TYPE 0x736c6e6b /* 'slnk' */ +#define HFSP_SYMLINK_CREATOR 0x72686170 /* 'rhap' */ + #define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ /* Structures used on disk */ @@ -161,7 +166,7 @@ struct hfs_btree_header_rec { u16 reserved1; __be32 clump_size; u8 btree_type; - u8 reserved2; + u8 key_type; __be32 attributes; u32 reserved3[16]; } __packed; @@ -186,6 +191,10 @@ struct hfs_btree_header_rec { #define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ #define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ +/* btree key type */ +#define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */ +#define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */ + /* HFS+ catalog entry key */ struct hfsplus_cat_key { __be16 key_len; diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 7acff6c5464f..12ed2b7d046b 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -18,13 +18,11 @@ static int hfsplus_readpage(struct file *file, struct page *page) { - //printk("readpage: %lu\n", page->index); return block_read_full_page(page, hfsplus_get_block); } static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) { - //printk("writepage: %lu\n", page->index); return block_write_full_page(page, hfsplus_get_block, wbc); } @@ -92,7 +90,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) } while (--i && nidx < tree->node_count); spin_unlock(&tree->hash_lock); } - //printk("releasepage: %lu,%x = %d\n", page->index, mask, res); return res ? try_to_free_buffers(page) : 0; } @@ -434,7 +431,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) inode->i_size = 2 + be32_to_cpu(folder->valence); inode->i_atime = hfsp_mt2ut(folder->access_date); inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); - inode->i_ctime = inode->i_mtime; + inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); + HFSPLUS_I(inode).create_date = folder->create_date; HFSPLUS_I(inode).fs_blocks = 0; inode->i_op = &hfsplus_dir_inode_operations; inode->i_fop = &hfsplus_dir_operations; @@ -465,9 +463,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) } inode->i_atime = hfsp_mt2ut(file->access_date); inode->i_mtime = hfsp_mt2ut(file->content_mod_date); - inode->i_ctime = inode->i_mtime; + inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); + HFSPLUS_I(inode).create_date = file->create_date; } else { - printk("HFS+-fs: bad catalog entry used to create inode\n"); + printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); res = -EIO; } return res; diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 935dafba0078..dc64fac00831 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -83,58 +83,58 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) switch (token) { case opt_creator: if (match_fourchar(&args[0], &sbi->creator)) { - printk("HFS+-fs: creator requires a 4 character value\n"); + printk(KERN_ERR "hfs: creator requires a 4 character value\n"); return 0; } break; case opt_type: if (match_fourchar(&args[0], &sbi->type)) { - printk("HFS+-fs: type requires a 4 character value\n"); + printk(KERN_ERR "hfs: type requires a 4 character value\n"); return 0; } break; case opt_umask: if (match_octal(&args[0], &tmp)) { - printk("HFS+-fs: umask requires a value\n"); + printk(KERN_ERR "hfs: umask requires a value\n"); return 0; } sbi->umask = (umode_t)tmp; break; case opt_uid: if (match_int(&args[0], &tmp)) { - printk("HFS+-fs: uid requires an argument\n"); + printk(KERN_ERR "hfs: uid requires an argument\n"); return 0; } sbi->uid = (uid_t)tmp; break; case opt_gid: if (match_int(&args[0], &tmp)) { - printk("HFS+-fs: gid requires an argument\n"); + printk(KERN_ERR "hfs: gid requires an argument\n"); return 0; } sbi->gid = (gid_t)tmp; break; case opt_part: if (match_int(&args[0], &sbi->part)) { - printk("HFS+-fs: part requires an argument\n"); + printk(KERN_ERR "hfs: part requires an argument\n"); return 0; } break; case opt_session: if (match_int(&args[0], &sbi->session)) { - printk("HFS+-fs: session requires an argument\n"); + printk(KERN_ERR "hfs: session requires an argument\n"); return 0; } break; case opt_nls: if (sbi->nls) { - printk("HFS+-fs: unable to change nls mapping\n"); + printk(KERN_ERR "hfs: unable to change nls mapping\n"); return 0; } p = match_strdup(&args[0]); sbi->nls = load_nls(p); if (!sbi->nls) { - printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); + printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p); kfree(p); return 0; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index d791780def50..7843f792a4b7 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -169,7 +169,7 @@ static void hfsplus_write_super(struct super_block *sb) block = HFSPLUS_SB(sb).blockoffset; block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); - printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, + printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, HFSPLUS_SB(sb).sect_count, block, offset); bh = sb_bread(sb, block); if (bh) { @@ -179,7 +179,7 @@ static void hfsplus_write_super(struct super_block *sb) mark_buffer_dirty(bh); brelse(bh); } else - printk("backup not found!\n"); + printk(KERN_WARNING "hfs: backup not found!\n"); } } HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; @@ -240,18 +240,18 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) return -EINVAL; if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { - printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " + printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; } else if (sbi.flags & HFSPLUS_SB_FORCE) { /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { - printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); + printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { - printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n"); + printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; } @@ -292,8 +292,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) INIT_HLIST_HEAD(&sbi->rsrc_inodes); hfsplus_fill_defaults(sbi); if (!hfsplus_parse_options(data, sbi)) { - if (!silent) - printk("HFS+-fs: unable to parse mount options\n"); + printk(KERN_ERR "hfs: unable to parse mount options\n"); err = -EINVAL; goto cleanup; } @@ -302,7 +301,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) nls = sbi->nls; sbi->nls = load_nls("utf8"); if (!sbi->nls) { - printk("HFS+: unable to load nls for utf8\n"); + printk(KERN_ERR "hfs: unable to load nls for utf8\n"); err = -EINVAL; goto cleanup; } @@ -310,17 +309,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) /* Grab the volume header */ if (hfsplus_read_wrapper(sb)) { if (!silent) - printk("HFS+-fs: unable to find HFS+ superblock\n"); + printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n"); err = -EINVAL; goto cleanup; } vhdr = HFSPLUS_SB(sb).s_vhdr; /* Copy parts of the volume header into the superblock */ - sb->s_magic = be16_to_cpu(vhdr->signature); - if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) { - if (!silent) - printk("HFS+-fs: wrong filesystem version\n"); + sb->s_magic = HFSPLUS_VOLHEAD_SIG; + if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || + be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { + printk(KERN_ERR "hfs: wrong filesystem version\n"); goto cleanup; } HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); @@ -341,20 +340,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) sb->s_maxbytes = MAX_LFS_FILESIZE; if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { - if (!silent) - printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " - "running fsck.hfsplus is recommended. mounting read-only.\n"); + printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " + "running fsck.hfsplus is recommended. mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } else if (sbi->flags & HFSPLUS_SB_FORCE) { /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { - if (!silent) - printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); + printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { - if (!silent) - printk("HFS+-fs: write access to a jounaled filesystem is not supported, " - "use the force option at your own risk, mounting read-only.\n"); + printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, " + "use the force option at your own risk, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } sbi->flags &= ~HFSPLUS_SB_FORCE; @@ -362,21 +358,18 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) /* Load metadata objects (B*Trees) */ HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); if (!HFSPLUS_SB(sb).ext_tree) { - if (!silent) - printk("HFS+-fs: failed to load extents file\n"); + printk(KERN_ERR "hfs: failed to load extents file\n"); goto cleanup; } HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); if (!HFSPLUS_SB(sb).cat_tree) { - if (!silent) - printk("HFS+-fs: failed to load catalog file\n"); + printk(KERN_ERR "hfs: failed to load catalog file\n"); goto cleanup; } HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); if (!HFSPLUS_SB(sb).alloc_file) { - if (!silent) - printk("HFS+-fs: failed to load allocation file\n"); + printk(KERN_ERR "hfs: failed to load allocation file\n"); goto cleanup; } @@ -384,8 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) root = iget(sb, HFSPLUS_ROOT_CNID); sb->s_root = d_alloc_root(root); if (!sb->s_root) { - if (!silent) - printk("HFS+-fs: failed to load root directory\n"); + printk(KERN_ERR "hfs: failed to load root directory\n"); iput(root); goto cleanup; } @@ -419,7 +411,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); if (!HFSPLUS_SB(sb).hidden_dir) { - printk("HFS+: create hidden dir...\n"); + printk(KERN_DEBUG "hfs: create hidden dir...\n"); HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, &str, HFSPLUS_SB(sb).hidden_dir); @@ -499,7 +491,7 @@ static void __exit exit_hfsplus_fs(void) { unregister_filesystem(&hfsplus_fs_type); if (kmem_cache_destroy(hfsplus_inode_cachep)) - printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n"); + printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n"); } module_init(init_hfsplus_fs) diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 060c69048c3d..689c8bd721fb 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c @@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c) } /* Compare unicode strings, return values like normal strcmp */ -int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2) +int hfsplus_strcasecmp(const struct hfsplus_unistr *s1, + const struct hfsplus_unistr *s2) { u16 len1, len2, c1, c2; const hfsplus_unichr *p1, *p2; @@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis } } +/* Compare names as a sequence of 16-bit unsigned integers */ +int hfsplus_strcmp(const struct hfsplus_unistr *s1, + const struct hfsplus_unistr *s2) +{ + u16 len1, len2, c1, c2; + const hfsplus_unichr *p1, *p2; + int len; + + len1 = be16_to_cpu(s1->length); + len2 = be16_to_cpu(s2->length); + p1 = s1->unicode; + p2 = s2->unicode; + + for (len = min(len1, len2); len > 0; len--) { + c1 = be16_to_cpu(*p1); + c2 = be16_to_cpu(*p2); + if (c1 != c2) + return c1 < c2 ? -1 : 1; + p1++; + p2++; + } + + return len1 < len2 ? -1 : + len1 > len2 ? 1 : 0; +} + + #define Hangul_SBase 0xac00 #define Hangul_LBase 0x1100 #define Hangul_VBase 0x1161 diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 95455e839231..72cab78f0509 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) { u32 extent; u16 attrib; + __be16 sig; - if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG) + sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG); + if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) && + sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) return 0; attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); @@ -70,7 +73,7 @@ static int hfsplus_get_last_session(struct super_block *sb, *start = (sector_t)te.cdte_addr.lba << 2; return 0; } - printk(KERN_ERR "HFS: Invalid session number or type of track\n"); + printk(KERN_ERR "hfs: invalid session number or type of track\n"); return -EINVAL; } ms_info.addr_format = CDROM_LBA; @@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_block *sb) } if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) break; + if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { + HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX; + break; + } brelse(bh); /* check for a partition block @@ -143,7 +150,7 @@ int hfsplus_read_wrapper(struct super_block *sb) blocksize >>= 1; if (sb_set_blocksize(sb, blocksize) != blocksize) { - printk("HFS+: unable to blocksize to %u!\n", blocksize); + printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize); return -EINVAL; } @@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_block *sb) return -EIO; /* should still be the same... */ - if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG) + if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ? + cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) : + cpu_to_be16(HFSPLUS_VOLHEAD_SIG))) goto error; HFSPLUS_SB(sb).s_vhbh = bh; HFSPLUS_SB(sb).s_vhdr = vhdr; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index f568102da1e8..b35195289945 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -72,8 +72,8 @@ huge_pages_needed(struct address_space *mapping, struct vm_area_struct *vma) unsigned long start = vma->vm_start; unsigned long end = vma->vm_end; unsigned long hugepages = (end - start) >> HPAGE_SHIFT; - pgoff_t next = vma->vm_pgoff; - pgoff_t endpg = next + ((end - start) >> PAGE_SHIFT); + pgoff_t next = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); + pgoff_t endpg = next + hugepages; pagevec_init(&pvec, 0); while (next < endpg) { diff --git a/fs/inode.c b/fs/inode.c index 108138d4e909..d0be6159eb7f 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1179,7 +1179,7 @@ EXPORT_SYMBOL(bmap); /** * touch_atime - update the access time * @mnt: mount the inode is accessed on - * @inode: inode accessed + * @dentry: dentry accessed * * Update the accessed time on an inode and mark it for writeback. * This function automatically handles read only file systems and media, diff --git a/fs/inotify.c b/fs/inotify.c index 2fecb7af4a77..3041503bde02 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -33,6 +33,7 @@ #include <linux/list.h> #include <linux/writeback.h> #include <linux/inotify.h> +#include <linux/syscalls.h> #include <asm/ioctls.h> @@ -966,7 +967,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) mask_add = 1; /* don't let user-space set invalid bits: we don't want flags set */ - mask &= IN_ALL_EVENTS; + mask &= IN_ALL_EVENTS | IN_ONESHOT; if (unlikely(!mask)) { ret = -EINVAL; goto out; diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index cb3cef525c3b..e6265a0b56b8 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -338,7 +338,7 @@ restart: * done (maybe it's a new transaction, but it fell at the same * address). */ - if (journal->j_checkpoint_transactions == transaction || + if (journal->j_checkpoint_transactions == transaction && transaction->t_tid == this_tid) { int batch_count = 0; struct buffer_head *bhs[NR_BATCH]; diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 002ad2bbc769..29e62d98bae6 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -829,7 +829,8 @@ restart_loop: journal->j_committing_transaction = NULL; spin_unlock(&journal->j_state_lock); - if (commit_transaction->t_checkpoint_list == NULL) { + if (commit_transaction->t_checkpoint_list == NULL && + commit_transaction->t_checkpoint_io_list == NULL) { __journal_drop_transaction(journal, commit_transaction); } else { if (journal->j_checkpoint_transactions == NULL) { diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 429f4b263cf1..ca917973c2c0 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1308,6 +1308,7 @@ int journal_stop(handle_t *handle) transaction_t *transaction = handle->h_transaction; journal_t *journal = transaction->t_journal; int old_handle_count, err; + pid_t pid; J_ASSERT(transaction->t_updates > 0); J_ASSERT(journal_current_handle() == handle); @@ -1333,8 +1334,15 @@ int journal_stop(handle_t *handle) * It doesn't cost much - we're about to run a commit and sleep * on IO anyway. Speeds up many-threaded, many-dir operations * by 30x or more... + * + * But don't do this if this process was the most recent one to + * perform a synchronous write. We do this to detect the case where a + * single process is doing a stream of sync writes. No point in waiting + * for joiners in that case. */ - if (handle->h_sync) { + pid = current->pid; + if (handle->h_sync && journal->j_last_sync_writer != pid) { + journal->j_last_sync_writer = pid; do { old_handle_count = transaction->t_handle_count; schedule_timeout_uninterruptible(1); diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index b2e95421d932..ce7b54b0b2b7 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -1965,7 +1965,7 @@ retry: iovec_cnt++; if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) { - static char allff[3]={255,255,255}; + static unsigned char allff[3]={255,255,255}; /* Add some extra padding if necessary */ node_iovec[iovec_cnt].iov_base = allff; node_iovec[iovec_cnt].iov_len = diff --git a/fs/libfs.c b/fs/libfs.c index 63c020e6589e..71fd08fa4103 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -388,6 +388,7 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; + inode->i_nlink = 2; root = d_alloc_root(inode); if (!root) { iput(inode); diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 145524039577..220058d8616d 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -22,12 +22,14 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #define NLMCLNT_GRACE_WAIT (5*HZ) #define NLMCLNT_POLL_TIMEOUT (30*HZ) +#define NLMCLNT_MAX_RETRIES 3 static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); static int nlm_stat_to_errno(u32 stat); static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); +static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *); static const struct rpc_call_ops nlmclnt_unlock_ops; static const struct rpc_call_ops nlmclnt_cancel_ops; @@ -598,7 +600,7 @@ out_unblock: nlmclnt_finish_block(req); /* Cancel the blocked request if it is still pending */ if (resp->status == NLM_LCK_BLOCKED) - nlmclnt_cancel(host, fl); + nlmclnt_cancel(host, req->a_args.block, fl); out: nlmclnt_release_lockargs(req); return status; @@ -728,8 +730,7 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = { * We always use an async RPC call for this in order not to hang a * process that has been Ctrl-C'ed. */ -int -nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) +static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl) { struct nlm_rqst *req; unsigned long flags; @@ -750,6 +751,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) req->a_flags = RPC_TASK_ASYNC; nlmclnt_setlockargs(req, fl); + req->a_args.block = block; status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); if (status < 0) { @@ -801,6 +803,9 @@ die: return; retry_cancel: + /* Don't ever retry more than 3 times */ + if (req->a_retries++ >= NLMCLNT_MAX_RETRIES) + goto die; nlm_rebind_host(req->a_host); rpc_restart_call(task); rpc_delay(task, 30 * HZ); diff --git a/fs/namei.c b/fs/namei.c index 33fb5bd34a81..e28de846c591 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -30,6 +30,8 @@ #include <linux/audit.h> #include <linux/capability.h> #include <linux/file.h> +#include <linux/fcntl.h> +#include <linux/namei.h> #include <asm/namei.h> #include <asm/uaccess.h> @@ -788,7 +790,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) inode = nd->dentry->d_inode; if (nd->depth) - lookup_flags = LOOKUP_FOLLOW; + lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); /* At this point we know we have a real path component. */ for(;;) { @@ -883,7 +885,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) last_with_slashes: lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; last_component: - nd->flags &= ~LOOKUP_CONTINUE; + /* Clear LOOKUP_CONTINUE iff it was previously unset */ + nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; if (lookup_flags & LOOKUP_PARENT) goto lookup_parent; if (this.name[0] == '.') switch (this.len) { @@ -1063,9 +1066,12 @@ set_it: } /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ -int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) +static int fastcall do_path_lookup(int dfd, const char *name, + unsigned int flags, struct nameidata *nd) { int retval = 0; + int fput_needed; + struct file *file; nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -1083,22 +1089,59 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata } nd->mnt = mntget(current->fs->rootmnt); nd->dentry = dget(current->fs->root); - } else { + } else if (dfd == AT_FDCWD) { nd->mnt = mntget(current->fs->pwdmnt); nd->dentry = dget(current->fs->pwd); + } else { + struct dentry *dentry; + + file = fget_light(dfd, &fput_needed); + retval = -EBADF; + if (!file) + goto unlock_fail; + + dentry = file->f_dentry; + + retval = -ENOTDIR; + if (!S_ISDIR(dentry->d_inode->i_mode)) + goto fput_unlock_fail; + + retval = file_permission(file, MAY_EXEC); + if (retval) + goto fput_unlock_fail; + + nd->mnt = mntget(file->f_vfsmnt); + nd->dentry = dget(dentry); + + fput_light(file, fput_needed); } read_unlock(¤t->fs->lock); current->total_link_count = 0; retval = link_path_walk(name, nd); out: - if (unlikely(current->audit_context - && nd && nd->dentry && nd->dentry->d_inode)) + if (likely(retval == 0)) { + if (unlikely(current->audit_context && nd && nd->dentry && + nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode, flags); + } + return retval; + +fput_unlock_fail: + fput_light(file, fput_needed); +unlock_fail: + read_unlock(¤t->fs->lock); return retval; } -static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags, - struct nameidata *nd, int open_flags, int create_mode) +int fastcall path_lookup(const char *name, unsigned int flags, + struct nameidata *nd) +{ + return do_path_lookup(AT_FDCWD, name, flags, nd); +} + +static int __path_lookup_intent_open(int dfd, const char *name, + unsigned int lookup_flags, struct nameidata *nd, + int open_flags, int create_mode) { struct file *filp = get_empty_filp(); int err; @@ -1108,7 +1151,7 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags nd->intent.open.file = filp; nd->intent.open.flags = open_flags; nd->intent.open.create_mode = create_mode; - err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd); + err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd); if (IS_ERR(nd->intent.open.file)) { if (err == 0) { err = PTR_ERR(nd->intent.open.file); @@ -1121,32 +1164,34 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags /** * path_lookup_open - lookup a file path with open intent + * @dfd: the directory to use as base, or AT_FDCWD * @name: pointer to file name * @lookup_flags: lookup intent flags * @nd: pointer to nameidata * @open_flags: open intent flags */ -int path_lookup_open(const char *name, unsigned int lookup_flags, +int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags, struct nameidata *nd, int open_flags) { - return __path_lookup_intent_open(name, lookup_flags, nd, + return __path_lookup_intent_open(dfd, name, lookup_flags, nd, open_flags, 0); } /** * path_lookup_create - lookup a file path with open + create intent + * @dfd: the directory to use as base, or AT_FDCWD * @name: pointer to file name * @lookup_flags: lookup intent flags * @nd: pointer to nameidata * @open_flags: open intent flags * @create_mode: create intent flags */ -static int path_lookup_create(const char *name, unsigned int lookup_flags, - struct nameidata *nd, int open_flags, - int create_mode) +static int path_lookup_create(int dfd, const char *name, + unsigned int lookup_flags, struct nameidata *nd, + int open_flags, int create_mode) { - return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, - open_flags, create_mode); + return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE, + nd, open_flags, create_mode); } int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, @@ -1156,7 +1201,7 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, int err = PTR_ERR(tmp); if (!IS_ERR(tmp)) { - err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0); + err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0); putname(tmp); } return err; @@ -1248,18 +1293,24 @@ access: * that namei follows links, while lnamei does not. * SMP-safe */ -int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) +int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, + struct nameidata *nd) { char *tmp = getname(name); int err = PTR_ERR(tmp); if (!IS_ERR(tmp)) { - err = path_lookup(tmp, flags, nd); + err = do_path_lookup(dfd, tmp, flags, nd); putname(tmp); } return err; } +int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) +{ + return __user_walk_fd(AT_FDCWD, name, flags, nd); +} + /* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. @@ -1518,7 +1569,8 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) * for symlinks (where the permissions are checked later). * SMP-safe */ -int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) +int open_namei(int dfd, const char *pathname, int flag, + int mode, struct nameidata *nd) { int acc_mode, error; struct path path; @@ -1540,7 +1592,8 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) * The simplest case - just a plain lookup. */ if (!(flag & O_CREAT)) { - error = path_lookup_open(pathname, lookup_flags(flag), nd, flag); + error = path_lookup_open(dfd, pathname, lookup_flags(flag), + nd, flag); if (error) return error; goto ok; @@ -1549,7 +1602,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) /* * Create - we need to know the parent. */ - error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode); + error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); if (error) return error; @@ -1744,7 +1797,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) return error; } -asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) +asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, + unsigned dev) { int error = 0; char * tmp; @@ -1757,7 +1811,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) if (IS_ERR(tmp)) return PTR_ERR(tmp); - error = path_lookup(tmp, LOOKUP_PARENT, &nd); + error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); if (error) goto out; dentry = lookup_create(&nd, 0); @@ -1793,6 +1847,11 @@ out: return error; } +asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev) +{ + return sys_mknodat(AT_FDCWD, filename, mode, dev); +} + int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int error = may_create(dir, dentry, NULL); @@ -1815,7 +1874,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) return error; } -asmlinkage long sys_mkdir(const char __user * pathname, int mode) +asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) { int error = 0; char * tmp; @@ -1826,7 +1885,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode) struct dentry *dentry; struct nameidata nd; - error = path_lookup(tmp, LOOKUP_PARENT, &nd); + error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); if (error) goto out; dentry = lookup_create(&nd, 1); @@ -1846,6 +1905,11 @@ out: return error; } +asmlinkage long sys_mkdir(const char __user *pathname, int mode) +{ + return sys_mkdirat(AT_FDCWD, pathname, mode); +} + /* * We try to drop the dentry early: we should have * a usage count of 2 if we're the only user of this @@ -1907,7 +1971,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) return error; } -asmlinkage long sys_rmdir(const char __user * pathname) +static long do_rmdir(int dfd, const char __user *pathname) { int error = 0; char * name; @@ -1918,7 +1982,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) if(IS_ERR(name)) return PTR_ERR(name); - error = path_lookup(name, LOOKUP_PARENT, &nd); + error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); if (error) goto exit; @@ -1948,6 +2012,11 @@ exit: return error; } +asmlinkage long sys_rmdir(const char __user *pathname) +{ + return do_rmdir(AT_FDCWD, pathname); +} + int vfs_unlink(struct inode *dir, struct dentry *dentry) { int error = may_delete(dir, dentry, 0); @@ -1984,7 +2053,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) * writeout happening, and we don't want to prevent access to the directory * while waiting on the I/O. */ -asmlinkage long sys_unlink(const char __user * pathname) +static long do_unlinkat(int dfd, const char __user *pathname) { int error = 0; char * name; @@ -1996,7 +2065,7 @@ asmlinkage long sys_unlink(const char __user * pathname) if(IS_ERR(name)) return PTR_ERR(name); - error = path_lookup(name, LOOKUP_PARENT, &nd); + error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); if (error) goto exit; error = -EISDIR; @@ -2031,6 +2100,22 @@ slashes: goto exit2; } +asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag) +{ + if ((flag & ~AT_REMOVEDIR) != 0) + return -EINVAL; + + if (flag & AT_REMOVEDIR) + return do_rmdir(dfd, pathname); + + return do_unlinkat(dfd, pathname); +} + +asmlinkage long sys_unlink(const char __user *pathname) +{ + return do_unlinkat(AT_FDCWD, pathname); +} + int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) { int error = may_create(dir, dentry, NULL); @@ -2052,7 +2137,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i return error; } -asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname) +asmlinkage long sys_symlinkat(const char __user *oldname, + int newdfd, const char __user *newname) { int error = 0; char * from; @@ -2067,7 +2153,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new struct dentry *dentry; struct nameidata nd; - error = path_lookup(to, LOOKUP_PARENT, &nd); + error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); if (error) goto out; dentry = lookup_create(&nd, 0); @@ -2085,6 +2171,11 @@ out: return error; } +asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname) +{ + return sys_symlinkat(oldname, AT_FDCWD, newname); +} + int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { struct inode *inode = old_dentry->d_inode; @@ -2132,7 +2223,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de * with linux 2.0, and to avoid hard-linking to directories * and other special files. --ADM */ -asmlinkage long sys_link(const char __user * oldname, const char __user * newname) +asmlinkage long sys_linkat(int olddfd, const char __user *oldname, + int newdfd, const char __user *newname) { struct dentry *new_dentry; struct nameidata nd, old_nd; @@ -2143,10 +2235,10 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam if (IS_ERR(to)) return PTR_ERR(to); - error = __user_walk(oldname, 0, &old_nd); + error = __user_walk_fd(olddfd, oldname, 0, &old_nd); if (error) goto exit; - error = path_lookup(to, LOOKUP_PARENT, &nd); + error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); if (error) goto out; error = -EXDEV; @@ -2169,6 +2261,11 @@ exit: return error; } +asmlinkage long sys_link(const char __user *oldname, const char __user *newname) +{ + return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname); +} + /* * The worst of all namespace operations - renaming directory. "Perverted" * doesn't even start to describe it. Somebody in UCB had a heck of a trip... @@ -2315,7 +2412,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, return error; } -static int do_rename(const char * oldname, const char * newname) +static int do_rename(int olddfd, const char *oldname, + int newdfd, const char *newname) { int error = 0; struct dentry * old_dir, * new_dir; @@ -2323,11 +2421,11 @@ static int do_rename(const char * oldname, const char * newname) struct dentry * trap; struct nameidata oldnd, newnd; - error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); + error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd); if (error) goto exit; - error = path_lookup(newname, LOOKUP_PARENT, &newnd); + error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd); if (error) goto exit1; @@ -2391,7 +2489,8 @@ exit: return error; } -asmlinkage long sys_rename(const char __user * oldname, const char __user * newname) +asmlinkage long sys_renameat(int olddfd, const char __user *oldname, + int newdfd, const char __user *newname) { int error; char * from; @@ -2403,13 +2502,18 @@ asmlinkage long sys_rename(const char __user * oldname, const char __user * newn to = getname(newname); error = PTR_ERR(to); if (!IS_ERR(to)) { - error = do_rename(from,to); + error = do_rename(olddfd, from, newdfd, to); putname(to); } putname(from); return error; } +asmlinkage long sys_rename(const char __user *oldname, const char __user *newname) +{ + return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); +} + int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) { int len; @@ -2553,6 +2657,7 @@ struct inode_operations page_symlink_inode_operations = { }; EXPORT_SYMBOL(__user_walk); +EXPORT_SYMBOL(__user_walk_fd); EXPORT_SYMBOL(follow_down); EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ diff --git a/fs/namespace.c b/fs/namespace.c index ce97becff461..058a44865beb 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -494,7 +494,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) p->mnt_namespace = NULL; list_del_init(&p->mnt_child); if (p->mnt_parent != p) - mnt->mnt_mountpoint->d_mounted--; + p->mnt_mountpoint->d_mounted--; change_mnt_propagation(p, MS_PRIVATE); } } @@ -1325,27 +1325,17 @@ dput_out: return retval; } -int copy_namespace(int flags, struct task_struct *tsk) +/* + * Allocate a new namespace structure and populate it with contents + * copied from the namespace of the passed in task structure. + */ +struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) { struct namespace *namespace = tsk->namespace; struct namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; - struct fs_struct *fs = tsk->fs; struct vfsmount *p, *q; - if (!namespace) - return 0; - - get_namespace(namespace); - - if (!(flags & CLONE_NEWNS)) - return 0; - - if (!capable(CAP_SYS_ADMIN)) { - put_namespace(namespace); - return -EPERM; - } - new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL); if (!new_ns) goto out; @@ -1396,8 +1386,6 @@ int copy_namespace(int flags, struct task_struct *tsk) } up_write(&namespace_sem); - tsk->namespace = new_ns; - if (rootmnt) mntput(rootmnt); if (pwdmnt) @@ -1405,12 +1393,40 @@ int copy_namespace(int flags, struct task_struct *tsk) if (altrootmnt) mntput(altrootmnt); - put_namespace(namespace); - return 0; +out: + return new_ns; +} + +int copy_namespace(int flags, struct task_struct *tsk) +{ + struct namespace *namespace = tsk->namespace; + struct namespace *new_ns; + int err = 0; + + if (!namespace) + return 0; + + get_namespace(namespace); + + if (!(flags & CLONE_NEWNS)) + return 0; + + if (!capable(CAP_SYS_ADMIN)) { + err = -EPERM; + goto out; + } + + new_ns = dup_namespace(tsk, tsk->fs); + if (!new_ns) { + err = -ENOMEM; + goto out; + } + + tsk->namespace = new_ns; out: put_namespace(namespace); - return -ENOMEM; + return err; } asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name, diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 10ae377e68ff..04ab2fc360e7 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -481,7 +481,7 @@ retry: if (wdata->verf.committed != NFS_FILE_SYNC) { need_commit = 1; if (memcmp(&first_verf.verifier, &wdata->verf.verifier, - sizeof(first_verf.verifier))); + sizeof(first_verf.verifier))) goto sync_retry; } diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index e897e00c2c9d..c0a754ecdee6 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -465,10 +465,11 @@ static int __init root_nfs_ports(void) "number from server, using default\n"); port = nfsd_port; } - nfs_port = htons(port); + nfs_port = port; dprintk("Root-NFS: Portmapper on server returned %d " "as nfsd port\n", port); } + nfs_port = htons(nfs_port); if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) { printk(KERN_ERR "Root-NFS: Unable to get mountd port " diff --git a/fs/nfsctl.c b/fs/nfsctl.c index 0b14938b5b62..0d4cf9486068 100644 --- a/fs/nfsctl.c +++ b/fs/nfsctl.c @@ -5,6 +5,7 @@ * */ #include <linux/config.h> +#include <linux/types.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/sunrpc/svc.h> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 361b4007d4a0..6d63f1d9e5f5 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -192,6 +192,16 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open } if (status) goto out; + + /* Openowner is now set, so sequence id will get bumped. Now we need + * these checks before we do any creates: */ + status = nfserr_grace; + if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) + goto out; + status = nfserr_no_grace; + if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) + goto out; + switch (open->op_claim_type) { case NFS4_OPEN_CLAIM_DELEGATE_CUR: status = nfserr_inval; @@ -210,6 +220,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open goto out; break; case NFS4_OPEN_CLAIM_PREVIOUS: + open->op_stateowner->so_confirmed = 1; /* * The CURRENT_FH is already set to the file being * opened. (1) set open->op_cinfo, (2) set @@ -221,6 +232,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open goto out; break; case NFS4_OPEN_CLAIM_DELEGATE_PREV: + open->op_stateowner->so_confirmed = 1; printk("NFSD: unsupported OPEN claim type %d\n", open->op_claim_type); status = nfserr_notsupp; @@ -584,31 +596,23 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se { int status = nfs_ok; - if (!current_fh->fh_dentry) - return nfserr_nofilehandle; - - status = nfs_ok; if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { nfs4_lock_state(); - if ((status = nfs4_preprocess_stateid_op(current_fh, - &setattr->sa_stateid, - CHECK_FH | WR_STATE, NULL))) { - dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); - goto out_unlock; - } + status = nfs4_preprocess_stateid_op(current_fh, + &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); nfs4_unlock_state(); + if (status) { + dprintk("NFSD: nfsd4_setattr: couldn't process stateid!"); + return status; + } } status = nfs_ok; if (setattr->sa_acl != NULL) status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); if (status) - goto out; + return status; status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0); -out: - return status; -out_unlock: - nfs4_unlock_state(); return status; } @@ -626,15 +630,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ return nfserr_inval; nfs4_lock_state(); - if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, - CHECK_FH | WR_STATE, &filp))) { - dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); - goto out; - } + status = nfs4_preprocess_stateid_op(current_fh, stateid, + CHECK_FH | WR_STATE, &filp); if (filp) get_file(filp); nfs4_unlock_state(); + if (status) { + dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); + return status; + } + write->wr_bytes_written = write->wr_buflen; write->wr_how_written = write->wr_stable_how; p = (u32 *)write->wr_verifier.data; @@ -650,9 +656,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ if (status == nfserr_symlink) status = nfserr_inval; return status; -out: - nfs4_unlock_state(); - return status; } /* This routine never returns NFS_OK! If there are no other errors, it @@ -768,6 +771,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, while (!status && resp->opcnt < args->opcnt) { op = &args->ops[resp->opcnt++]; + dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum); + /* * The XDR decode routines may have pre-set op->status; * for example, if there is a miscellaneous XDR error @@ -792,17 +797,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, /* All operations except RENEW, SETCLIENTID, RESTOREFH * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH * require a valid current filehandle - * - * SETATTR NOFILEHANDLE error handled in nfsd4_setattr - * due to required returned bitmap argument */ if ((!current_fh->fh_dentry) && !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || (op->opnum == OP_SETCLIENTID) || (op->opnum == OP_SETCLIENTID_CONFIRM) || (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || - (op->opnum == OP_RELEASE_LOCKOWNER) || - (op->opnum == OP_SETATTR))) { + (op->opnum == OP_RELEASE_LOCKOWNER))) { op->status = nfserr_nofilehandle; goto encode_op; } diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index be963a133aaa..06da7506363c 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) nfs4_save_user(&uid, &gid); - filp = dentry_open(dget(dir), mntget(rec_dir.mnt), - O_RDWR); + filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY); status = PTR_ERR(filp); if (IS_ERR(filp)) goto out; @@ -400,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname) nfs4_save_user(&uid, &gid); - status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir); - if (status == -ENOENT) - printk("NFSD: recovery directory %s doesn't exist\n", + status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, + &rec_dir); + if (status) + printk("NFSD: unable to find recovery directory %s\n", rec_dirname); if (!status) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6bbefd06f10d..1143cfb64549 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1088,7 +1088,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str sop->so_seqid = open->op_seqid; sop->so_confirmed = 0; rp = &sop->so_replay; - rp->rp_status = NFSERR_SERVERFAULT; + rp->rp_status = nfserr_serverfault; rp->rp_buflen = 0; rp->rp_buf = rp->rp_ibuf; return sop; @@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags) locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); put_nfs4_file(stp->st_file); kmem_cache_free(stateid_slab, stp); - stp = NULL; } static void @@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop) sop->so_time = get_seconds(); } -static void -release_state_owner(struct nfs4_stateid *stp, int flag) -{ - struct nfs4_stateowner *sop = stp->st_stateowner; - - dprintk("NFSD: release_state_owner\n"); - release_stateid(stp, flag); - - /* place unused nfs4_stateowners on so_close_lru list to be - * released by the laundromat service after the lease period - * to enable us to handle CLOSE replay - */ - if (sop->so_confirmed && list_empty(&sop->so_stateids)) - move_to_close_lru(sop); -} - static int cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { return ((sop->so_owner.len == owner->len) && @@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = { }; -/* - * nfsd4_process_open1() - * lookup stateowner. - * found: - * check confirmed - * confirmed: - * check seqid - * not confirmed: - * delete owner - * create new owner - * notfound: - * verify clientid - * create new owner - * - * called with nfs4_lock_state() held. - */ int nfsd4_process_open1(struct nfsd4_open *open) { - int status; clientid_t *clientid = &open->op_clientid; struct nfs4_client *clp = NULL; unsigned int strhashval; struct nfs4_stateowner *sop = NULL; - status = nfserr_inval; if (!check_name(open->op_owner)) - goto out; + return nfserr_inval; if (STALE_CLIENTID(&open->op_clientid)) return nfserr_stale_clientid; strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); sop = find_openstateowner_str(strhashval, open); - if (sop) { - open->op_stateowner = sop; - /* check for replay */ - if (open->op_seqid == sop->so_seqid - 1){ - if (sop->so_replay.rp_buflen) - return NFSERR_REPLAY_ME; - else { - /* The original OPEN failed so spectacularly - * that we don't even have replay data saved! - * Therefore, we have no choice but to continue - * processing this OPEN; presumably, we'll - * fail again for the same reason. - */ - dprintk("nfsd4_process_open1:" - " replay with no replay cache\n"); - goto renew; - } - } else if (sop->so_confirmed) { - if (open->op_seqid == sop->so_seqid) - goto renew; - status = nfserr_bad_seqid; - goto out; - } else { - /* If we get here, we received an OPEN for an - * unconfirmed nfs4_stateowner. Since the seqid's are - * different, purge the existing nfs4_stateowner, and - * instantiate a new one. - */ - clp = sop->so_client; - release_stateowner(sop); - } - } else { - /* nfs4_stateowner not found. - * Verify clientid and instantiate new nfs4_stateowner. - * If verify fails this is presumably the result of the - * client's lease expiring. - */ - status = nfserr_expired; + open->op_stateowner = sop; + if (!sop) { + /* Make sure the client's lease hasn't expired. */ clp = find_confirmed_client(clientid); if (clp == NULL) - goto out; + return nfserr_expired; + goto renew; } - status = nfserr_resource; - sop = alloc_init_open_stateowner(strhashval, clp, open); - if (sop == NULL) - goto out; - open->op_stateowner = sop; + if (!sop->so_confirmed) { + /* Replace unconfirmed owners without checking for replay. */ + clp = sop->so_client; + release_stateowner(sop); + open->op_stateowner = NULL; + goto renew; + } + if (open->op_seqid == sop->so_seqid - 1) { + if (sop->so_replay.rp_buflen) + return NFSERR_REPLAY_ME; + /* The original OPEN failed so spectacularly + * that we don't even have replay data saved! + * Therefore, we have no choice but to continue + * processing this OPEN; presumably, we'll + * fail again for the same reason. + */ + dprintk("nfsd4_process_open1: replay with no replay cache\n"); + goto renew; + } + if (open->op_seqid != sop->so_seqid) + return nfserr_bad_seqid; renew: - status = nfs_ok; + if (open->op_stateowner == NULL) { + sop = alloc_init_open_stateowner(strhashval, clp, open); + if (sop == NULL) + return nfserr_resource; + open->op_stateowner = sop; + } + list_del_init(&sop->so_close_lru); renew_client(sop->so_client); -out: - return status; + return nfs_ok; } static inline int @@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, if (!open->op_truncate) return 0; if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) - return -EINVAL; + return nfserr_inval; return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); } @@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta { struct file *filp = stp->st_vfs_file; struct inode *inode = filp->f_dentry->d_inode; - unsigned int share_access; + unsigned int share_access, new_writer; int status; set_access(&share_access, stp->st_access_bmap); - share_access = ~share_access; - share_access &= open->op_share_access; - - if (!(share_access & NFS4_SHARE_ACCESS_WRITE)) - return nfsd4_truncate(rqstp, cur_fh, open); + new_writer = (~share_access) & open->op_share_access + & NFS4_SHARE_ACCESS_WRITE; - status = get_write_access(inode); - if (status) - return nfserrno(status); + if (new_writer) { + status = get_write_access(inode); + if (status) + return nfserrno(status); + } status = nfsd4_truncate(rqstp, cur_fh, open); if (status) { - put_write_access(inode); + if (new_writer) + put_write_access(inode); return status; } /* remember the open */ - filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; + filp->f_mode |= open->op_share_access; set_bit(open->op_share_access, &stp->st_access_bmap); set_bit(open->op_share_deny, &stp->st_deny_bmap); @@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf struct nfs4_delegation *dp = NULL; int status; - if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) - return nfserr_grace; - - if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) - return nfserr_no_grace; - status = nfserr_inval; if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) goto out; @@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos CHECK_FH | OPEN_STATE | CLOSE_STATE, &close->cl_stateowner, &stp, NULL))) goto out; - /* - * Return success, but first update the stateid. - */ status = nfs_ok; update_stateid(&stp->st_stateid); memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t)); - /* release_state_owner() calls nfsd_close() if needed */ - release_state_owner(stp, OPEN_STATE); + /* release_stateid() calls nfsd_close() if needed */ + release_stateid(stp, OPEN_STATE); + + /* place unused nfs4_stateowners on so_close_lru list to be + * released by the laundromat service after the lease period + * to enable us to handle CLOSE replay + */ + if (list_empty(&close->cl_stateowner->so_stateids)) + move_to_close_lru(close->cl_stateowner); out: if (close->cl_stateowner) { nfs4_get_stateowner(close->cl_stateowner); @@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str sop->so_seqid = lock->lk_new_lock_seqid + 1; sop->so_confirmed = 1; rp = &sop->so_replay; - rp->rp_status = NFSERR_SERVERFAULT; + rp->rp_status = nfserr_serverfault; rp->rp_buflen = 0; rp->rp_buf = rp->rp_ibuf; return sop; @@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock if (check_lock_length(lock->lk_offset, lock->lk_length)) return nfserr_inval; + if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { + dprintk("NFSD: nfsd4_lock: permission denied!\n"); + return status; + } + nfs4_lock_state(); if (lock->lk_is_new) { @@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock lock->lk_new_open_seqid, &lock->lk_new_open_stateid, CHECK_FH | OPEN_STATE, - &lock->lk_stateowner, &open_stp, + &lock->lk_replay_owner, &open_stp, lock); if (status) goto out; - open_sop = lock->lk_stateowner; + open_sop = lock->lk_replay_owner; /* create lockowner and lock stateid */ fp = open_stp->st_file; strhashval = lock_ownerstr_hashval(fp->fi_inode, @@ -2739,29 +2694,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock if (lock_sop == NULL) goto out; lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); - if (lock_stp == NULL) { - release_stateowner(lock_sop); + if (lock_stp == NULL) goto out; - } } else { /* lock (lock owner + lock stateid) already exists */ status = nfs4_preprocess_seqid_op(current_fh, lock->lk_old_lock_seqid, &lock->lk_old_lock_stateid, CHECK_FH | LOCK_STATE, - &lock->lk_stateowner, &lock_stp, lock); + &lock->lk_replay_owner, &lock_stp, lock); if (status) goto out; - lock_sop = lock->lk_stateowner; + lock_sop = lock->lk_replay_owner; } - /* lock->lk_stateowner and lock_stp have been created or found */ + /* lock->lk_replay_owner and lock_stp have been created or found */ filp = lock_stp->st_vfs_file; - if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { - dprintk("NFSD: nfsd4_lock: permission denied!\n"); - goto out; - } - status = nfserr_grace; if (nfs4_in_grace() && !lock->lk_reclaim) goto out; @@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock */ status = posix_lock_file(filp, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); switch (-status) { case 0: /* success! */ @@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock goto conflicting_lock; case (EDEADLK): status = nfserr_deadlock; + dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); + goto out; default: + status = nfserrno(status); dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); - goto out_destroy_new_stateid; + goto out; } conflicting_lock: @@ -2831,20 +2780,12 @@ conflicting_lock: goto out; } nfs4_set_lock_denied(conflock, &lock->lk_denied); - -out_destroy_new_stateid: - if (lock->lk_is_new) { - dprintk("NFSD: nfsd4_lock: destroy new stateid!\n"); - /* - * An error encountered after instantiation of the new - * stateid has forced us to destroy it. - */ - release_state_owner(lock_stp, LOCK_STATE); - } out: - if (lock->lk_stateowner) { - nfs4_get_stateowner(lock->lk_stateowner); - *replay_owner = lock->lk_stateowner; + if (status && lock->lk_is_new && lock_sop) + release_stateowner(lock_sop); + if (lock->lk_replay_owner) { + nfs4_get_stateowner(lock->lk_replay_owner); + *replay_owner = lock->lk_replay_owner; } nfs4_unlock_state(); return status; @@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock * Try to unlock the file in the VFS. */ status = posix_lock_file(filp, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); if (status) { dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); goto out_nfserr; @@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) lock_kernel(); for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { - if ((*flpp)->fl_owner == (fl_owner_t)lowner) + if ((*flpp)->fl_owner == (fl_owner_t)lowner) { status = 1; goto out; + } } out: unlock_kernel(); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index dcd673186944..69d3501173a8 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -528,7 +528,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) { DECODE_HEAD; - lock->lk_stateowner = NULL; + lock->lk_replay_owner = NULL; /* * type, reclaim(boolean), offset, length, new_lock_owner(boolean) */ @@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen, */ if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) goto fail; - nfserr = nfserr_toosmall; p = nfsd4_encode_rdattr_error(p, buflen, nfserr); - if (p == NULL) + if (p == NULL) { + nfserr = nfserr_toosmall; goto fail; + } } cd->buflen -= (p - cd->buffer); cd->buffer = p; @@ -1895,7 +1896,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie static void nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock) { - ENCODE_SEQID_OP_HEAD; if (!nfserr) { @@ -1906,7 +1906,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock } else if (nfserr == nfserr_denied) nfsd4_encode_lock_denied(resp, &lock->lk_denied); - ENCODE_SEQID_OP_TAIL(lock->lk_stateowner); + ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner); } static void diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 0aa1b9603d7f..3e6b75cd90fd 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -36,6 +36,22 @@ nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) return nfs_ok; } +static int +nfsd_return_attrs(int err, struct nfsd_attrstat *resp) +{ + if (err) return err; + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + resp->fh.fh_dentry, + &resp->stat)); +} +static int +nfsd_return_dirop(int err, struct nfsd_diropres *resp) +{ + if (err) return err; + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + resp->fh.fh_dentry, + &resp->stat)); +} /* * Get a file's attributes * N.B. After this call resp->fh needs an fh_put @@ -44,10 +60,12 @@ static int nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) { + int nfserr; dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); - return fh_verify(rqstp, &resp->fh, 0, MAY_NOP); + nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); + return nfsd_return_attrs(nfserr, resp); } /* @@ -58,12 +76,14 @@ static int nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, struct nfsd_attrstat *resp) { + int nfserr; dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", SVCFH_fmt(&argp->fh), argp->attrs.ia_valid, (long) argp->attrs.ia_size); fh_copy(&resp->fh, &argp->fh); - return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); + nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); + return nfsd_return_attrs(nfserr, resp); } /* @@ -86,7 +106,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, &resp->fh); fh_put(&argp->fh); - return nfserr; + return nfsd_return_dirop(nfserr, resp); } /* @@ -142,7 +162,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, argp->vec, argp->vlen, &resp->count); - return nfserr; + if (nfserr) return nfserr; + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + resp->fh.fh_dentry, + &resp->stat)); } /* @@ -165,7 +188,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp, argp->vec, argp->vlen, argp->len, &stable); - return nfserr; + return nfsd_return_attrs(nfserr, resp); } /* @@ -322,7 +345,7 @@ out_unlock: done: fh_put(dirfhp); - return nfserr; + return nfsd_return_dirop(nfserr, resp); } static int @@ -425,7 +448,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, &argp->attrs, S_IFDIR, 0, &resp->fh); fh_put(&argp->fh); - return nfserr; + return nfsd_return_dirop(nfserr, resp); } /* diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 89ed04696865..1d163b616915 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -64,6 +64,32 @@ struct nfsd_list { }; static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); +#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) +static struct svc_stat nfsd_acl_svcstats; +static struct svc_version * nfsd_acl_version[] = { + [2] = &nfsd_acl_version2, + [3] = &nfsd_acl_version3, +}; + +#define NFSD_ACL_MINVERS 2 +#define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0])) +static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS]; + +static struct svc_program nfsd_acl_program = { + .pg_prog = NFS_ACL_PROGRAM, + .pg_nvers = NFSD_ACL_NRVERS, + .pg_vers = nfsd_acl_versions, + .pg_name = "nfsd", + .pg_class = "nfsd", + .pg_stats = &nfsd_acl_svcstats, + .pg_authenticate = &svc_set_client, +}; + +static struct svc_stat nfsd_acl_svcstats = { + .program = &nfsd_acl_program, +}; +#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ + static struct svc_version * nfsd_version[] = { [2] = &nfsd_version2, #if defined(CONFIG_NFSD_V3) @@ -79,6 +105,9 @@ static struct svc_version * nfsd_version[] = { static struct svc_version *nfsd_versions[NFSD_NRVERS]; struct svc_program nfsd_program = { +#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) + .pg_next = &nfsd_acl_program, +#endif .pg_prog = NFS_PROGRAM, /* program number */ .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ .pg_vers = nfsd_versions, /* version table */ @@ -147,6 +176,26 @@ nfsd_svc(unsigned short port, int nrservs) nfsd_program.pg_vers[i] = nfsd_version[i]; } + +#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) + found_one = 0; + + for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) { + if (NFSCTL_VERISSET(nfsd_versbits, i)) { + nfsd_acl_program.pg_vers[i] = + nfsd_acl_version[i]; + found_one = 1; + } else + nfsd_acl_program.pg_vers[i] = NULL; + } + + if (!found_one) { + for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) + nfsd_acl_program.pg_vers[i] = + nfsd_acl_version[i]; + } +#endif + atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); @@ -411,30 +460,3 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1); return 1; } - -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -static struct svc_stat nfsd_acl_svcstats; -static struct svc_version * nfsd_acl_version[] = { - [2] = &nfsd_acl_version2, - [3] = &nfsd_acl_version3, -}; - -#define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0])) -static struct svc_program nfsd_acl_program = { - .pg_prog = NFS_ACL_PROGRAM, - .pg_nvers = NFSD_ACL_NRVERS, - .pg_vers = nfsd_acl_version, - .pg_name = "nfsd", - .pg_class = "nfsd", - .pg_stats = &nfsd_acl_svcstats, - .pg_authenticate = &svc_set_client, -}; - -static struct svc_stat nfsd_acl_svcstats = { - .program = &nfsd_acl_program, -}; - -#define nfsd_acl_program_p &nfsd_acl_program -#else -#define nfsd_acl_program_p NULL -#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index eef0576a7785..5320e5afaddb 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -710,14 +710,15 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp, { struct inode *inode = dp->d_inode; int (*fsync) (struct file *, struct dentry *, int); - int err = nfs_ok; + int err; - filemap_fdatawrite(inode->i_mapping); - if (fop && (fsync = fop->fsync)) - err=fsync(filp, dp, 0); - filemap_fdatawait(inode->i_mapping); + err = filemap_fdatawrite(inode->i_mapping); + if (err == 0 && fop && (fsync = fop->fsync)) + err = fsync(filp, dp, 0); + if (err == 0) + err = filemap_fdatawait(inode->i_mapping); - return nfserrno(err); + return err; } @@ -734,10 +735,10 @@ nfsd_sync(struct file *filp) return err; } -void +int nfsd_sync_dir(struct dentry *dp) { - nfsd_dosync(NULL, dp, dp->d_inode->i_fop); + return nfsd_dosync(NULL, dp, dp->d_inode->i_fop); } /* @@ -814,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset return size; } -static inline int +static int nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long *count) { @@ -878,7 +879,7 @@ static void kill_suid(struct dentry *dentry) mutex_unlock(&dentry->d_inode->i_mutex); } -static inline int +static int nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, unsigned long cnt, int *stablep) @@ -890,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, int err = 0; int stable = *stablep; +#ifdef MSNFS err = nfserr_perm; -#ifdef MSNFS if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) goto out; @@ -1064,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, return err; if (EX_ISSYNC(fhp->fh_export)) { if (file->f_op && file->f_op->fsync) { - err = nfsd_sync(file); + err = nfserrno(nfsd_sync(file)); } else { err = nfserr_notsupp; } @@ -1132,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, "nfsd_create: parent %s/%s not locked!\n", dentry->d_parent->d_name.name, dentry->d_name.name); - err = -EIO; + err = nfserr_io; goto out; } } @@ -1175,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) { - nfsd_sync_dir(dentry); + err = nfserrno(nfsd_sync_dir(dentry)); write_inode_now(dchild->d_inode, 1); } @@ -1185,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, * send along the gid when it tries to implement setgid * directories via NFS. */ - err = 0; - if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) - err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { + int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + if (err2) + err = err2; + } /* * Update the file handle to get the new inode info. */ @@ -1306,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) { - nfsd_sync_dir(dentry); + err = nfserrno(nfsd_sync_dir(dentry)); /* setattr will sync the child (or not) */ } - /* - * Update the filehandle to get the new inode info. - */ - err = fh_update(resfhp); - if (err) - goto out; - if (createmode == NFS3_CREATE_EXCLUSIVE) { /* Cram the verifier into atime/mtime/mode */ iap->ia_valid = ATTR_MTIME|ATTR_ATIME @@ -1337,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, * implement setgid directories via NFS. Clear out all that cruft. */ set_attr: - if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) - err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { + int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + if (err2) + err = err2; + } + + /* + * Update the filehandle to get the new inode info. + */ + if (!err) + err = fh_update(resfhp); out: fh_unlock(fhp); @@ -1447,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, } else err = vfs_symlink(dentry->d_inode, dnew, path, mode); - if (!err) { + if (!err) if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); - } else + err = nfsd_sync_dir(dentry); + if (err) err = nfserrno(err); fh_unlock(fhp); @@ -1506,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, err = vfs_link(dold, dirp, dnew); if (!err) { if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); + err = nfserrno(nfsd_sync_dir(ddir)); write_inode_now(dest, 1); } } else { @@ -1590,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && ((atomic_read(&odentry->d_count) > 1) || (atomic_read(&ndentry->d_count) > 1))) { - err = nfserr_perm; + err = -EPERM; } else #endif err = vfs_rename(fdir, odentry, tdir, ndentry); if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); + err = nfsd_sync_dir(tdentry); + if (!err) + err = nfsd_sync_dir(fdentry); } out_dput_new: @@ -1661,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, #ifdef MSNFS if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && (atomic_read(&rdentry->d_count) > 1)) { - err = nfserr_perm; + err = -EPERM; } else #endif err = vfs_unlink(dirp, rdentry); @@ -1671,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, dput(rdentry); - if (err) - goto out_nfserr; - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); - -out: - return err; + if (err == 0 && + EX_ISSYNC(fhp->fh_export)) + err = nfsd_sync_dir(dentry); out_nfserr: err = nfserrno(err); - goto out; +out: + return err; } /* diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index d424041b38e9..bae3d7548bea 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -58,7 +58,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, goto out; } - down(&OCFS2_I(inode)->ip_io_sem); + mutex_lock(&OCFS2_I(inode)->ip_io_mutex); lock_buffer(bh); set_buffer_uptodate(bh); @@ -82,7 +82,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, brelse(bh); } - up(&OCFS2_I(inode)->ip_io_sem); + mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); out: mlog_exit(ret); return ret; @@ -125,13 +125,13 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, flags &= ~OCFS2_BH_CACHED; if (inode) - down(&OCFS2_I(inode)->ip_io_sem); + mutex_lock(&OCFS2_I(inode)->ip_io_mutex); for (i = 0 ; i < nr ; i++) { if (bhs[i] == NULL) { bhs[i] = sb_getblk(sb, block++); if (bhs[i] == NULL) { if (inode) - up(&OCFS2_I(inode)->ip_io_sem); + mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); status = -EIO; mlog_errno(status); goto bail; @@ -220,7 +220,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, ocfs2_set_buffer_uptodate(inode, bh); } if (inode) - up(&OCFS2_I(inode)->ip_io_sem); + mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); mlog(ML_BH_IO, "block=(%"MLFu64"), nr=(%d), cached=%s\n", block, nr, (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes"); diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 7307ba528913..d08971d29b63 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -917,8 +917,9 @@ static int o2hb_thread(void *data) elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); mlog(0, "start = %lu.%lu, end = %lu.%lu, msec = %u\n", - before_hb.tv_sec, before_hb.tv_usec, - after_hb.tv_sec, after_hb.tv_usec, elapsed_msec); + before_hb.tv_sec, (unsigned long) before_hb.tv_usec, + after_hb.tv_sec, (unsigned long) after_hb.tv_usec, + elapsed_msec); if (elapsed_msec < reg->hr_timeout_ms) { /* the kthread api has blocked signals for us so no diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 35d92c01a972..d22d4cf08db1 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -1285,14 +1285,16 @@ static void o2net_idle_timer(unsigned long data) mlog(ML_NOTICE, "here are some times that might help debug the " "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv " "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n", - sc->sc_tv_timer.tv_sec, sc->sc_tv_timer.tv_usec, - now.tv_sec, now.tv_usec, - sc->sc_tv_data_ready.tv_sec, sc->sc_tv_data_ready.tv_usec, - sc->sc_tv_advance_start.tv_sec, sc->sc_tv_advance_start.tv_usec, - sc->sc_tv_advance_stop.tv_sec, sc->sc_tv_advance_stop.tv_usec, + sc->sc_tv_timer.tv_sec, (long) sc->sc_tv_timer.tv_usec, + now.tv_sec, (long) now.tv_usec, + sc->sc_tv_data_ready.tv_sec, (long) sc->sc_tv_data_ready.tv_usec, + sc->sc_tv_advance_start.tv_sec, + (long) sc->sc_tv_advance_start.tv_usec, + sc->sc_tv_advance_stop.tv_sec, + (long) sc->sc_tv_advance_stop.tv_usec, sc->sc_msg_key, sc->sc_msg_type, - sc->sc_tv_func_start.tv_sec, sc->sc_tv_func_start.tv_usec, - sc->sc_tv_func_stop.tv_sec, sc->sc_tv_func_stop.tv_usec); + sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec, + sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec); o2net_sc_queue_work(sc, &sc->sc_shutdown_work); } diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 3fecba0a6023..42eb53b5293b 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -657,6 +657,7 @@ void dlm_complete_thread(struct dlm_ctxt *dlm); int dlm_launch_recovery_thread(struct dlm_ctxt *dlm); void dlm_complete_recovery_thread(struct dlm_ctxt *dlm); void dlm_wait_for_recovery(struct dlm_ctxt *dlm); +int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node); void dlm_put(struct dlm_ctxt *dlm); struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm); diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index da3c22045f89..6ee30837389c 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -573,8 +573,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data) spin_lock(&dlm_domain_lock); dlm = __dlm_lookup_domain_full(query->domain, query->name_len); /* Once the dlm ctxt is marked as leaving then we don't want - * to be put in someone's domain map. */ + * to be put in someone's domain map. + * Also, explicitly disallow joining at certain troublesome + * times (ie. during recovery). */ if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) { + int bit = query->node_idx; spin_lock(&dlm->spinlock); if (dlm->dlm_state == DLM_CTXT_NEW && @@ -586,6 +589,19 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data) } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { /* Disallow parallel joins. */ response = JOIN_DISALLOW; + } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { + mlog(ML_NOTICE, "node %u trying to join, but recovery " + "is ongoing.\n", bit); + response = JOIN_DISALLOW; + } else if (test_bit(bit, dlm->recovery_map)) { + mlog(ML_NOTICE, "node %u trying to join, but it " + "still needs recovery.\n", bit); + response = JOIN_DISALLOW; + } else if (test_bit(bit, dlm->domain_map)) { + mlog(ML_NOTICE, "node %u trying to join, but it " + "is still in the domain! needs recovery?\n", + bit); + response = JOIN_DISALLOW; } else { /* Alright we're fully a part of this domain * so we keep some state as to who's joining diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 27e984f7e4cd..a3194fe173d9 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -1050,17 +1050,10 @@ static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm, node = dlm_bitmap_diff_iter_next(&bdi, &sc); while (node >= 0) { if (sc == NODE_UP) { - /* a node came up. easy. might not even need - * to talk to it if its node number is higher - * or if we are already blocked. */ - mlog(0, "node up! %d\n", node); - if (blocked) - goto next; - - if (node > dlm->node_num) { - mlog(0, "node > this node. skipping.\n"); - goto next; - } + /* a node came up. clear any old vote from + * the response map and set it in the vote map + * then restart the mastery. */ + mlog(ML_NOTICE, "node %d up while restarting\n", node); /* redo the master request, but only for the new node */ mlog(0, "sending request to new node\n"); @@ -2005,6 +1998,15 @@ fail: break; mlog(0, "timed out during migration\n"); + /* avoid hang during shutdown when migrating lockres + * to a node which also goes down */ + if (dlm_is_node_dead(dlm, target)) { + mlog(0, "%s:%.*s: expected migration target %u " + "is no longer up. restarting.\n", + dlm->name, res->lockname.len, + res->lockname.name, target); + ret = -ERESTARTSYS; + } } if (ret == -ERESTARTSYS) { /* migration failed, detach and clean up mle */ diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 0c8eb1093f00..186e9a76aa58 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -39,6 +39,7 @@ #include <linux/inet.h> #include <linux/timer.h> #include <linux/kthread.h> +#include <linux/delay.h> #include "cluster/heartbeat.h" @@ -256,6 +257,27 @@ static int dlm_recovery_thread(void *data) return 0; } +/* returns true when the recovery master has contacted us */ +static int dlm_reco_master_ready(struct dlm_ctxt *dlm) +{ + int ready; + spin_lock(&dlm->spinlock); + ready = (dlm->reco.new_master != O2NM_INVALID_NODE_NUM); + spin_unlock(&dlm->spinlock); + return ready; +} + +/* returns true if node is no longer in the domain + * could be dead or just not joined */ +int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node) +{ + int dead; + spin_lock(&dlm->spinlock); + dead = test_bit(node, dlm->domain_map); + spin_unlock(&dlm->spinlock); + return dead; +} + /* callers of the top-level api calls (dlmlock/dlmunlock) should * block on the dlm->reco.event when recovery is in progress. * the dlm recovery thread will set this state when it begins @@ -297,6 +319,7 @@ static void dlm_end_recovery(struct dlm_ctxt *dlm) static int dlm_do_recovery(struct dlm_ctxt *dlm) { int status = 0; + int ret; spin_lock(&dlm->spinlock); @@ -343,10 +366,13 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) goto master_here; if (dlm->reco.new_master == O2NM_INVALID_NODE_NUM) { - /* choose a new master */ - if (!dlm_pick_recovery_master(dlm)) { + /* choose a new master, returns 0 if this node + * is the master, -EEXIST if it's another node. + * this does not return until a new master is chosen + * or recovery completes entirely. */ + ret = dlm_pick_recovery_master(dlm); + if (!ret) { /* already notified everyone. go. */ - dlm->reco.new_master = dlm->node_num; goto master_here; } mlog(0, "another node will master this recovery session.\n"); @@ -371,8 +397,13 @@ master_here: if (status < 0) { mlog(ML_ERROR, "error %d remastering locks for node %u, " "retrying.\n", status, dlm->reco.dead_node); + /* yield a bit to allow any final network messages + * to get handled on remaining nodes */ + msleep(100); } else { /* success! see if any other nodes need recovery */ + mlog(0, "DONE mastering recovery of %s:%u here(this=%u)!\n", + dlm->name, dlm->reco.dead_node, dlm->node_num); dlm_reset_recovery(dlm); } dlm_end_recovery(dlm); @@ -477,7 +508,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) BUG(); break; case DLM_RECO_NODE_DATA_DEAD: - mlog(0, "node %u died after " + mlog(ML_NOTICE, "node %u died after " "requesting recovery info for " "node %u\n", ndata->node_num, dead_node); @@ -485,6 +516,19 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) // start all over destroy = 1; status = -EAGAIN; + /* instead of spinning like crazy here, + * wait for the domain map to catch up + * with the network state. otherwise this + * can be hit hundreds of times before + * the node is really seen as dead. */ + wait_event_timeout(dlm->dlm_reco_thread_wq, + dlm_is_node_dead(dlm, + ndata->node_num), + msecs_to_jiffies(1000)); + mlog(0, "waited 1 sec for %u, " + "dead? %s\n", ndata->node_num, + dlm_is_node_dead(dlm, ndata->node_num) ? + "yes" : "no"); goto leave; case DLM_RECO_NODE_DATA_RECEIVING: case DLM_RECO_NODE_DATA_REQUESTED: @@ -678,11 +722,27 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data) dlm = item->dlm; dead_node = item->u.ral.dead_node; reco_master = item->u.ral.reco_master; + mres = (struct dlm_migratable_lockres *)data; + + if (dead_node != dlm->reco.dead_node || + reco_master != dlm->reco.new_master) { + /* show extra debug info if the recovery state is messed */ + mlog(ML_ERROR, "%s: bad reco state: reco(dead=%u, master=%u), " + "request(dead=%u, master=%u)\n", + dlm->name, dlm->reco.dead_node, dlm->reco.new_master, + dead_node, reco_master); + mlog(ML_ERROR, "%s: name=%.*s master=%u locks=%u/%u flags=%u " + "entry[0]={c=%"MLFu64",l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n", + dlm->name, mres->lockname_len, mres->lockname, mres->master, + mres->num_locks, mres->total_locks, mres->flags, + mres->ml[0].cookie, mres->ml[0].list, mres->ml[0].flags, + mres->ml[0].type, mres->ml[0].convert_type, + mres->ml[0].highest_blocked, mres->ml[0].node); + BUG(); + } BUG_ON(dead_node != dlm->reco.dead_node); BUG_ON(reco_master != dlm->reco.new_master); - mres = (struct dlm_migratable_lockres *)data; - /* lock resources should have already been moved to the * dlm->reco.resources list. now move items from that list * to a temp list if the dead owner matches. note that the @@ -757,15 +817,18 @@ int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data) continue; switch (ndata->state) { + /* should have moved beyond INIT but not to FINALIZE yet */ case DLM_RECO_NODE_DATA_INIT: case DLM_RECO_NODE_DATA_DEAD: - case DLM_RECO_NODE_DATA_DONE: case DLM_RECO_NODE_DATA_FINALIZE_SENT: mlog(ML_ERROR, "bad ndata state for node %u:" " state=%d\n", ndata->node_num, ndata->state); BUG(); break; + /* these states are possible at this point, anywhere along + * the line of recovery */ + case DLM_RECO_NODE_DATA_DONE: case DLM_RECO_NODE_DATA_RECEIVING: case DLM_RECO_NODE_DATA_REQUESTED: case DLM_RECO_NODE_DATA_REQUESTING: @@ -799,13 +862,31 @@ static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm, { struct dlm_lock_resource *res; struct list_head *iter, *iter2; + struct dlm_lock *lock; spin_lock(&dlm->spinlock); list_for_each_safe(iter, iter2, &dlm->reco.resources) { res = list_entry (iter, struct dlm_lock_resource, recovering); + /* always prune any $RECOVERY entries for dead nodes, + * otherwise hangs can occur during later recovery */ if (dlm_is_recovery_lock(res->lockname.name, - res->lockname.len)) + res->lockname.len)) { + spin_lock(&res->spinlock); + list_for_each_entry(lock, &res->granted, list) { + if (lock->ml.node == dead_node) { + mlog(0, "AHA! there was " + "a $RECOVERY lock for dead " + "node %u (%s)!\n", + dead_node, dlm->name); + list_del_init(&lock->list); + dlm_lock_put(lock); + break; + } + } + spin_unlock(&res->spinlock); continue; + } + if (res->owner == dead_node) { mlog(0, "found lockres owned by dead node while " "doing recovery for node %u. sending it.\n", @@ -1179,7 +1260,7 @@ static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data) again: ret = dlm_lockres_master_requery(dlm, res, &real_master); if (ret < 0) { - mlog(0, "dlm_lockres_master_requery failure: %d\n", + mlog(0, "dlm_lockres_master_requery ret=%d\n", ret); goto again; } @@ -1757,6 +1838,7 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) struct dlm_lock_resource *res; int i; struct list_head *bucket; + struct dlm_lock *lock; /* purge any stale mles */ @@ -1780,10 +1862,25 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) bucket = &(dlm->resources[i]); list_for_each(iter, bucket) { res = list_entry (iter, struct dlm_lock_resource, list); + /* always prune any $RECOVERY entries for dead nodes, + * otherwise hangs can occur during later recovery */ if (dlm_is_recovery_lock(res->lockname.name, - res->lockname.len)) + res->lockname.len)) { + spin_lock(&res->spinlock); + list_for_each_entry(lock, &res->granted, list) { + if (lock->ml.node == dead_node) { + mlog(0, "AHA! there was " + "a $RECOVERY lock for dead " + "node %u (%s)!\n", + dead_node, dlm->name); + list_del_init(&lock->list); + dlm_lock_put(lock); + break; + } + } + spin_unlock(&res->spinlock); continue; - + } spin_lock(&res->spinlock); /* zero the lvb if necessary */ dlm_revalidate_lvb(dlm, res, dead_node); @@ -1869,12 +1966,9 @@ void dlm_hb_node_up_cb(struct o2nm_node *node, int idx, void *data) return; spin_lock(&dlm->spinlock); - set_bit(idx, dlm->live_nodes_map); - - /* notify any mles attached to the heartbeat events */ - dlm_hb_event_notify_attached(dlm, idx, 1); - + /* do NOT notify mle attached to the heartbeat events. + * new nodes are not interesting in mastery until joined. */ spin_unlock(&dlm->spinlock); dlm_put(dlm); @@ -1897,7 +1991,18 @@ static void dlm_reco_unlock_ast(void *astdata, enum dlm_status st) mlog(0, "unlockast for recovery lock fired!\n"); } - +/* + * dlm_pick_recovery_master will continually attempt to use + * dlmlock() on the special "$RECOVERY" lockres with the + * LKM_NOQUEUE flag to get an EX. every thread that enters + * this function on each node racing to become the recovery + * master will not stop attempting this until either: + * a) this node gets the EX (and becomes the recovery master), + * or b) dlm->reco.new_master gets set to some nodenum + * != O2NM_INVALID_NODE_NUM (another node will do the reco). + * so each time a recovery master is needed, the entire cluster + * will sync at this point. if the new master dies, that will + * be detected in dlm_do_recovery */ static int dlm_pick_recovery_master(struct dlm_ctxt *dlm) { enum dlm_status ret; @@ -1906,23 +2011,45 @@ static int dlm_pick_recovery_master(struct dlm_ctxt *dlm) mlog(0, "starting recovery of %s at %lu, dead=%u, this=%u\n", dlm->name, jiffies, dlm->reco.dead_node, dlm->node_num); -retry: +again: memset(&lksb, 0, sizeof(lksb)); ret = dlmlock(dlm, LKM_EXMODE, &lksb, LKM_NOQUEUE|LKM_RECOVERY, DLM_RECOVERY_LOCK_NAME, dlm_reco_ast, dlm, dlm_reco_bast); + mlog(0, "%s: dlmlock($RECOVERY) returned %d, lksb=%d\n", + dlm->name, ret, lksb.status); + if (ret == DLM_NORMAL) { mlog(0, "dlm=%s dlmlock says I got it (this=%u)\n", dlm->name, dlm->node_num); - /* I am master, send message to all nodes saying - * that I am beginning a recovery session */ - status = dlm_send_begin_reco_message(dlm, - dlm->reco.dead_node); + + /* got the EX lock. check to see if another node + * just became the reco master */ + if (dlm_reco_master_ready(dlm)) { + mlog(0, "%s: got reco EX lock, but %u will " + "do the recovery\n", dlm->name, + dlm->reco.new_master); + status = -EEXIST; + } else { + status = dlm_send_begin_reco_message(dlm, + dlm->reco.dead_node); + /* this always succeeds */ + BUG_ON(status); + + /* set the new_master to this node */ + spin_lock(&dlm->spinlock); + dlm->reco.new_master = dlm->node_num; + spin_unlock(&dlm->spinlock); + } /* recovery lock is a special case. ast will not get fired, * so just go ahead and unlock it. */ ret = dlmunlock(dlm, &lksb, 0, dlm_reco_unlock_ast, dlm); + if (ret == DLM_DENIED) { + mlog(0, "got DLM_DENIED, trying LKM_CANCEL\n"); + ret = dlmunlock(dlm, &lksb, LKM_CANCEL, dlm_reco_unlock_ast, dlm); + } if (ret != DLM_NORMAL) { /* this would really suck. this could only happen * if there was a network error during the unlock @@ -1930,20 +2057,42 @@ retry: * is actually "done" and the lock structure is * even freed. we can continue, but only * because this specific lock name is special. */ - mlog(0, "dlmunlock returned %d\n", ret); - } - - if (status < 0) { - mlog(0, "failed to send recovery message. " - "must retry with new node map.\n"); - goto retry; + mlog(ML_ERROR, "dlmunlock returned %d\n", ret); } } else if (ret == DLM_NOTQUEUED) { mlog(0, "dlm=%s dlmlock says another node got it (this=%u)\n", dlm->name, dlm->node_num); /* another node is master. wait on - * reco.new_master != O2NM_INVALID_NODE_NUM */ + * reco.new_master != O2NM_INVALID_NODE_NUM + * for at most one second */ + wait_event_timeout(dlm->dlm_reco_thread_wq, + dlm_reco_master_ready(dlm), + msecs_to_jiffies(1000)); + if (!dlm_reco_master_ready(dlm)) { + mlog(0, "%s: reco master taking awhile\n", + dlm->name); + goto again; + } + /* another node has informed this one that it is reco master */ + mlog(0, "%s: reco master %u is ready to recover %u\n", + dlm->name, dlm->reco.new_master, dlm->reco.dead_node); status = -EEXIST; + } else { + struct dlm_lock_resource *res; + + /* dlmlock returned something other than NOTQUEUED or NORMAL */ + mlog(ML_ERROR, "%s: got %s from dlmlock($RECOVERY), " + "lksb.status=%s\n", dlm->name, dlm_errname(ret), + dlm_errname(lksb.status)); + res = dlm_lookup_lockres(dlm, DLM_RECOVERY_LOCK_NAME, + DLM_RECOVERY_LOCK_NAME_LEN); + if (res) { + dlm_print_one_lock_resource(res); + dlm_lockres_put(res); + } else { + mlog(ML_ERROR, "recovery lock not found\n"); + } + BUG(); } return status; @@ -1982,7 +2131,7 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) mlog(0, "not sending begin reco to self\n"); continue; } - +retry: ret = -EINVAL; mlog(0, "attempting to send begin reco msg to %d\n", nodenum); @@ -1991,8 +2140,17 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) /* negative status is handled ok by caller here */ if (ret >= 0) ret = status; + if (dlm_is_host_down(ret)) { + /* node is down. not involved in recovery + * so just keep going */ + mlog(0, "%s: node %u was down when sending " + "begin reco msg (%d)\n", dlm->name, nodenum, ret); + ret = 0; + } if (ret < 0) { struct dlm_lock_resource *res; + /* this is now a serious problem, possibly ENOMEM + * in the network stack. must retry */ mlog_errno(ret); mlog(ML_ERROR, "begin reco of dlm %s to node %u " " returned %d\n", dlm->name, nodenum, ret); @@ -2004,7 +2162,10 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) } else { mlog(ML_ERROR, "recovery lock not found\n"); } - break; + /* sleep for a bit in hopes that we can avoid + * another ENOMEM */ + msleep(100); + goto retry; } } @@ -2027,19 +2188,34 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data) spin_lock(&dlm->spinlock); if (dlm->reco.new_master != O2NM_INVALID_NODE_NUM) { - mlog(0, "new_master already set to %u!\n", - dlm->reco.new_master); + if (test_bit(dlm->reco.new_master, dlm->recovery_map)) { + mlog(0, "%s: new_master %u died, changing " + "to %u\n", dlm->name, dlm->reco.new_master, + br->node_idx); + } else { + mlog(0, "%s: new_master %u NOT DEAD, changing " + "to %u\n", dlm->name, dlm->reco.new_master, + br->node_idx); + /* may not have seen the new master as dead yet */ + } } if (dlm->reco.dead_node != O2NM_INVALID_NODE_NUM) { - mlog(0, "dead_node already set to %u!\n", - dlm->reco.dead_node); + mlog(ML_NOTICE, "%s: dead_node previously set to %u, " + "node %u changing it to %u\n", dlm->name, + dlm->reco.dead_node, br->node_idx, br->dead_node); } dlm->reco.new_master = br->node_idx; dlm->reco.dead_node = br->dead_node; if (!test_bit(br->dead_node, dlm->recovery_map)) { - mlog(ML_ERROR, "recovery master %u sees %u as dead, but this " + mlog(0, "recovery master %u sees %u as dead, but this " "node has not yet. marking %u as dead\n", br->node_idx, br->dead_node, br->dead_node); + if (!test_bit(br->dead_node, dlm->domain_map) || + !test_bit(br->dead_node, dlm->live_nodes_map)) + mlog(0, "%u not in domain/live_nodes map " + "so setting it in reco map manually\n", + br->dead_node); + set_bit(br->dead_node, dlm->recovery_map); __dlm_hb_node_down(dlm, br->dead_node); } spin_unlock(&dlm->spinlock); diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c index cec2ce1cd318..c95f08d2e925 100644 --- a/fs/ocfs2/dlm/dlmunlock.c +++ b/fs/ocfs2/dlm/dlmunlock.c @@ -188,6 +188,19 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, actions &= ~(DLM_UNLOCK_REMOVE_LOCK| DLM_UNLOCK_REGRANT_LOCK| DLM_UNLOCK_CLEAR_CONVERT_TYPE); + } else if (status == DLM_RECOVERING || + status == DLM_MIGRATING || + status == DLM_FORWARD) { + /* must clear the actions because this unlock + * is about to be retried. cannot free or do + * any list manipulation. */ + mlog(0, "%s:%.*s: clearing actions, %s\n", + dlm->name, res->lockname.len, + res->lockname.name, + status==DLM_RECOVERING?"recovering": + (status==DLM_MIGRATING?"migrating": + "forward")); + actions = 0; } if (flags & LKM_CANCEL) lock->cancel_pending = 0; diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c index e1fdd288796e..c3764f4744ee 100644 --- a/fs/ocfs2/dlm/userdlm.c +++ b/fs/ocfs2/dlm/userdlm.c @@ -27,7 +27,7 @@ * Boston, MA 021110-1307, USA. */ -#include <asm/signal.h> +#include <linux/signal.h> #include <linux/module.h> #include <linux/fs.h> diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index f2fb40cd296a..b6ba292e9544 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -262,8 +262,7 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, el = &eb->h_list; } - if (el->l_tree_depth) - BUG(); + BUG_ON(el->l_tree_depth); for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { rec = &el->l_recs[i]; @@ -364,8 +363,8 @@ static int ocfs2_extent_map_lookup_read(struct inode *inode, return ret; } - if (ent->e_tree_depth) - BUG(); /* FIXME: Make sure this isn't a corruption */ + /* FIXME: Make sure this isn't a corruption */ + BUG_ON(ent->e_tree_depth); *ret_ent = ent; @@ -423,8 +422,7 @@ static int ocfs2_extent_map_try_insert(struct inode *inode, le32_to_cpu(rec->e_clusters), NULL, NULL); - if (!old_ent) - BUG(); + BUG_ON(!old_ent); ret = -EEXIST; if (old_ent->e_tree_depth < tree_depth) @@ -988,7 +986,7 @@ int __init init_ocfs2_extent_maps(void) return 0; } -void __exit exit_ocfs2_extent_maps(void) +void exit_ocfs2_extent_maps(void) { kmem_cache_destroy(ocfs2_em_ent_cachep); } diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index eaf33caa0a1f..1715bc90e705 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1022,8 +1022,9 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, } newsize = count + saved_pos; - mlog(0, "pos=%lld newsize=%"MLFu64" cursize=%lld\n", - saved_pos, newsize, i_size_read(inode)); + mlog(0, "pos=%lld newsize=%lld cursize=%lld\n", + (long long) saved_pos, (long long) newsize, + (long long) i_size_read(inode)); /* No need for a higher level metadata lock if we're * never going past i_size. */ @@ -1042,8 +1043,9 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, spin_unlock(&OCFS2_I(inode)->ip_lock); mlog(0, "Writing at EOF, may need more allocation: " - "i_size = %lld, newsize = %"MLFu64", need %u clusters\n", - i_size_read(inode), newsize, clusters); + "i_size = %lld, newsize = %lld, need %u clusters\n", + (long long) i_size_read(inode), (long long) newsize, + clusters); /* We only want to continue the rest of this loop if * our extend will actually require more diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index d4ecc0627716..8122489c5762 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -903,10 +903,10 @@ void ocfs2_clear_inode(struct inode *inode) "Clear inode of %"MLFu64", inode is locked\n", oi->ip_blkno); - mlog_bug_on_msg(down_trylock(&oi->ip_io_sem), - "Clear inode of %"MLFu64", io_sem is locked\n", + mlog_bug_on_msg(!mutex_trylock(&oi->ip_io_mutex), + "Clear inode of %"MLFu64", io_mutex is locked\n", oi->ip_blkno); - up(&oi->ip_io_sem); + mutex_unlock(&oi->ip_io_mutex); /* * down_trylock() returns 0, down_write_trylock() returns 1 diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 9b0177433653..84c507961287 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -46,10 +46,10 @@ struct ocfs2_inode_info struct list_head ip_io_markers; int ip_orphaned_slot; - struct semaphore ip_io_sem; + struct mutex ip_io_mutex; /* Used by the journalling code to attach an inode to a - * handle. These are protected by ip_io_sem in order to lock + * handle. These are protected by ip_io_mutex in order to lock * out other I/O to the inode until we either commit or * abort. */ struct list_head ip_handle_list; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 303c8d96457f..fa0bcac5ceae 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -147,8 +147,7 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb, mlog_entry("(max_buffs = %d)\n", max_buffs); - if (!osb || !osb->journal->j_journal) - BUG(); + BUG_ON(!osb || !osb->journal->j_journal); if (ocfs2_is_hard_readonly(osb)) { ret = -EROFS; @@ -401,7 +400,7 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, * j_trans_barrier for us. */ ocfs2_set_inode_lock_trans(OCFS2_SB(inode->i_sb)->journal, inode); - down(&OCFS2_I(inode)->ip_io_sem); + mutex_lock(&OCFS2_I(inode)->ip_io_mutex); switch (type) { case OCFS2_JOURNAL_ACCESS_CREATE: case OCFS2_JOURNAL_ACCESS_WRITE: @@ -416,7 +415,7 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle, status = -EINVAL; mlog(ML_ERROR, "Uknown access type!\n"); } - up(&OCFS2_I(inode)->ip_io_sem); + mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); if (status < 0) mlog(ML_ERROR, "Error %d getting %d access to buffer!\n", @@ -561,7 +560,11 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) SET_INODE_JOURNAL(inode); OCFS2_I(inode)->ip_open_count++; - status = ocfs2_meta_lock(inode, NULL, &bh, 1); + /* Skip recovery waits here - journal inode metadata never + * changes in a live cluster so it can be considered an + * exception to the rule. */ + status = ocfs2_meta_lock_full(inode, NULL, &bh, 1, + OCFS2_META_LOCK_RECOVERY); if (status < 0) { if (status != -ERESTARTSYS) mlog(ML_ERROR, "Could not get lock on journal!\n"); @@ -672,8 +675,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) mlog_entry_void(); - if (!osb) - BUG(); + BUG_ON(!osb); journal = osb->journal; if (!journal) @@ -805,8 +807,7 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full) mlog_entry_void(); - if (!journal) - BUG(); + BUG_ON(!journal); status = journal_wipe(journal->j_journal, full); if (status < 0) { @@ -1072,10 +1073,10 @@ restart: NULL); bail: - down(&osb->recovery_lock); + mutex_lock(&osb->recovery_lock); if (!status && !ocfs2_node_map_is_empty(osb, &osb->recovery_map)) { - up(&osb->recovery_lock); + mutex_unlock(&osb->recovery_lock); goto restart; } @@ -1083,7 +1084,7 @@ bail: mb(); /* sync with ocfs2_recovery_thread_running */ wake_up(&osb->recovery_event); - up(&osb->recovery_lock); + mutex_unlock(&osb->recovery_lock); mlog_exit(status); /* no one is callint kthread_stop() for us so the kthread() api @@ -1098,7 +1099,7 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) mlog_entry("(node_num=%d, osb->node_num = %d)\n", node_num, osb->node_num); - down(&osb->recovery_lock); + mutex_lock(&osb->recovery_lock); if (osb->disable_recovery) goto out; @@ -1120,7 +1121,7 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) } out: - up(&osb->recovery_lock); + mutex_unlock(&osb->recovery_lock); wake_up(&osb->recovery_event); mlog_exit_void(); @@ -1271,8 +1272,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, /* Should not ever be called to recover ourselves -- in that * case we should've called ocfs2_journal_load instead. */ - if (osb->node_num == node_num) - BUG(); + BUG_ON(osb->node_num == node_num); slot_num = ocfs2_node_num_to_slot(si, node_num); if (slot_num == OCFS2_INVALID_SLOT) { diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index f468c600cf92..8d8e4779df92 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -33,6 +33,7 @@ #include <linux/rbtree.h> #include <linux/workqueue.h> #include <linux/kref.h> +#include <linux/mutex.h> #include "cluster/nodemanager.h" #include "cluster/heartbeat.h" @@ -233,7 +234,7 @@ struct ocfs2_super struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/<maj_min> */ atomic_t vol_state; - struct semaphore recovery_lock; + struct mutex recovery_lock; struct task_struct *recovery_thread_task; int disable_recovery; wait_queue_head_t checkpoint_event; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 364d64bd5f10..046824b6b625 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -932,7 +932,7 @@ static void ocfs2_inode_init_once(void *data, oi->ip_dir_start_lookup = 0; init_rwsem(&oi->ip_alloc_sem); - init_MUTEX(&(oi->ip_io_sem)); + mutex_init(&oi->ip_io_mutex); oi->ip_blkno = 0ULL; oi->ip_clusters = 0; @@ -1137,9 +1137,9 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) /* disable any new recovery threads and wait for any currently * running ones to exit. Do this before setting the vol_state. */ - down(&osb->recovery_lock); + mutex_lock(&osb->recovery_lock); osb->disable_recovery = 1; - up(&osb->recovery_lock); + mutex_unlock(&osb->recovery_lock); wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb)); /* At this point, we know that no more recovery threads can be @@ -1254,8 +1254,7 @@ static int ocfs2_initialize_super(struct super_block *sb, osb->sb = sb; /* Save off for ocfs2_rw_direct */ osb->s_sectsize_bits = blksize_bits(sector_size); - if (!osb->s_sectsize_bits) - BUG(); + BUG_ON(!osb->s_sectsize_bits); osb->net_response_ids = 0; spin_lock_init(&osb->net_response_lock); @@ -1283,7 +1282,7 @@ static int ocfs2_initialize_super(struct super_block *sb, snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); - init_MUTEX(&osb->recovery_lock); + mutex_init(&osb->recovery_lock); osb->disable_recovery = 0; osb->recovery_thread_task = NULL; diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index 600a8bc5b541..fc29cb7a437d 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c @@ -77,8 +77,7 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, if (arr && ((inode = *arr) != NULL)) { /* get a ref in addition to the array ref */ inode = igrab(inode); - if (!inode) - BUG(); + BUG_ON(!inode); return inode; } @@ -89,8 +88,7 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, /* add one more if putting into array for first time */ if (arr && inode) { *arr = igrab(inode); - if (!*arr) - BUG(); + BUG_ON(!*arr); } return inode; } diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index 3a0458fd3e1b..300b5bedfb21 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c @@ -388,7 +388,7 @@ out_free: } } -/* Item insertion is guarded by ip_io_sem, so the insertion path takes +/* Item insertion is guarded by ip_io_mutex, so the insertion path takes * advantage of this by not rechecking for a duplicate insert during * the slow case. Additionally, if the cache needs to be bumped up to * a tree, the code will not recheck after acquiring the lock -- @@ -418,7 +418,7 @@ void ocfs2_set_buffer_uptodate(struct inode *inode, (unsigned long long) bh->b_blocknr); /* No need to recheck under spinlock - insertion is guarded by - * ip_io_sem */ + * ip_io_mutex */ spin_lock(&oi->ip_lock); if (ocfs2_insert_can_use_array(oi, ci)) { /* Fast case - it's an array and there's a free @@ -440,7 +440,7 @@ void ocfs2_set_buffer_uptodate(struct inode *inode, /* Called against a newly allocated buffer. Most likely nobody should * be able to read this sort of metadata while it's still being - * allocated, but this is careful to take ip_io_sem anyway. */ + * allocated, but this is careful to take ip_io_mutex anyway. */ void ocfs2_set_new_buffer_uptodate(struct inode *inode, struct buffer_head *bh) { @@ -451,9 +451,9 @@ void ocfs2_set_new_buffer_uptodate(struct inode *inode, set_buffer_uptodate(bh); - down(&oi->ip_io_sem); + mutex_lock(&oi->ip_io_mutex); ocfs2_set_buffer_uptodate(inode, bh); - up(&oi->ip_io_sem); + mutex_unlock(&oi->ip_io_mutex); } /* Requires ip_lock. */ @@ -537,7 +537,7 @@ int __init init_ocfs2_uptodate_cache(void) return 0; } -void __exit exit_ocfs2_uptodate_cache(void) +void exit_ocfs2_uptodate_cache(void) { if (ocfs2_uptodate_cachep) kmem_cache_destroy(ocfs2_uptodate_cachep); diff --git a/fs/ocfs2/uptodate.h b/fs/ocfs2/uptodate.h index e5aacdf4eabf..01cd32d26b06 100644 --- a/fs/ocfs2/uptodate.h +++ b/fs/ocfs2/uptodate.h @@ -27,7 +27,7 @@ #define OCFS2_UPTODATE_H int __init init_ocfs2_uptodate_cache(void); -void __exit exit_ocfs2_uptodate_cache(void); +void exit_ocfs2_uptodate_cache(void); void ocfs2_metadata_cache_init(struct inode *inode); void ocfs2_metadata_cache_purge(struct inode *inode); diff --git a/fs/open.c b/fs/open.c index 8e20c1f32563..70e0230d8e77 100644 --- a/fs/open.c +++ b/fs/open.c @@ -20,6 +20,7 @@ #include <linux/security.h> #include <linux/mount.h> #include <linux/vfs.h> +#include <linux/fcntl.h> #include <asm/uaccess.h> #include <linux/fs.h> #include <linux/personality.h> @@ -383,7 +384,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) error = get_user(newattrs.ia_atime.tv_sec, ×->actime); newattrs.ia_atime.tv_nsec = 0; - if (!error) + if (!error) error = get_user(newattrs.ia_mtime.tv_sec, ×->modtime); newattrs.ia_mtime.tv_nsec = 0; if (error) @@ -414,14 +415,14 @@ out: * must be owner or have write permission. * Else, update from *times, must be owner or super user. */ -long do_utimes(char __user * filename, struct timeval * times) +long do_utimes(int dfd, char __user *filename, struct timeval *times) { int error; struct nameidata nd; struct inode * inode; struct iattr newattrs; - error = user_path_walk(filename, &nd); + error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); if (error) goto out; @@ -461,13 +462,18 @@ out: return error; } -asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes) +asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes) { struct timeval times[2]; if (utimes && copy_from_user(×, utimes, sizeof(times))) return -EFAULT; - return do_utimes(filename, utimes ? times : NULL); + return do_utimes(dfd, filename, utimes ? times : NULL); +} + +asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes) +{ + return sys_futimesat(AT_FDCWD, filename, utimes); } @@ -476,7 +482,7 @@ asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utime * We do this by temporarily clearing all FS-related capabilities and * switching the fsuid/fsgid around to the real ones. */ -asmlinkage long sys_access(const char __user * filename, int mode) +asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) { struct nameidata nd; int old_fsuid, old_fsgid; @@ -506,7 +512,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) else current->cap_effective = current->cap_permitted; - res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); + res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (!res) { res = vfs_permission(&nd, mode); /* SuS v2 requires we report a read only fs too */ @@ -523,6 +529,11 @@ asmlinkage long sys_access(const char __user * filename, int mode) return res; } +asmlinkage long sys_access(const char __user *filename, int mode) +{ + return sys_faccessat(AT_FDCWD, filename, mode); +} + asmlinkage long sys_chdir(const char __user * filename) { struct nameidata nd; @@ -635,14 +646,15 @@ out: return err; } -asmlinkage long sys_chmod(const char __user * filename, mode_t mode) +asmlinkage long sys_fchmodat(int dfd, const char __user *filename, + mode_t mode) { struct nameidata nd; struct inode * inode; int error; struct iattr newattrs; - error = user_path_walk(filename, &nd); + error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); if (error) goto out; inode = nd.dentry->d_inode; @@ -669,6 +681,11 @@ out: return error; } +asmlinkage long sys_chmod(const char __user *filename, mode_t mode) +{ + return sys_fchmodat(AT_FDCWD, filename, mode); +} + static int chown_common(struct dentry * dentry, uid_t user, gid_t group) { struct inode * inode; @@ -717,6 +734,26 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) return error; } +asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, + gid_t group, int flag) +{ + struct nameidata nd; + int error = -EINVAL; + int follow; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; + error = __user_walk_fd(dfd, filename, follow, &nd); + if (!error) { + error = chown_common(nd.dentry, user, group); + path_release(&nd); + } +out: + return error; +} + asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) { struct nameidata nd; @@ -820,7 +857,8 @@ cleanup_file: * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ -struct file *filp_open(const char * filename, int flags, int mode) +static struct file *do_filp_open(int dfd, const char *filename, int flags, + int mode) { int namei_flags, error; struct nameidata nd; @@ -829,12 +867,17 @@ struct file *filp_open(const char * filename, int flags, int mode) if ((namei_flags+1) & O_ACCMODE) namei_flags++; - error = open_namei(filename, namei_flags, mode, &nd); + error = open_namei(dfd, filename, namei_flags, mode, &nd); if (!error) return nameidata_to_filp(&nd, flags); return ERR_PTR(error); } + +struct file *filp_open(const char *filename, int flags, int mode) +{ + return do_filp_open(AT_FDCWD, filename, flags, mode); +} EXPORT_SYMBOL(filp_open); /** @@ -991,7 +1034,7 @@ void fastcall put_unused_fd(unsigned int fd) EXPORT_SYMBOL(put_unused_fd); /* - * Install a file pointer in the fd array. + * Install a file pointer in the fd array. * * The VFS is full of places where we drop the files lock between * setting the open_fds bitmap and installing the file in the file @@ -1016,7 +1059,7 @@ void fastcall fd_install(unsigned int fd, struct file * file) EXPORT_SYMBOL(fd_install); -long do_sys_open(const char __user *filename, int flags, int mode) +long do_sys_open(int dfd, const char __user *filename, int flags, int mode) { char *tmp = getname(filename); int fd = PTR_ERR(tmp); @@ -1024,7 +1067,7 @@ long do_sys_open(const char __user *filename, int flags, int mode) if (!IS_ERR(tmp)) { fd = get_unused_fd(); if (fd >= 0) { - struct file *f = filp_open(tmp, flags, mode); + struct file *f = do_filp_open(dfd, tmp, flags, mode); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); @@ -1043,10 +1086,20 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode) if (force_o_largefile()) flags |= O_LARGEFILE; - return do_sys_open(filename, flags, mode); + return do_sys_open(AT_FDCWD, filename, flags, mode); } EXPORT_SYMBOL_GPL(sys_open); +asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, + int mode) +{ + if (force_o_largefile()) + flags |= O_LARGEFILE; + + return do_sys_open(dfd, filename, flags, mode); +} +EXPORT_SYMBOL_GPL(sys_openat); + #ifndef __alpha__ /* diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 8f8014285a34..1d24fead51a6 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -548,7 +548,7 @@ static int show_stat(struct seq_file *p, void *v) } seq_printf(p, "intr %llu", (unsigned long long)sum); -#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA) +#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64) for (i = 0; i < NR_IRQS; i++) seq_printf(p, " %u", kstat_irqs(i)); #endif diff --git a/fs/quota_v2.c b/fs/quota_v2.c index a4ef91bb4f3b..b4199ec3ece4 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c @@ -35,7 +35,7 @@ static int v2_check_quota_file(struct super_block *sb, int type) size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) { - printk("quota_v2: failed read expected=%d got=%d\n", + printk("quota_v2: failed read expected=%zd got=%zd\n", sizeof(struct v2_disk_dqheader), size); return 0; } diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 9dd71e807034..d71ac6579289 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -150,18 +150,15 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (d_reclen <= 32) { local_buf = small_buf; } else { - local_buf = - reiserfs_kmalloc(d_reclen, GFP_NOFS, - inode->i_sb); + local_buf = kmalloc(d_reclen, + GFP_NOFS); if (!local_buf) { pathrelse(&path_to_entry); ret = -ENOMEM; goto out; } if (item_moved(&tmp_ih, &path_to_entry)) { - reiserfs_kfree(local_buf, - d_reclen, - inode->i_sb); + kfree(local_buf); goto research; } } @@ -174,15 +171,12 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir) (dirent, local_buf, d_reclen, d_off, d_ino, DT_UNKNOWN) < 0) { if (local_buf != small_buf) { - reiserfs_kfree(local_buf, - d_reclen, - inode->i_sb); + kfree(local_buf); } goto end; } if (local_buf != small_buf) { - reiserfs_kfree(local_buf, d_reclen, - inode->i_sb); + kfree(local_buf); } // next entry should be looked for with such offset next_pos = deh_offset(deh) + 1; diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index ad6fa964b0e7..f3473176c83a 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -192,6 +192,8 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) * sizeof(b_blocknr_t), GFP_NOFS); + if (!allocated_blocks) + return -ENOMEM; /* First we compose a key to point at the writing position, we want to do that outside of any locking region. */ @@ -1285,6 +1287,23 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t struct reiserfs_transaction_handle th; th.t_trans_id = 0; + /* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items + * lying around (most of the disk, in fact). Despite the filesystem + * now being a v3.6 format, the old items still can't support large + * file sizes. Catch this case here, as the rest of the VFS layer is + * oblivious to the different limitations between old and new items. + * reiserfs_setattr catches this for truncates. This chunk is lifted + * from generic_write_checks. */ + if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 && + *ppos + count > MAX_NON_LFS) { + if (*ppos >= MAX_NON_LFS) { + send_sig(SIGXFSZ, current, 0); + return -EFBIG; + } + if (count > MAX_NON_LFS - (unsigned long)*ppos) + count = MAX_NON_LFS - (unsigned long)*ppos; + } + if (file->f_flags & O_DIRECT) { // Direct IO needs treatment ssize_t result, after_file_end = 0; if ((*ppos + count >= inode->i_size) diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 45829889dcdc..aa22588019ec 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c @@ -2021,38 +2021,6 @@ static int get_neighbors(struct tree_balance *p_s_tb, int n_h) return CARRY_ON; } -#ifdef CONFIG_REISERFS_CHECK -void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s) -{ - void *vp; - static size_t malloced; - - vp = kmalloc(size, flags); - if (vp) { - REISERFS_SB(s)->s_kmallocs += size; - if (REISERFS_SB(s)->s_kmallocs > malloced + 200000) { - reiserfs_warning(s, - "vs-8301: reiserfs_kmalloc: allocated memory %d", - REISERFS_SB(s)->s_kmallocs); - malloced = REISERFS_SB(s)->s_kmallocs; - } - } - return vp; -} - -void reiserfs_kfree(const void *vp, size_t size, struct super_block *s) -{ - kfree(vp); - - REISERFS_SB(s)->s_kmallocs -= size; - if (REISERFS_SB(s)->s_kmallocs < 0) - reiserfs_warning(s, - "vs-8302: reiserfs_kfree: allocated memory %d", - REISERFS_SB(s)->s_kmallocs); - -} -#endif - static int get_virtual_node_size(struct super_block *sb, struct buffer_head *bh) { int max_num_of_items; @@ -2086,7 +2054,7 @@ static int get_mem_for_virtual_node(struct tree_balance *tb) /* we have to allocate more memory for virtual node */ if (tb->vn_buf) { /* free memory allocated before */ - reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb); + kfree(tb->vn_buf); /* this is not needed if kfree is atomic */ check_fs = 1; } @@ -2095,24 +2063,15 @@ static int get_mem_for_virtual_node(struct tree_balance *tb) tb->vn_buf_size = size; /* get memory for virtual item */ - buf = - reiserfs_kmalloc(size, GFP_ATOMIC | __GFP_NOWARN, - tb->tb_sb); + buf = kmalloc(size, GFP_ATOMIC | __GFP_NOWARN); if (!buf) { /* getting memory with GFP_KERNEL priority may involve balancing now (due to indirect_to_direct conversion on dcache shrinking). So, release path and collected resources here */ free_buffers_in_tb(tb); - buf = reiserfs_kmalloc(size, GFP_NOFS, tb->tb_sb); + buf = kmalloc(size, GFP_NOFS); if (!buf) { -#ifdef CONFIG_REISERFS_CHECK - reiserfs_warning(tb->tb_sb, - "vs-8345: get_mem_for_virtual_node: " - "kmalloc failed. reiserfs kmalloced %d bytes", - REISERFS_SB(tb->tb_sb)-> - s_kmallocs); -#endif tb->vn_buf_size = 0; } tb->vn_buf = buf; @@ -2619,7 +2578,6 @@ void unfix_nodes(struct tree_balance *tb) } } - if (tb->vn_buf) - reiserfs_kfree(tb->vn_buf, tb->vn_buf_size, tb->tb_sb); + kfree(tb->vn_buf); } diff --git a/fs/reiserfs/hashes.c b/fs/reiserfs/hashes.c index a3ec238fd9e0..e664ac16fad9 100644 --- a/fs/reiserfs/hashes.c +++ b/fs/reiserfs/hashes.c @@ -21,7 +21,6 @@ #include <linux/kernel.h> #include <linux/reiserfs_fs.h> #include <asm/types.h> -#include <asm/bug.h> #define DELTA 0x9E3779B9 #define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */ diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index ffa34b861bdb..b33d67bba2fd 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -2363,6 +2363,13 @@ static int reiserfs_write_full_page(struct page *page, int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize; th.t_trans_id = 0; + /* no logging allowed when nonblocking or from PF_MEMALLOC */ + if (checked && (current->flags & PF_MEMALLOC)) { + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return 0; + } + /* The page dirty bit is cleared before writepage is called, which * means we have to tell create_empty_buffers to make dirty buffers * The page really should be up to date at this point, so tossing @@ -2743,6 +2750,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh) int ret = 1; struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); + lock_buffer(bh); spin_lock(&j->j_dirty_buffers_lock); if (!buffer_mapped(bh)) { goto free_jh; @@ -2758,7 +2766,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh) if (buffer_journaled(bh) || buffer_journal_dirty(bh)) { ret = 0; } - } else if (buffer_dirty(bh) || buffer_locked(bh)) { + } else if (buffer_dirty(bh)) { struct reiserfs_journal_list *jl; struct reiserfs_jh *jh = bh->b_private; @@ -2784,6 +2792,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh) reiserfs_free_jh(bh); } spin_unlock(&j->j_dirty_buffers_lock); + unlock_buffer(bh); return ret; } diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 4491fcf2a0e6..b7a179560ab4 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -152,18 +152,16 @@ static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block struct reiserfs_bitmap_node *bn; static int id; - bn = reiserfs_kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS, - p_s_sb); + bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS); if (!bn) { return NULL; } - bn->data = reiserfs_kmalloc(p_s_sb->s_blocksize, GFP_NOFS, p_s_sb); + bn->data = kzalloc(p_s_sb->s_blocksize, GFP_NOFS); if (!bn->data) { - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn); return NULL; } bn->id = id++; - memset(bn->data, 0, p_s_sb->s_blocksize); INIT_LIST_HEAD(&bn->list); return bn; } @@ -197,8 +195,8 @@ static inline void free_bitmap_node(struct super_block *p_s_sb, struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); journal->j_used_bitmap_nodes--; if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) { - reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb); - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn->data); + kfree(bn); } else { list_add(&bn->list, &journal->j_bitmap_nodes); journal->j_free_bitmap_nodes++; @@ -276,8 +274,8 @@ static int free_bitmap_nodes(struct super_block *p_s_sb) while (next != &journal->j_bitmap_nodes) { bn = list_entry(next, struct reiserfs_bitmap_node, list); list_del(next); - reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb); - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn->data); + kfree(bn); next = journal->j_bitmap_nodes.next; journal->j_free_bitmap_nodes--; } @@ -581,7 +579,7 @@ static inline void put_journal_list(struct super_block *s, jl->j_trans_id, jl->j_refcount); } if (--jl->j_refcount == 0) - reiserfs_kfree(jl, sizeof(struct reiserfs_journal_list), s); + kfree(jl); } /* @@ -848,6 +846,14 @@ static int write_ordered_buffers(spinlock_t * lock, spin_lock(lock); goto loop_next; } + /* in theory, dirty non-uptodate buffers should never get here, + * but the upper layer io error paths still have a few quirks. + * Handle them here as gracefully as we can + */ + if (!buffer_uptodate(bh) && buffer_dirty(bh)) { + clear_buffer_dirty(bh); + ret = -EIO; + } if (buffer_dirty(bh)) { list_del_init(&jh->list); list_add(&jh->list, &tmp); @@ -879,6 +885,19 @@ static int write_ordered_buffers(spinlock_t * lock, if (!buffer_uptodate(bh)) { ret = -EIO; } + /* ugly interaction with invalidatepage here. + * reiserfs_invalidate_page will pin any buffer that has a valid + * journal head from an older transaction. If someone else sets + * our buffer dirty after we write it in the first loop, and + * then someone truncates the page away, nobody will ever write + * the buffer. We're safe if we write the page one last time + * after freeing the journal header. + */ + if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) { + spin_unlock(lock); + ll_rw_block(WRITE, 1, &bh); + spin_lock(lock); + } put_bh(bh); cond_resched_lock(lock); } @@ -977,6 +996,7 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal *journal = SB_JOURNAL(s); int barrier = 0; int retval = 0; + int write_len; reiserfs_check_lock_depth(s, "flush_commit_list"); @@ -1018,24 +1038,35 @@ static int flush_commit_list(struct super_block *s, } if (!list_empty(&jl->j_bh_list)) { + int ret; unlock_kernel(); - write_ordered_buffers(&journal->j_dirty_buffers_lock, - journal, jl, &jl->j_bh_list); + ret = write_ordered_buffers(&journal->j_dirty_buffers_lock, + journal, jl, &jl->j_bh_list); + if (ret < 0 && retval == 0) + retval = ret; lock_kernel(); } BUG_ON(!list_empty(&jl->j_bh_list)); /* * for the description block and all the log blocks, submit any buffers - * that haven't already reached the disk + * that haven't already reached the disk. Try to write at least 256 + * log blocks. later on, we will only wait on blocks that correspond + * to this transaction, but while we're unplugging we might as well + * get a chunk of data on there. */ atomic_inc(&journal->j_async_throttle); - for (i = 0; i < (jl->j_len + 1); i++) { + write_len = jl->j_len + 1; + if (write_len < 256) + write_len = 256; + for (i = 0 ; i < write_len ; i++) { bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s); tbh = journal_find_get_block(s, bn); - if (buffer_dirty(tbh)) /* redundant, ll_rw_block() checks */ - ll_rw_block(SWRITE, 1, &tbh); - put_bh(tbh); + if (tbh) { + if (buffer_dirty(tbh)) + ll_rw_block(WRITE, 1, &tbh) ; + put_bh(tbh) ; + } } atomic_dec(&journal->j_async_throttle); @@ -1818,8 +1849,7 @@ void remove_journal_hash(struct super_block *sb, static void free_journal_ram(struct super_block *p_s_sb) { struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); - reiserfs_kfree(journal->j_current_jl, - sizeof(struct reiserfs_journal_list), p_s_sb); + kfree(journal->j_current_jl); journal->j_num_lists--; vfree(journal->j_cnode_free_orig); @@ -2093,21 +2123,15 @@ static int journal_read_transaction(struct super_block *p_s_sb, } trans_id = get_desc_trans_id(desc); /* now we know we've got a good transaction, and it was inside the valid time ranges */ - log_blocks = - reiserfs_kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS, p_s_sb); - real_blocks = - reiserfs_kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS, p_s_sb); + log_blocks = kmalloc(get_desc_trans_len(desc) * + sizeof(struct buffer_head *), GFP_NOFS); + real_blocks = kmalloc(get_desc_trans_len(desc) * + sizeof(struct buffer_head *), GFP_NOFS); if (!log_blocks || !real_blocks) { brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); reiserfs_warning(p_s_sb, "journal-1169: kmalloc failed, unable to mount FS"); return -1; @@ -2145,12 +2169,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, brelse_array(real_blocks, i); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } } @@ -2166,12 +2186,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, brelse_array(real_blocks, get_desc_trans_len(desc)); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data, @@ -2193,12 +2209,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, get_desc_trans_len(desc) - i); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } brelse(real_blocks[i]); @@ -2217,12 +2229,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, journal->j_trans_id = trans_id + 1; brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), - p_s_sb); - reiserfs_kfree(real_blocks, - le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), - p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return 0; } @@ -2471,14 +2479,8 @@ static int journal_read(struct super_block *p_s_sb) static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s) { struct reiserfs_journal_list *jl; - retry: - jl = reiserfs_kmalloc(sizeof(struct reiserfs_journal_list), GFP_NOFS, - s); - if (!jl) { - yield(); - goto retry; - } - memset(jl, 0, sizeof(*jl)); + jl = kzalloc(sizeof(struct reiserfs_journal_list), + GFP_NOFS | __GFP_NOFAIL); INIT_LIST_HEAD(&jl->j_list); INIT_LIST_HEAD(&jl->j_working_list); INIT_LIST_HEAD(&jl->j_tail_bh_list); @@ -2821,6 +2823,9 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th, journal->j_cnode_free < (journal->j_trans_max * 3)) { return 1; } + /* protected by the BKL here */ + journal->j_len_alloc += new_alloc; + th->t_blocks_allocated += new_alloc ; return 0; } @@ -3042,14 +3047,12 @@ struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct } return th; } - th = reiserfs_kmalloc(sizeof(struct reiserfs_transaction_handle), - GFP_NOFS, s); + th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS); if (!th) return NULL; ret = journal_begin(th, s, nblocks); if (ret) { - reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle), - s); + kfree(th); return NULL; } @@ -3067,8 +3070,7 @@ int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *th) ret = -EIO; if (th->t_refcount == 0) { SB_JOURNAL(s)->j_persistent_trans--; - reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle), - s); + kfree(th); } return ret; } diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 8f8d8d01107c..c8123308e060 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -456,7 +456,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, /* get memory for composing the entry */ buflen = DEH_SIZE + ROUND_UP(namelen); if (buflen > sizeof(small_buf)) { - buffer = reiserfs_kmalloc(buflen, GFP_NOFS, dir->i_sb); + buffer = kmalloc(buflen, GFP_NOFS); if (buffer == 0) return -ENOMEM; } else @@ -490,7 +490,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, retval = reiserfs_find_entry(dir, name, namelen, &path, &de); if (retval != NAME_NOT_FOUND) { if (buffer != small_buf) - reiserfs_kfree(buffer, buflen, dir->i_sb); + kfree(buffer); pathrelse(&path); if (retval == IO_ERROR) { @@ -515,7 +515,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, reiserfs_warning(dir->i_sb, "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); if (buffer != small_buf) - reiserfs_kfree(buffer, buflen, dir->i_sb); + kfree(buffer); pathrelse(&path); return -EBUSY; } @@ -535,7 +535,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, &entry_key); if (buffer != small_buf) - reiserfs_kfree(buffer, buflen, dir->i_sb); + kfree(buffer); pathrelse(&path); return -EBUSY; } @@ -546,7 +546,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer, paste_size); if (buffer != small_buf) - reiserfs_kfree(buffer, buflen, dir->i_sb); + kfree(buffer); if (retval) { reiserfs_check_path(&path); return retval; @@ -1065,7 +1065,7 @@ static int reiserfs_symlink(struct inode *parent_dir, goto out_failed; } - name = reiserfs_kmalloc(item_len, GFP_NOFS, parent_dir->i_sb); + name = kmalloc(item_len, GFP_NOFS); if (!name) { drop_new_inode(inode); retval = -ENOMEM; @@ -1079,14 +1079,14 @@ static int reiserfs_symlink(struct inode *parent_dir, retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); - reiserfs_kfree(name, item_len, parent_dir->i_sb); + kfree(name); goto out_failed; } retval = reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), dentry, inode); - reiserfs_kfree(name, item_len, parent_dir->i_sb); + kfree(name); if (retval) { /* reiserfs_new_inode iputs for us */ goto out_failed; } diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index fc2f43c75df4..ef6caed9336b 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -88,7 +88,6 @@ static int show_super(struct seq_file *m, struct super_block *sb) seq_printf(m, "state: \t%s\n" "mount options: \t%s%s%s%s%s%s%s%s%s%s%s\n" "gen. counter: \t%i\n" - "s_kmallocs: \t%i\n" "s_disk_reads: \t%i\n" "s_disk_writes: \t%i\n" "s_fix_nodes: \t%i\n" @@ -128,7 +127,7 @@ static int show_super(struct seq_file *m, struct super_block *sb) "SMALL_TAILS " : "NO_TAILS ", replay_only(sb) ? "REPLAY_ONLY " : "", convert_reiserfs(sb) ? "CONV " : "", - atomic_read(&r->s_generation_counter), SF(s_kmallocs), + atomic_read(&r->s_generation_counter), SF(s_disk_reads), SF(s_disk_writes), SF(s_fix_nodes), SF(s_do_balance), SF(s_unneeded_left_neighbor), SF(s_good_search_by_key_reada), SF(s_bmaps), diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 397d9590c8f2..d63da756eb49 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -472,12 +472,6 @@ static void reiserfs_put_super(struct super_block *s) print_statistics(s); - if (REISERFS_SB(s)->s_kmallocs != 0) { - reiserfs_warning(s, - "vs-2004: reiserfs_put_super: allocated memory left %d", - REISERFS_SB(s)->s_kmallocs); - } - if (REISERFS_SB(s)->reserved_blocks != 0) { reiserfs_warning(s, "green-2005: reiserfs_put_super: reserved blocks left %d", @@ -1130,8 +1124,6 @@ static void handle_attrs(struct super_block *s) "reiserfs: cannot support attributes until flag is set in super-block"); REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS); } - } else if (le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared) { - REISERFS_SB(s)->s_mount_opt |= REISERFS_ATTRS; } } diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index cc061bfd437b..ffb79c48c5bf 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -368,15 +368,13 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) if (d_reclen <= 32) { local_buf = small_buf; } else { - local_buf = - reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb); + local_buf = kmalloc(d_reclen, GFP_NOFS); if (!local_buf) { pathrelse(&path_to_entry); return -ENOMEM; } if (item_moved(&tmp_ih, &path_to_entry)) { - reiserfs_kfree(local_buf, d_reclen, - inode->i_sb); + kfree(local_buf); /* sigh, must retry. Do this same offset again */ next_pos = d_off; @@ -399,13 +397,12 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) if (filldir(dirent, local_buf, d_reclen, d_off, d_ino, DT_UNKNOWN) < 0) { if (local_buf != small_buf) { - reiserfs_kfree(local_buf, d_reclen, - inode->i_sb); + kfree(local_buf); } goto end; } if (local_buf != small_buf) { - reiserfs_kfree(local_buf, d_reclen, inode->i_sb); + kfree(local_buf); } } /* while */ @@ -1322,109 +1319,44 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) return err; } -static int -__reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd, - int need_lock) +static int reiserfs_check_acl(struct inode *inode, int mask) { - umode_t mode = inode->i_mode; - - if (mask & MAY_WRITE) { - /* - * Nobody gets write access to a read-only fs. - */ - if (IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; + struct posix_acl *acl; + int error = -EAGAIN; /* do regular unix permission checks by default */ - /* - * Nobody gets write access to an immutable file. - */ - if (IS_IMMUTABLE(inode)) - return -EACCES; - } + reiserfs_read_lock_xattr_i(inode); + reiserfs_read_lock_xattrs(inode->i_sb); - /* We don't do permission checks on the internal objects. - * Permissions are determined by the "owning" object. */ - if (is_reiserfs_priv_object(inode)) - return 0; + acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); - if (current->fsuid == inode->i_uid) { - mode >>= 6; -#ifdef CONFIG_REISERFS_FS_POSIX_ACL - } else if (reiserfs_posixacl(inode->i_sb) && - get_inode_sd_version(inode) != STAT_DATA_V1) { - struct posix_acl *acl; - - /* ACL can't contain additional permissions if - the ACL_MASK entry is 0 */ - if (!(mode & S_IRWXG)) - goto check_groups; - - if (need_lock) { - reiserfs_read_lock_xattr_i(inode); - reiserfs_read_lock_xattrs(inode->i_sb); - } - acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); - if (need_lock) { - reiserfs_read_unlock_xattrs(inode->i_sb); - reiserfs_read_unlock_xattr_i(inode); - } - if (IS_ERR(acl)) { - if (PTR_ERR(acl) == -ENODATA) - goto check_groups; - return PTR_ERR(acl); - } + reiserfs_read_unlock_xattrs(inode->i_sb); + reiserfs_read_unlock_xattr_i(inode); - if (acl) { - int err = posix_acl_permission(inode, acl, mask); + if (acl) { + if (!IS_ERR(acl)) { + error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); - if (err == -EACCES) { - goto check_capabilities; - } - return err; - } else { - goto check_groups; - } -#endif - } else { - check_groups: - if (in_group_p(inode->i_gid)) - mode >>= 3; + } else if (PTR_ERR(acl) != -ENODATA) + error = PTR_ERR(acl); } - /* - * If the DACs are ok we don't need any capability check. - */ - if (((mode & mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == mask)) - return 0; + return error; +} - check_capabilities: +int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd) +{ /* - * Read/write DACs are always overridable. - * Executable DACs are overridable if at least one exec bit is set. + * We don't do permission checks on the internal objects. + * Permissions are determined by the "owning" object. */ - if (!(mask & MAY_EXEC) || - (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode)) - if (capable(CAP_DAC_OVERRIDE)) - return 0; + if (is_reiserfs_priv_object(inode)) + return 0; /* - * Searching includes executable on directories, else just read. + * Stat data v1 doesn't support ACLs. */ - if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) - if (capable(CAP_DAC_READ_SEARCH)) - return 0; - - return -EACCES; -} - -int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd) -{ - return __reiserfs_permission(inode, mask, nd, 1); -} - -int -reiserfs_permission_locked(struct inode *inode, int mask, struct nameidata *nd) -{ - return __reiserfs_permission(inode, mask, nd, 0); + if (get_inode_sd_version(inode) == STAT_DATA_V1) + return generic_permission(inode, mask, NULL); + else + return generic_permission(inode, mask, reiserfs_check_acl); } diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 43de3ba83332..ab8894c3b9e5 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -228,7 +228,8 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); } else { acl = posix_acl_from_disk(value, retval); - *p_acl = posix_acl_dup(acl); + if (!IS_ERR(acl)) + *p_acl = posix_acl_dup(acl); } kfree(value); diff --git a/fs/select.c b/fs/select.c index f10a10317d54..6ce68a9c8976 100644 --- a/fs/select.c +++ b/fs/select.c @@ -179,12 +179,11 @@ get_max: #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) #define POLLEX_SET (POLLPRI) -int do_select(int n, fd_set_bits *fds, long *timeout) +int do_select(int n, fd_set_bits *fds, s64 *timeout) { struct poll_wqueues table; poll_table *wait; int retval, i; - long __timeout = *timeout; rcu_read_lock(); retval = max_select_fd(n, fds); @@ -196,11 +195,12 @@ int do_select(int n, fd_set_bits *fds, long *timeout) poll_initwait(&table); wait = &table.pt; - if (!__timeout) + if (!*timeout) wait = NULL; retval = 0; for (;;) { unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; + long __timeout; set_current_state(TASK_INTERRUPTIBLE); @@ -255,22 +255,32 @@ int do_select(int n, fd_set_bits *fds, long *timeout) *rexp = res_ex; } wait = NULL; - if (retval || !__timeout || signal_pending(current)) + if (retval || !*timeout || signal_pending(current)) break; if(table.error) { retval = table.error; break; } + + if (*timeout < 0) { + /* Wait indefinitely */ + __timeout = MAX_SCHEDULE_TIMEOUT; + } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT - 1)) { + /* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */ + __timeout = MAX_SCHEDULE_TIMEOUT - 1; + *timeout -= __timeout; + } else { + __timeout = *timeout; + *timeout = 0; + } __timeout = schedule_timeout(__timeout); + if (*timeout >= 0) + *timeout += __timeout; } __set_current_state(TASK_RUNNING); poll_freewait(&table); - /* - * Up-to-date the caller timeout. - */ - *timeout = __timeout; return retval; } @@ -295,36 +305,14 @@ static void select_bits_free(void *bits, int size) #define MAX_SELECT_SECONDS \ ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) -asmlinkage long -sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp) +static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, + fd_set __user *exp, s64 *timeout) { fd_set_bits fds; char *bits; - long timeout; int ret, size, max_fdset; struct fdtable *fdt; - timeout = MAX_SCHEDULE_TIMEOUT; - if (tvp) { - time_t sec, usec; - - if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp)) - || __get_user(sec, &tvp->tv_sec) - || __get_user(usec, &tvp->tv_usec)) { - ret = -EFAULT; - goto out_nofds; - } - - ret = -EINVAL; - if (sec < 0 || usec < 0) - goto out_nofds; - - if ((unsigned long) sec < MAX_SELECT_SECONDS) { - timeout = ROUND_UP(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; - } - } - ret = -EINVAL; if (n < 0) goto out_nofds; @@ -362,18 +350,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s zero_fd_set(n, fds.res_out); zero_fd_set(n, fds.res_ex); - ret = do_select(n, &fds, &timeout); - - if (tvp && !(current->personality & STICKY_TIMEOUTS)) { - time_t sec = 0, usec = 0; - if (timeout) { - sec = timeout / HZ; - usec = timeout % HZ; - usec *= (1000000/HZ); - } - put_user(sec, &tvp->tv_sec); - put_user(usec, &tvp->tv_usec); - } + ret = do_select(n, &fds, timeout); if (ret < 0) goto out; @@ -395,6 +372,163 @@ out_nofds: return ret; } +asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, + fd_set __user *exp, struct timeval __user *tvp) +{ + s64 timeout = -1; + struct timeval tv; + int ret; + + if (tvp) { + if (copy_from_user(&tv, tvp, sizeof(tv))) + return -EFAULT; + + if (tv.tv_sec < 0 || tv.tv_usec < 0) + return -EINVAL; + + /* Cast to u64 to make GCC stop complaining */ + if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS) + timeout = -1; /* infinite */ + else { + timeout = ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ); + timeout += tv.tv_sec * HZ; + } + } + + ret = core_sys_select(n, inp, outp, exp, &timeout); + + if (tvp) { + struct timeval rtv; + + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)); + rtv.tv_sec = timeout; + if (timeval_compare(&rtv, &tv) < 0) + rtv = tv; + if (copy_to_user(tvp, &rtv, sizeof(rtv))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND) + ret = -EINTR; + } + } + + return ret; +} + +#ifdef TIF_RESTORE_SIGMASK +asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp, + fd_set __user *exp, struct timespec __user *tsp, + const sigset_t __user *sigmask, size_t sigsetsize) +{ + s64 timeout = MAX_SCHEDULE_TIMEOUT; + sigset_t ksigmask, sigsaved; + struct timespec ts; + int ret; + + if (tsp) { + if (copy_from_user(&ts, tsp, sizeof(ts))) + return -EFAULT; + + if (ts.tv_sec < 0 || ts.tv_nsec < 0) + return -EINVAL; + + /* Cast to u64 to make GCC stop complaining */ + if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS) + timeout = -1; /* infinite */ + else { + timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ); + timeout += ts.tv_sec * HZ; + } + } + + if (sigmask) { + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask))) + return -EFAULT; + + sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + + ret = core_sys_select(n, inp, outp, exp, &timeout); + + if (tsp) { + struct timespec rts; + + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * + 1000; + rts.tv_sec = timeout; + if (timespec_compare(&rts, &ts) < 0) + rts = ts; + if (copy_to_user(tsp, &rts, sizeof(rts))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND) + ret = -EINTR; + } + } + + if (ret == -ERESTARTNOHAND) { + /* + * Don't restore the signal mask yet. Let do_signal() deliver + * the signal on the way back to userspace, before the signal + * mask is restored. + */ + if (sigmask) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } + } else if (sigmask) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + return ret; +} + +/* + * Most architectures can't handle 7-argument syscalls. So we provide a + * 6-argument version where the sixth argument is a pointer to a structure + * which has a pointer to the sigset_t itself followed by a size_t containing + * the sigset size. + */ +asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, + fd_set __user *exp, struct timespec __user *tsp, void __user *sig) +{ + size_t sigsetsize = 0; + sigset_t __user *up = NULL; + + if (sig) { + if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t)) + || __get_user(up, (sigset_t __user * __user *)sig) + || __get_user(sigsetsize, + (size_t __user *)(sig+sizeof(void *)))) + return -EFAULT; + } + + return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize); +} +#endif /* TIF_RESTORE_SIGMASK */ + struct poll_list { struct poll_list *next; int len; @@ -436,16 +570,19 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage, } static int do_poll(unsigned int nfds, struct poll_list *list, - struct poll_wqueues *wait, long timeout) + struct poll_wqueues *wait, s64 *timeout) { int count = 0; poll_table* pt = &wait->pt; - if (!timeout) + /* Optimise the no-wait case */ + if (!(*timeout)) pt = NULL; for (;;) { struct poll_list *walk; + long __timeout; + set_current_state(TASK_INTERRUPTIBLE); walk = list; while(walk != NULL) { @@ -453,18 +590,36 @@ static int do_poll(unsigned int nfds, struct poll_list *list, walk = walk->next; } pt = NULL; - if (count || !timeout || signal_pending(current)) + if (count || !*timeout || signal_pending(current)) break; count = wait->error; if (count) break; - timeout = schedule_timeout(timeout); + + if (*timeout < 0) { + /* Wait indefinitely */ + __timeout = MAX_SCHEDULE_TIMEOUT; + } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT-1)) { + /* + * Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in + * a loop + */ + __timeout = MAX_SCHEDULE_TIMEOUT - 1; + *timeout -= __timeout; + } else { + __timeout = *timeout; + *timeout = 0; + } + + __timeout = schedule_timeout(__timeout); + if (*timeout >= 0) + *timeout += __timeout; } __set_current_state(TASK_RUNNING); return count; } -asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout) +int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) { struct poll_wqueues table; int fdcount, err; @@ -482,14 +637,6 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti if (nfds > max_fdset && nfds > OPEN_MAX) return -EINVAL; - if (timeout) { - /* Careful about overflow in the intermediate values */ - if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ) - timeout = (unsigned long)(timeout*HZ+999)/1000+1; - else /* Negative or overflow */ - timeout = MAX_SCHEDULE_TIMEOUT; - } - poll_initwait(&table); head = NULL; @@ -519,6 +666,7 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti } i -= pp->len; } + fdcount = do_poll(nfds, head, &table, timeout); /* OK, now copy the revents fields back to user space. */ @@ -547,3 +695,103 @@ out_fds: poll_freewait(&table); return err; } + +asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, + long timeout_msecs) +{ + s64 timeout_jiffies = 0; + + if (timeout_msecs) { +#if HZ > 1000 + /* We can only overflow if HZ > 1000 */ + if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ) + timeout_jiffies = -1; + else +#endif + timeout_jiffies = msecs_to_jiffies(timeout_msecs); + } + + return do_sys_poll(ufds, nfds, &timeout_jiffies); +} + +#ifdef TIF_RESTORE_SIGMASK +asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, + struct timespec __user *tsp, const sigset_t __user *sigmask, + size_t sigsetsize) +{ + sigset_t ksigmask, sigsaved; + struct timespec ts; + s64 timeout = -1; + int ret; + + if (tsp) { + if (copy_from_user(&ts, tsp, sizeof(ts))) + return -EFAULT; + + /* Cast to u64 to make GCC stop complaining */ + if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS) + timeout = -1; /* infinite */ + else { + timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ); + timeout += ts.tv_sec * HZ; + } + } + + if (sigmask) { + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask))) + return -EFAULT; + + sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + + ret = do_sys_poll(ufds, nfds, &timeout); + + /* We can restart this syscall, usually */ + if (ret == -EINTR) { + /* + * Don't restore the signal mask yet. Let do_signal() deliver + * the signal on the way back to userspace, before the signal + * mask is restored. + */ + if (sigmask) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } + ret = -ERESTARTNOHAND; + } else if (sigmask) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + if (tsp && timeout >= 0) { + struct timespec rts; + + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + /* Yes, we know it's actually an s64, but it's also positive. */ + rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * + 1000; + rts.tv_sec = timeout; + if (timespec_compare(&rts, &ts) < 0) + rts = ts; + if (copy_to_user(tsp, &rts, sizeof(rts))) { + sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND && timeout >= 0) + ret = -EINTR; + } + } + + return ret; +} +#endif /* TIF_RESTORE_SIGMASK */ diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index c6c33e15143a..0424d06b147e 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -209,6 +209,8 @@ init_cache: ctl.valid = 1; read_really: result = server->ops->readdir(filp, dirent, filldir, &ctl); + if (result == -ERESTARTSYS && page) + ClearPageUptodate(page); if (ctl.idx == -1) goto invalid_cache; /* retry */ ctl.head.end = ctl.fpos - 1; @@ -217,7 +219,8 @@ finished: if (page) { cache->head = ctl.head; kunmap(page); - SetPageUptodate(page); + if (result != -ERESTARTSYS) + SetPageUptodate(page); unlock_page(page); page_cache_release(page); } diff --git a/fs/stat.c b/fs/stat.c index b8a0e5110ab2..9948cc1685a4 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -63,12 +63,12 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) EXPORT_SYMBOL(vfs_getattr); -int vfs_stat(char __user *name, struct kstat *stat) +int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk(name, &nd); + error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd); if (!error) { error = vfs_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); @@ -76,14 +76,19 @@ int vfs_stat(char __user *name, struct kstat *stat) return error; } +int vfs_stat(char __user *name, struct kstat *stat) +{ + return vfs_stat_fd(AT_FDCWD, name, stat); +} + EXPORT_SYMBOL(vfs_stat); -int vfs_lstat(char __user *name, struct kstat *stat) +int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk_link(name, &nd); + error = __user_walk_fd(dfd, name, 0, &nd); if (!error) { error = vfs_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); @@ -91,6 +96,11 @@ int vfs_lstat(char __user *name, struct kstat *stat) return error; } +int vfs_lstat(char __user *name, struct kstat *stat) +{ + return vfs_lstat_fd(AT_FDCWD, name, stat); +} + EXPORT_SYMBOL(vfs_lstat); int vfs_fstat(unsigned int fd, struct kstat *stat) @@ -151,7 +161,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf) { struct kstat stat; - int error = vfs_stat(filename, &stat); + int error = vfs_stat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_old_stat(&stat, statbuf); @@ -161,7 +171,7 @@ asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) { struct kstat stat; - int error = vfs_lstat(filename, &stat); + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_old_stat(&stat, statbuf); @@ -229,27 +239,52 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } -asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf) +asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf) { struct kstat stat; - int error = vfs_stat(filename, &stat); + int error = vfs_stat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_new_stat(&stat, statbuf); return error; } -asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf) + +asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf) { struct kstat stat; - int error = vfs_lstat(filename, &stat); + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); if (!error) error = cp_new_stat(&stat, statbuf); return error; } -asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf) + +#ifndef __ARCH_WANT_STAT64 +asmlinkage long sys_newfstatat(int dfd, char __user *filename, + struct stat __user *statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_new_stat(&stat, statbuf); + +out: + return error; +} +#endif + +asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf) { struct kstat stat; int error = vfs_fstat(fd, &stat); @@ -260,7 +295,8 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf) return error; } -asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz) +asmlinkage long sys_readlinkat(int dfd, const char __user *path, + char __user *buf, int bufsiz) { struct nameidata nd; int error; @@ -268,7 +304,7 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu if (bufsiz <= 0) return -EINVAL; - error = user_path_walk_link(path, &nd); + error = __user_walk_fd(dfd, path, 0, &nd); if (!error) { struct inode * inode = nd.dentry->d_inode; @@ -285,6 +321,12 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu return error; } +asmlinkage long sys_readlink(const char __user *path, char __user *buf, + int bufsiz) +{ + return sys_readlinkat(AT_FDCWD, path, buf, bufsiz); +} + /* ---------- LFS-64 ----------- */ #ifdef __ARCH_WANT_STAT64 @@ -355,6 +397,26 @@ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf) return error; } +asmlinkage long sys_fstatat64(int dfd, char __user *filename, + struct stat64 __user *statbuf, int flag) +{ + struct kstat stat; + int error = -EINVAL; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) + goto out; + + if (flag & AT_SYMLINK_NOFOLLOW) + error = vfs_lstat_fd(dfd, filename, &stat); + else + error = vfs_stat_fd(dfd, filename, &stat); + + if (!error) + error = cp_new_stat64(&stat, statbuf); + +out: + return error; +} #endif /* __ARCH_WANT_STAT64 */ void inode_add_bytes(struct inode *inode, loff_t bytes) diff --git a/fs/super.c b/fs/super.c index c177b92419c5..30294218fa63 100644 --- a/fs/super.c +++ b/fs/super.c @@ -247,8 +247,9 @@ void generic_shutdown_super(struct super_block *sb) /* Forget any remaining inodes */ if (invalidate_inodes(sb)) { - printk("VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Have a nice day...\n"); + printk("VFS: Busy inodes after unmount of %s. " + "Self-destruct in 5 seconds. Have a nice day...\n", + sb->s_id); } unlock_kernel(); diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 4fae57d9d115..201049ac8a96 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -579,10 +579,9 @@ static void udf_table_free_blocks(struct super_block * sb, { loffset = nextoffset; aed->lengthAllocDescs = cpu_to_le32(adsize); - if (obh) - sptr = UDF_I_DATA(inode) + nextoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize; - else - sptr = obh->b_data + nextoffset - adsize; + sptr = UDF_I_DATA(inode) + nextoffset - + udf_file_entry_alloc_offset(inode) + + UDF_I_LENEATTR(inode) - adsize; dptr = nbh->b_data + sizeof(struct allocExtDesc); memcpy(dptr, sptr, adsize); nextoffset = sizeof(struct allocExtDesc) + adsize; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index ca732e79c48b..ab9a7629d23e 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -296,7 +296,7 @@ static struct dentry * udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct inode *inode = NULL; - struct fileIdentDesc cfi, *fi; + struct fileIdentDesc cfi; struct udf_fileident_bh fibh; if (dentry->d_name.len > UDF_NAME_LEN-2) @@ -318,7 +318,7 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) else #endif /* UDF_RECOVERY */ - if ((fi = udf_find_entry(dir, dentry, &fibh, &cfi))) + if (udf_find_entry(dir, dentry, &fibh, &cfi)) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index e0c04e36a051..3c3f62ce2ad9 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -376,7 +376,7 @@ out: * This function gets the block which contains the fragment. */ -static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) +int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) { struct super_block * sb = inode->i_sb; struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; diff --git a/fs/ufs/super.c b/fs/ufs/super.c index d4aacee593ff..e9055ef7f5ac 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -388,7 +388,8 @@ static int ufs_parse_options (char * options, unsigned * mount_options) /* * Read on-disk structures associated with cylinder groups */ -static int ufs_read_cylinder_structures (struct super_block *sb) { +static int ufs_read_cylinder_structures (struct super_block *sb) +{ struct ufs_sb_info * sbi = UFS_SB(sb); struct ufs_sb_private_info * uspi; struct ufs_super_block *usb; @@ -415,6 +416,7 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { base = space = kmalloc(size, GFP_KERNEL); if (!base) goto failed; + sbi->s_csp = (struct ufs_csum *)space; for (i = 0; i < blks; i += uspi->s_fpb) { size = uspi->s_bsize; if (i + uspi->s_fpb > blks) @@ -430,7 +432,6 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { goto failed; ubh_ubhcpymem (space, ubh, size); - sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; space += size; ubh_brelse (ubh); @@ -486,7 +487,8 @@ failed: * Put on-disk structures associated with cylinder groups and * write them back to disk */ -static void ufs_put_cylinder_structures (struct super_block *sb) { +static void ufs_put_cylinder_structures (struct super_block *sb) +{ struct ufs_sb_info * sbi = UFS_SB(sb); struct ufs_sb_private_info * uspi; struct ufs_buffer_head * ubh; @@ -499,7 +501,7 @@ static void ufs_put_cylinder_structures (struct super_block *sb) { size = uspi->s_cssize; blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; - base = space = (char*) sbi->s_csp[0]; + base = space = (char*) sbi->s_csp; for (i = 0; i < blks; i += uspi->s_fpb) { size = uspi->s_bsize; if (i + uspi->s_fpb > blks) diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 61d2e35012a4..02e86291ef8a 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -29,6 +29,11 @@ * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr> */ +/* + * Modified to avoid infinite loop on 2006 by + * Evgeniy Dushistov <dushistov@mail.ru> + */ + #include <linux/errno.h> #include <linux/fs.h> #include <linux/ufs_fs.h> @@ -65,19 +70,16 @@ #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) -#define DATA_BUFFER_USED(bh) \ - (atomic_read(&bh->b_count)>1 || buffer_locked(bh)) static int ufs_trunc_direct (struct inode * inode) { struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block * sb; struct ufs_sb_private_info * uspi; - struct buffer_head * bh; __fs32 * p; unsigned frag1, frag2, frag3, frag4, block1, block2; unsigned frag_to_free, free_count; - unsigned i, j, tmp; + unsigned i, tmp; int retry; UFSD(("ENTER\n")) @@ -117,15 +119,7 @@ static int ufs_trunc_direct (struct inode * inode) ufs_panic (sb, "ufs_trunc_direct", "internal error"); frag1 = ufs_fragnum (frag1); frag2 = ufs_fragnum (frag2); - for (j = frag1; j < frag2; j++) { - bh = sb_find_get_block (sb, tmp + j); - if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { - retry = 1; - brelse (bh); - goto next1; - } - bforget (bh); - } + inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift; mark_inode_dirty(inode); ufs_free_fragments (inode, tmp + frag1, frag2 - frag1); @@ -140,15 +134,7 @@ next1: tmp = fs32_to_cpu(sb, *p); if (!tmp) continue; - for (j = 0; j < uspi->s_fpb; j++) { - bh = sb_find_get_block(sb, tmp + j); - if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { - retry = 1; - brelse (bh); - goto next2; - } - bforget (bh); - } + *p = 0; inode->i_blocks -= uspi->s_nspb; mark_inode_dirty(inode); @@ -162,7 +148,6 @@ next1: frag_to_free = tmp; free_count = uspi->s_fpb; } -next2:; } if (free_count > 0) @@ -179,15 +164,7 @@ next2:; if (!tmp ) ufs_panic(sb, "ufs_truncate_direct", "internal error"); frag4 = ufs_fragnum (frag4); - for (j = 0; j < frag4; j++) { - bh = sb_find_get_block (sb, tmp + j); - if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) { - retry = 1; - brelse (bh); - goto next1; - } - bforget (bh); - } + *p = 0; inode->i_blocks -= frag4 << uspi->s_nspfshift; mark_inode_dirty(inode); @@ -204,9 +181,8 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_buffer_head * ind_ubh; - struct buffer_head * bh; __fs32 * ind; - unsigned indirect_block, i, j, tmp; + unsigned indirect_block, i, tmp; unsigned frag_to_free, free_count; int retry; @@ -238,15 +214,7 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) tmp = fs32_to_cpu(sb, *ind); if (!tmp) continue; - for (j = 0; j < uspi->s_fpb; j++) { - bh = sb_find_get_block(sb, tmp + j); - if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *ind)) { - retry = 1; - brelse (bh); - goto next; - } - bforget (bh); - } + *ind = 0; ubh_mark_buffer_dirty(ind_ubh); if (free_count == 0) { @@ -261,7 +229,6 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) } inode->i_blocks -= uspi->s_nspb; mark_inode_dirty(inode); -next:; } if (free_count > 0) { @@ -430,9 +397,7 @@ void ufs_truncate (struct inode * inode) struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block * sb; struct ufs_sb_private_info * uspi; - struct buffer_head * bh; - unsigned offset; - int err, retry; + int retry; UFSD(("ENTER\n")) sb = inode->i_sb; @@ -442,6 +407,9 @@ void ufs_truncate (struct inode * inode) return; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; + + block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); + lock_kernel(); while (1) { retry = ufs_trunc_direct(inode); @@ -457,15 +425,7 @@ void ufs_truncate (struct inode * inode) blk_run_address_space(inode->i_mapping); yield(); } - offset = inode->i_size & uspi->s_fshift; - if (offset) { - bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err); - if (bh) { - memset (bh->b_data + offset, 0, uspi->s_fsize - offset); - mark_buffer_dirty (bh); - brelse (bh); - } - } + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; ufsi->i_lastfrag = DIRECT_FRAGMENT; unlock_kernel(); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 120626789406..8f2beec526cf 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -747,10 +747,11 @@ xfs_convert_page( struct backing_dev_info *bdi; bdi = inode->i_mapping->backing_dev_info; + wbc->nr_to_write--; if (bdi_write_congested(bdi)) { wbc->encountered_congestion = 1; done = 1; - } else if (--wbc->nr_to_write <= 0) { + } else if (wbc->nr_to_write <= 0) { done = 1; } } @@ -1462,4 +1463,5 @@ struct address_space_operations linvfs_aops = { .commit_write = generic_commit_write, .bmap = linvfs_bmap, .direct_IO = linvfs_direct_IO, + .migratepage = buffer_migrate_page, }; diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index e44b7c1a3a36..bfb4f2917bb6 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -822,6 +822,13 @@ xfs_buf_rele( XB_TRACE(bp, "rele", bp->b_relse); + if (unlikely(!hash)) { + ASSERT(!bp->b_relse); + if (atomic_dec_and_test(&bp->b_hold)) + xfs_buf_free(bp); + return; + } + if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) { if (bp->b_relse) { atomic_inc(&bp->b_hold); @@ -1514,6 +1521,7 @@ xfs_mapping_buftarg( struct address_space *mapping; static struct address_space_operations mapping_aops = { .sync_page = block_sync_page, + .migratepage = fail_migrate_page, }; inode = new_inode(bdev->bd_inode->i_sb); diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 76c6df34d0db..d7f6f2d8ac8e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -262,6 +262,31 @@ has_fs_struct(struct task_struct *task) return (task->fs != init_task.fs); } +STATIC inline void +cleanup_inode( + vnode_t *dvp, + vnode_t *vp, + struct dentry *dentry, + int mode) +{ + struct dentry teardown = {}; + int err2; + + /* Oh, the horror. + * If we can't add the ACL or we fail in + * linvfs_init_security we must back out. + * ENOSPC can hit here, among other things. + */ + teardown.d_inode = LINVFS_GET_IP(vp); + teardown.d_name = dentry->d_name; + + if (S_ISDIR(mode)) + VOP_RMDIR(dvp, &teardown, NULL, err2); + else + VOP_REMOVE(dvp, &teardown, NULL, err2); + VN_RELE(vp); +} + STATIC int linvfs_mknod( struct inode *dir, @@ -316,30 +341,19 @@ linvfs_mknod( } if (!error) + { error = linvfs_init_security(vp, dir); + if (error) + cleanup_inode(dvp, vp, dentry, mode); + } if (default_acl) { if (!error) { error = _ACL_INHERIT(vp, &va, default_acl); - if (!error) { + if (!error) VMODIFY(vp); - } else { - struct dentry teardown = {}; - int err2; - - /* Oh, the horror. - * If we can't add the ACL we must back out. - * ENOSPC can hit here, among other things. - */ - teardown.d_inode = ip = LINVFS_GET_IP(vp); - teardown.d_name = dentry->d_name; - - if (S_ISDIR(mode)) - VOP_RMDIR(dvp, &teardown, NULL, err2); - else - VOP_REMOVE(dvp, &teardown, NULL, err2); - VN_RELE(vp); - } + else + cleanup_inode(dvp, vp, dentry, mode); } _ACL_FREE(default_acl); } @@ -659,6 +673,8 @@ linvfs_setattr( if (ia_valid & ATTR_ATIME) { vattr.va_mask |= XFS_AT_ATIME; vattr.va_atime = attr->ia_atime; + if (ia_valid & ATTR_ATIME_SET) + inode->i_atime = attr->ia_atime; } if (ia_valid & ATTR_MTIME) { vattr.va_mask |= XFS_AT_MTIME; diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 427cff1a3f83..e27dc8f29972 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,9 +61,9 @@ * */ -/* Version string */ +/* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20050902 +#define ACPI_CA_VERSION 0x20060127 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -83,7 +83,7 @@ #define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */ /* - * Should the subystem abort the loading of an ACPI table if the + * Should the subsystem abort the loading of an ACPI table if the * table checksum is incorrect? */ #define ACPI_CHECKSUM_ABORT FALSE @@ -98,11 +98,6 @@ #define ACPI_CA_SUPPORT_LEVEL 3 -/* String size constants */ - -#define ACPI_MAX_STRING_LENGTH 512 -#define ACPI_PATHNAME_MAX 256 /* A full namespace pathname */ - /* Maximum count for a semaphore object */ #define ACPI_MAX_SEMAPHORE_COUNT 256 @@ -115,6 +110,10 @@ #define ACPI_SYSMEM_REGION_WINDOW_SIZE 4096 +/* owner_id tracking. 8 entries allows for 255 owner_ids */ + +#define ACPI_NUM_OWNERID_MASKS 8 + /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) @@ -134,14 +133,11 @@ #define ACPI_METHOD_NUM_ARGS 7 #define ACPI_METHOD_MAX_ARG 6 -/* Maximum length of resulting string when converting from a buffer */ - -#define ACPI_MAX_STRING_CONVERSION 200 - -/* Length of _HID, _UID, and _CID values */ +/* Length of _HID, _UID, _CID, and UUID values */ #define ACPI_DEVICE_ID_LENGTH 0x09 #define ACPI_MAX_CID_LENGTH 48 +#define ACPI_UUID_LENGTH 16 /* * Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h index 70ce3b4d006e..d8167095caf3 100644 --- a/include/acpi/acdebug.h +++ b/include/acpi/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 3d96dcb1bb4b..11a8fe39cb04 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,26 +57,11 @@ struct acpi_external_list { }; extern struct acpi_external_list *acpi_gbl_external_list; -extern const char *acpi_gbl_io_decode[2]; + +/* Strings used for decoding flags to ASL keywords */ + extern const char *acpi_gbl_word_decode[4]; -extern const char *acpi_gbl_consume_decode[2]; -extern const char *acpi_gbl_min_decode[2]; -extern const char *acpi_gbl_max_decode[2]; -extern const char *acpi_gbl_DECdecode[2]; -extern const char *acpi_gbl_RNGdecode[4]; -extern const char *acpi_gbl_MEMdecode[4]; -extern const char *acpi_gbl_RWdecode[2]; extern const char *acpi_gbl_irq_decode[2]; -extern const char *acpi_gbl_HEdecode[2]; -extern const char *acpi_gbl_LLdecode[2]; -extern const char *acpi_gbl_SHRdecode[2]; -extern const char *acpi_gbl_TYPdecode[4]; -extern const char *acpi_gbl_BMdecode[2]; -extern const char *acpi_gbl_SIZdecode[4]; -extern const char *acpi_gbl_TTPdecode[2]; -extern const char *acpi_gbl_MTPdecode[4]; -extern const char *acpi_gbl_TRSdecode[2]; - extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES]; extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES]; extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES]; @@ -171,11 +156,19 @@ u8 acpi_dm_is_string_buffer(union acpi_parse_object *op); /* * dmresrc */ +void acpi_dm_dump_integer8(u8 value, char *name); + +void acpi_dm_dump_integer16(u16 value, char *name); + +void acpi_dm_dump_integer32(u32 value, char *name); + +void acpi_dm_dump_integer64(u64 value, char *name); + void -acpi_dm_resource_descriptor(struct acpi_op_walk_info *info, - u8 * byte_data, u32 byte_count); +acpi_dm_resource_template(struct acpi_op_walk_info *info, + u8 * byte_data, u32 byte_count); -u8 acpi_dm_is_resource_descriptor(union acpi_parse_object *op); +u8 acpi_dm_is_resource_template(union acpi_parse_object *op); void acpi_dm_indent(u32 level); @@ -187,73 +180,69 @@ void acpi_dm_decode_attribute(u8 attribute); * dmresrcl */ void -acpi_dm_word_descriptor(struct asl_word_address_desc *resource, - u32 length, u32 level); +acpi_dm_word_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_dword_descriptor(struct asl_dword_address_desc *resource, - u32 length, u32 level); +acpi_dm_dword_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_extended_descriptor(struct asl_extended_address_desc *resource, +acpi_dm_extended_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_qword_descriptor(struct asl_qword_address_desc *resource, - u32 length, u32 level); +acpi_dm_qword_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_memory24_descriptor(struct asl_memory_24_desc *resource, +acpi_dm_memory24_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_memory32_descriptor(struct asl_memory_32_desc *resource, +acpi_dm_memory32_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_fixed_mem32_descriptor(struct asl_fixed_memory_32_desc *resource, - u32 length, u32 level); +acpi_dm_fixed_memory32_descriptor(union aml_resource *resource, + u32 length, u32 level); void -acpi_dm_generic_register_descriptor(struct asl_general_register_desc *resource, +acpi_dm_generic_register_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_interrupt_descriptor(struct asl_extended_xrupt_desc *resource, +acpi_dm_interrupt_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_vendor_large_descriptor(struct asl_large_vendor_desc *resource, +acpi_dm_vendor_large_descriptor(union aml_resource *resource, u32 length, u32 level); +void acpi_dm_vendor_common(char *name, u8 * byte_data, u32 length, u32 level); + /* * dmresrcs */ void -acpi_dm_irq_descriptor(struct asl_irq_format_desc *resource, - u32 length, u32 level); +acpi_dm_irq_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_dma_descriptor(struct asl_dma_format_desc *resource, - u32 length, u32 level); +acpi_dm_dma_descriptor(union aml_resource *resource, u32 length, u32 level); -void -acpi_dm_io_descriptor(struct asl_io_port_desc *resource, u32 length, u32 level); +void acpi_dm_io_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_fixed_io_descriptor(struct asl_fixed_io_port_desc *resource, +acpi_dm_fixed_io_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_start_dependent_descriptor(struct asl_start_dependent_desc *resource, +acpi_dm_start_dependent_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_end_dependent_descriptor(struct asl_start_dependent_desc *resource, +acpi_dm_end_dependent_descriptor(union aml_resource *resource, u32 length, u32 level); void -acpi_dm_vendor_small_descriptor(struct asl_small_vendor_desc *resource, +acpi_dm_vendor_small_descriptor(union aml_resource *resource, u32 length, u32 level); /* diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h index 065f24a77cfc..c41a926ff317 100644 --- a/include/acpi/acdispat.h +++ b/include/acpi/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -201,6 +201,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, union acpi_operand_object *obj_desc, struct acpi_namespace_node *calling_method_node); +acpi_status +acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state); + /* * dsinit */ diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h index bfa54600ecd9..f2717be4fe0d 100644 --- a/include/acpi/acevents.h +++ b/include/acpi/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,8 @@ acpi_status acpi_ev_initialize_events(void); acpi_status acpi_ev_install_xrupt_handlers(void); +acpi_status acpi_ev_install_fadt_gpes(void); + u32 acpi_ev_fixed_event_detect(void); /* @@ -105,6 +107,10 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block); +acpi_status +acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, + struct acpi_gpe_block_info *gpe_block); + acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); u32 diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 4f005eb65928..dc768aa580e4 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 4ab2ca18b8df..734cc77bf2c7 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,6 +80,15 @@ extern u32 acpi_dbg_layer; extern u32 acpi_gbl_nesting_level; +/* Support for dynamic control method tracing mechanism */ + +ACPI_EXTERN u32 acpi_gbl_original_dbg_level; +ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; +ACPI_EXTERN acpi_name acpi_gbl_trace_method_name; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; +ACPI_EXTERN u32 acpi_gbl_trace_flags; + /***************************************************************************** * * Runtime configuration (static defaults that can be overriden at runtime) @@ -89,11 +98,15 @@ extern u32 acpi_gbl_nesting_level; /* * Enable "slack" in the AML interpreter? Default is FALSE, and the * interpreter strictly follows the ACPI specification. Setting to TRUE - * allows the interpreter to forgive certain bad AML constructs. Currently: + * allows the interpreter to ignore certain errors and/or bad AML constructs. + * + * Currently, these features are enabled by this flag: + * * 1) Allow "implicit return" of last value in a control method - * 2) Allow access beyond end of operation region + * 2) Allow access beyond the end of an operation region * 3) Allow access to uninitialized locals/args (auto-init to integer 0) * 4) Allow ANY object type to be a source operand for the Store() operator + * 5) Allow unresolved references (invalid target name) in package objects */ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); @@ -211,9 +224,11 @@ ACPI_EXTERN u32 acpi_gbl_original_mode; ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; ACPI_EXTERN u32 acpi_gbl_ps_find_count; -ACPI_EXTERN u64 acpi_gbl_owner_id_mask; +ACPI_EXTERN u32 acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS]; ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; ACPI_EXTERN u16 acpi_gbl_global_lock_handle; +ACPI_EXTERN u8 acpi_gbl_last_owner_id_index; +ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset; ACPI_EXTERN u8 acpi_gbl_debugger_configuration; ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; ACPI_EXTERN u8 acpi_gbl_step_to_next_call; diff --git a/include/acpi/achware.h b/include/acpi/achware.h index 3644d7248e7e..29b60a8c0593 100644 --- a/include/acpi/achware.h +++ b/include/acpi/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h index 2c9c1a1d1b7f..9f22cfcb624b 100644 --- a/include/acpi/acinterp.h +++ b/include/acpi/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,49 @@ #ifndef __ACINTERP_H__ #define __ACINTERP_H__ -#define ACPI_WALK_OPERANDS (&(walk_state->operands [walk_state->num_operands -1])) +#define ACPI_WALK_OPERANDS (&(walk_state->operands [walk_state->num_operands -1])) + +/* Macros for tables used for debug output */ + +#define ACPI_EXD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_operand_object,f) +#define ACPI_EXD_NSOFFSET(f) (u8) ACPI_OFFSET (struct acpi_namespace_node,f) +#define ACPI_EXD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_exdump_info)) + +/* + * If possible, pack the following structure to byte alignment, since we + * don't care about performance for debug output + */ +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#pragma pack(1) +#endif + +typedef const struct acpi_exdump_info { + u8 opcode; + u8 offset; + char *name; + +} acpi_exdump_info; + +/* Values for the Opcode field above */ + +#define ACPI_EXD_INIT 0 +#define ACPI_EXD_TYPE 1 +#define ACPI_EXD_UINT8 2 +#define ACPI_EXD_UINT16 3 +#define ACPI_EXD_UINT32 4 +#define ACPI_EXD_UINT64 5 +#define ACPI_EXD_LITERAL 6 +#define ACPI_EXD_POINTER 7 +#define ACPI_EXD_ADDRESS 8 +#define ACPI_EXD_STRING 9 +#define ACPI_EXD_BUFFER 10 +#define ACPI_EXD_PACKAGE 11 +#define ACPI_EXD_FIELD 12 +#define ACPI_EXD_REFERENCE 13 + +/* restore default alignment */ + +#pragma pack() /* * exconvrt - object conversion @@ -327,7 +369,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, void acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags); -void acpi_ex_dump_node(struct acpi_namespace_node *node, u32 flags); +void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags); #endif /* ACPI_FUTURE_USAGE */ /* diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h index 9fba0fddda90..8361820d2970 100644 --- a/include/acpi/aclocal.h +++ b/include/acpi/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -276,6 +276,37 @@ struct acpi_create_field_info { u8 field_type; }; +/* + * Bitmapped ACPI types. Used internally only + */ +#define ACPI_BTYPE_ANY 0x00000000 +#define ACPI_BTYPE_INTEGER 0x00000001 +#define ACPI_BTYPE_STRING 0x00000002 +#define ACPI_BTYPE_BUFFER 0x00000004 +#define ACPI_BTYPE_PACKAGE 0x00000008 +#define ACPI_BTYPE_FIELD_UNIT 0x00000010 +#define ACPI_BTYPE_DEVICE 0x00000020 +#define ACPI_BTYPE_EVENT 0x00000040 +#define ACPI_BTYPE_METHOD 0x00000080 +#define ACPI_BTYPE_MUTEX 0x00000100 +#define ACPI_BTYPE_REGION 0x00000200 +#define ACPI_BTYPE_POWER 0x00000400 +#define ACPI_BTYPE_PROCESSOR 0x00000800 +#define ACPI_BTYPE_THERMAL 0x00001000 +#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 +#define ACPI_BTYPE_DDB_HANDLE 0x00004000 +#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 +#define ACPI_BTYPE_REFERENCE 0x00010000 +#define ACPI_BTYPE_RESOURCE 0x00020000 + +#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) + +#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) +#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) +#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ +#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF + /***************************************************************************** * * Event typedefs and structs @@ -385,13 +416,13 @@ struct acpi_field_info { #define ACPI_CONTROL_PREDICATE_FALSE 0xC3 #define ACPI_CONTROL_PREDICATE_TRUE 0xC4 -#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ - u8 data_type; /* To differentiate various internal objs */\ +#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ + u8 data_type; /* To differentiate various internal objs */\ u8 flags; \ u16 value; \ u16 state; \ u16 reserved; \ - void *next; \ + void *next; struct acpi_common_state { ACPI_STATE_COMMON}; @@ -544,8 +575,7 @@ union acpi_parse_value { char aml_op_name[16]) /* Op name (debug only) */\ /* NON-DEBUG members below: */\ struct acpi_namespace_node *node; /* For use by interpreter */\ - union acpi_parse_value value; /* Value or args associated with the opcode */\ - + union acpi_parse_value value; /* Value or args associated with the opcode */ #define ACPI_DASM_BUFFER 0x00 #define ACPI_DASM_RESOURCE 0x01 @@ -573,6 +603,8 @@ struct acpi_parse_obj_named { /* The parse node is the fundamental element of the parse tree */ +#define ACPI_MAX_PARSEOP_NAME 20 + struct acpi_parse_obj_asl { ACPI_PARSE_COMMON union acpi_parse_object *child; union acpi_parse_object *parent_method; @@ -597,7 +629,7 @@ struct acpi_parse_obj_asl { u8 aml_opcode_length; u8 aml_pkg_len_bytes; u8 extra; - char parse_op_name[12]; + char parse_op_name[ACPI_MAX_PARSEOP_NAME]; }; union acpi_parse_object { @@ -735,44 +767,52 @@ struct acpi_bit_register_info { /* resource_type values */ -#define ACPI_RESOURCE_TYPE_MEMORY_RANGE 0 -#define ACPI_RESOURCE_TYPE_IO_RANGE 1 -#define ACPI_RESOURCE_TYPE_BUS_NUMBER_RANGE 2 +#define ACPI_ADDRESS_TYPE_MEMORY_RANGE 0 +#define ACPI_ADDRESS_TYPE_IO_RANGE 1 +#define ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE 2 /* Resource descriptor types and masks */ -#define ACPI_RDESC_TYPE_LARGE 0x80 -#define ACPI_RDESC_TYPE_SMALL 0x00 +#define ACPI_RESOURCE_NAME_LARGE 0x80 +#define ACPI_RESOURCE_NAME_SMALL 0x00 -#define ACPI_RDESC_TYPE_MASK 0x80 -#define ACPI_RDESC_SMALL_MASK 0x78 /* Only bits 6:3 contain the type */ +#define ACPI_RESOURCE_NAME_SMALL_MASK 0x78 /* Bits 6:3 contain the type */ +#define ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK 0x07 /* Bits 2:0 contain the length */ +#define ACPI_RESOURCE_NAME_LARGE_MASK 0x7F /* Bits 6:0 contain the type */ /* - * Small resource descriptor types - * Note: The 3 length bits (2:0) must be zero + * Small resource descriptor "names" as defined by the ACPI specification. + * Note: Bits 2:0 are used for the descriptor length */ -#define ACPI_RDESC_TYPE_IRQ_FORMAT 0x20 -#define ACPI_RDESC_TYPE_DMA_FORMAT 0x28 -#define ACPI_RDESC_TYPE_START_DEPENDENT 0x30 -#define ACPI_RDESC_TYPE_END_DEPENDENT 0x38 -#define ACPI_RDESC_TYPE_IO_PORT 0x40 -#define ACPI_RDESC_TYPE_FIXED_IO_PORT 0x48 -#define ACPI_RDESC_TYPE_SMALL_VENDOR 0x70 -#define ACPI_RDESC_TYPE_END_TAG 0x78 +#define ACPI_RESOURCE_NAME_IRQ 0x20 +#define ACPI_RESOURCE_NAME_DMA 0x28 +#define ACPI_RESOURCE_NAME_START_DEPENDENT 0x30 +#define ACPI_RESOURCE_NAME_END_DEPENDENT 0x38 +#define ACPI_RESOURCE_NAME_IO 0x40 +#define ACPI_RESOURCE_NAME_FIXED_IO 0x48 +#define ACPI_RESOURCE_NAME_RESERVED_S1 0x50 +#define ACPI_RESOURCE_NAME_RESERVED_S2 0x58 +#define ACPI_RESOURCE_NAME_RESERVED_S3 0x60 +#define ACPI_RESOURCE_NAME_RESERVED_S4 0x68 +#define ACPI_RESOURCE_NAME_VENDOR_SMALL 0x70 +#define ACPI_RESOURCE_NAME_END_TAG 0x78 /* - * Large resource descriptor types + * Large resource descriptor "names" as defined by the ACPI specification. + * Note: includes the Large Descriptor bit in bit[7] */ -#define ACPI_RDESC_TYPE_MEMORY_24 0x81 -#define ACPI_RDESC_TYPE_GENERAL_REGISTER 0x82 -#define ACPI_RDESC_TYPE_LARGE_VENDOR 0x84 -#define ACPI_RDESC_TYPE_MEMORY_32 0x85 -#define ACPI_RDESC_TYPE_FIXED_MEMORY_32 0x86 -#define ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE 0x87 -#define ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE 0x88 -#define ACPI_RDESC_TYPE_EXTENDED_XRUPT 0x89 -#define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A -#define ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE 0x8B +#define ACPI_RESOURCE_NAME_MEMORY24 0x81 +#define ACPI_RESOURCE_NAME_GENERIC_REGISTER 0x82 +#define ACPI_RESOURCE_NAME_RESERVED_L1 0x83 +#define ACPI_RESOURCE_NAME_VENDOR_LARGE 0x84 +#define ACPI_RESOURCE_NAME_MEMORY32 0x85 +#define ACPI_RESOURCE_NAME_FIXED_MEMORY32 0x86 +#define ACPI_RESOURCE_NAME_ADDRESS32 0x87 +#define ACPI_RESOURCE_NAME_ADDRESS16 0x88 +#define ACPI_RESOURCE_NAME_EXTENDED_IRQ 0x89 +#define ACPI_RESOURCE_NAME_ADDRESS64 0x8A +#define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 0x8B +#define ACPI_RESOURCE_NAME_LARGE_MAX 0x8B /***************************************************************************** * @@ -780,7 +820,7 @@ struct acpi_bit_register_info { * ****************************************************************************/ -#define ACPI_ASCII_ZERO 0x30 +#define ACPI_ASCII_ZERO 0x30 /***************************************************************************** * diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 702cc4e57f5f..f2be2a881730 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,7 +60,7 @@ /* * For 16-bit addresses, we have to assume that the upper 32 bits - * are zero. + * (out of 64) are zero. */ #define ACPI_LODWORD(l) ((u32)(l)) #define ACPI_HIDWORD(l) ((u32)(0)) @@ -104,30 +104,38 @@ #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) /* - * Extract a byte of data using a pointer. Any more than a byte and we - * get into potential aligment issues -- see the STORE macros below + * Extract data using a pointer. Any more than a byte and we + * get into potential aligment issues -- see the STORE macros below. + * Use with care. */ -#define ACPI_GET8(addr) (*(u8*)(addr)) +#define ACPI_GET8(ptr) *ACPI_CAST_PTR (u8, ptr) +#define ACPI_GET16(ptr) *ACPI_CAST_PTR (u16, ptr) +#define ACPI_GET32(ptr) *ACPI_CAST_PTR (u32, ptr) +#define ACPI_GET64(ptr) *ACPI_CAST_PTR (u64, ptr) +#define ACPI_SET8(ptr) *ACPI_CAST_PTR (u8, ptr) +#define ACPI_SET16(ptr) *ACPI_CAST_PTR (u16, ptr) +#define ACPI_SET32(ptr) *ACPI_CAST_PTR (u32, ptr) +#define ACPI_SET64(ptr) *ACPI_CAST_PTR (u64, ptr) -/* Pointer arithmetic */ - -#define ACPI_PTR_ADD(t,a,b) (t *) (void *)((char *)(a) + (acpi_native_uint)(b)) -#define ACPI_PTR_DIFF(a,b) (acpi_native_uint) ((char *)(a) - (char *)(b)) +/* + * Pointer manipulation + */ +#define ACPI_CAST_PTR(t, p) ((t *) (acpi_uintptr_t) (p)) +#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (acpi_uintptr_t) (p)) +#define ACPI_ADD_PTR(t,a,b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8,(a)) + (acpi_native_uint)(b))) +#define ACPI_PTR_DIFF(a,b) (acpi_native_uint) (ACPI_CAST_PTR (u8,(a)) - ACPI_CAST_PTR (u8,(b))) /* Pointer/Integer type conversions */ -#define ACPI_TO_POINTER(i) ACPI_PTR_ADD (void, (void *) NULL,(acpi_native_uint)i) +#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL) #define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL) #define ACPI_FADT_OFFSET(f) ACPI_OFFSET (FADT_DESCRIPTOR, f) -#define ACPI_CAST_PTR(t, p) ((t *)(void *)(p)) -#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **)(void *)(p)) - #if ACPI_MACHINE_WIDTH == 16 #define ACPI_STORE_POINTER(d,s) ACPI_MOVE_32_TO_32(d,s) #define ACPI_PHYSADDR_TO_PTR(i) (void *)(i) -#define ACPI_PTR_TO_PHYSADDR(i) (u32) (char *)(i) +#define ACPI_PTR_TO_PHYSADDR(i) (u32) ACPI_CAST_PTR (u8,(i)) #else #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) @@ -202,7 +210,7 @@ #define ACPI_BUFFER_INDEX(buf_len,buf_offset,byte_gran) (buf_offset) -#ifdef ACPI_MISALIGNED_TRANSFERS +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED /* The hardware supports unaligned transfers, just do the little-endian move */ @@ -326,11 +334,19 @@ #define ACPI_MUL_16(a) _ACPI_MUL(a,4) #define ACPI_MOD_16(a) _ACPI_MOD(a,16) +#define ACPI_DIV_32(a) _ACPI_DIV(a,5) +#define ACPI_MUL_32(a) _ACPI_MUL(a,5) +#define ACPI_MOD_32(a) _ACPI_MOD(a,32) + /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & (~(((acpi_native_uint) boundary)-1))) -#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + (((acpi_native_uint) boundary)-1)) & (~(((acpi_native_uint) boundary)-1))) +#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \ + (~(((acpi_native_uint) boundary)-1))) + +#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \ + (((acpi_native_uint) boundary)-1)) & \ + (~(((acpi_native_uint) boundary)-1))) #define ACPI_ROUND_DOWN_TO_32_BITS(a) ACPI_ROUND_DOWN(a,4) #define ACPI_ROUND_DOWN_TO_64_BITS(a) ACPI_ROUND_DOWN(a,8) @@ -365,6 +381,14 @@ #define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask) #define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) +/* Generate a UUID */ + +#define ACPI_INIT_UUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ + (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \ + (b) & 0xFF, ((b) >> 8) & 0xFF, \ + (c) & 0xFF, ((c) >> 8) & 0xFF, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) + /* * An struct acpi_namespace_node * can appear in some contexts, * where a pointer to an union acpi_operand_object can also @@ -423,57 +447,52 @@ #define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F)) #define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH)) +#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) /* - * Reporting macros that are never compiled out + * Module name is include in both debug and non-debug versions primarily for + * error messages. The __FILE__ macro is not very useful for this, because it + * often includes the entire pathname to the module */ -#define ACPI_PARAM_LIST(pl) pl +#define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_acpi_module_name = name; +#else +#define ACPI_MODULE_NAME(name) +#endif /* - * Error reporting. These versions add callers module and line#. - * - * Since _acpi_module_name gets compiled out when ACPI_DEBUG_OUTPUT - * isn't defined, only use it in debug mode. + * Ascii error messages can be configured out */ -#ifdef ACPI_DEBUG_OUTPUT +#ifndef ACPI_NO_ERROR_MESSAGES +#define AE_INFO _acpi_module_name, __LINE__ -#define ACPI_REPORT_INFO(fp) {acpi_ut_report_info(_acpi_module_name,__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_ERROR(fp) {acpi_ut_report_error(_acpi_module_name,__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_WARNING(fp) {acpi_ut_report_warning(_acpi_module_name,__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_NSERROR(s,e) acpi_ns_report_error(_acpi_module_name,__LINE__,_COMPONENT, s, e); - -#define ACPI_REPORT_METHOD_ERROR(s,n,p,e) acpi_ns_report_method_error(_acpi_module_name,__LINE__,_COMPONENT, s, n, p, e); +/* + * Error reporting. Callers module and line number are inserted by AE_INFO, + * the plist contains a set of parens to allow variable-length lists. + * These macros are used for both the debug and non-debug versions of the code. + */ +#define ACPI_INFO(plist) acpi_ut_info plist +#define ACPI_WARNING(plist) acpi_ut_warning plist +#define ACPI_EXCEPTION(plist) acpi_ut_exception plist +#define ACPI_ERROR(plist) acpi_ut_error plist +#define ACPI_ERROR_NAMESPACE(s,e) acpi_ns_report_error (AE_INFO, s, e); +#define ACPI_ERROR_METHOD(s,n,p,e) acpi_ns_report_method_error (AE_INFO, s, n, p, e); #else -#define ACPI_REPORT_INFO(fp) {acpi_ut_report_info("ACPI",__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_ERROR(fp) {acpi_ut_report_error("ACPI",__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_WARNING(fp) {acpi_ut_report_warning("ACPI",__LINE__,_COMPONENT); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define ACPI_REPORT_NSERROR(s,e) acpi_ns_report_error("ACPI",__LINE__,_COMPONENT, s, e); +/* No error messages */ -#define ACPI_REPORT_METHOD_ERROR(s,n,p,e) acpi_ns_report_method_error("ACPI",__LINE__,_COMPONENT, s, n, p, e); +#define ACPI_INFO(plist) +#define ACPI_WARNING(plist) +#define ACPI_EXCEPTION(plist) +#define ACPI_ERROR(plist) +#define ACPI_ERROR_NAMESPACE(s,e) +#define ACPI_ERROR_METHOD(s,n,p,e) #endif -/* Error reporting. These versions pass thru the module and line# */ - -#define _ACPI_REPORT_INFO(a,b,c,fp) {acpi_ut_report_info(a,b,c); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define _ACPI_REPORT_ERROR(a,b,c,fp) {acpi_ut_report_error(a,b,c); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} -#define _ACPI_REPORT_WARNING(a,b,c,fp) {acpi_ut_report_warning(a,b,c); \ - acpi_os_printf ACPI_PARAM_LIST(fp);} - /* * Debug macros that are conditionally compiled */ #ifdef ACPI_DEBUG_OUTPUT -#define ACPI_MODULE_NAME(name) static char ACPI_UNUSED_VAR *_acpi_module_name = name; /* * Common parameters used for debug output functions: @@ -509,7 +528,7 @@ #endif #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(ACPI_DEBUG_PARAMETERS) + acpi_ut_trace(ACPI_DEBUG_PARAMETERS) #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b) #define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \ @@ -525,6 +544,9 @@ * bad form, but having a separate exit macro is very ugly and difficult to maintain. * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros * so that "_acpi_function_name" is defined. + * + * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining + * about these constructs. */ #ifdef ACPI_USE_DO_WHILE_0 #define ACPI_DO_WHILE0(a) do a while(0) @@ -532,10 +554,55 @@ #define ACPI_DO_WHILE0(a) a #endif -#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(ACPI_DEBUG_PARAMETERS);return;}) -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(ACPI_DEBUG_PARAMETERS,(s));return((s));}) -#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(ACPI_DEBUG_PARAMETERS,(acpi_integer)(s));return((s));}) -#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(ACPI_DEBUG_PARAMETERS,(u8 *)(s));return((s));}) +#define return_VOID ACPI_DO_WHILE0 ({ \ + acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \ + return;}) +/* + * There are two versions of most of the return macros. The default version is + * safer, since it avoids side-effects by guaranteeing that the argument will + * not be evaluated twice. + * + * A less-safe version of the macros is provided for optional use if the + * compiler uses excessive CPU stack (for example, this may happen in the + * debug case if code optimzation is disabled.) + */ +#ifndef ACPI_SIMPLE_RETURN_MACROS + +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ + register acpi_status _s = (s); \ + acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, _s); \ + return (_s); }) +#define return_PTR(s) ACPI_DO_WHILE0 ({ \ + register void *_s = (void *) (s); \ + acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) _s); \ + return (_s); }) +#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ + register acpi_integer _s = (s); \ + acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, _s); \ + return (_s); }) +#define return_UINT8(s) ACPI_DO_WHILE0 ({ \ + register u8 _s = (u8) (s); \ + acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) _s); \ + return (_s); }) +#define return_UINT32(s) ACPI_DO_WHILE0 ({ \ + register u32 _s = (u32) (s); \ + acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) _s); \ + return (_s); }) +#else /* Use original less-safe macros */ + +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ + acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, (s)); \ + return((s)); }) +#define return_PTR(s) ACPI_DO_WHILE0 ({ \ + acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) (s)); \ + return((s)); }) +#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ + acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (acpi_integer) (s)); \ + return((s)); }) +#define return_UINT8(s) return_VALUE(s) +#define return_UINT32(s) return_VALUE(s) + +#endif /* ACPI_SIMPLE_RETURN_MACROS */ /* Conditional execution */ @@ -555,18 +622,6 @@ #define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) #define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) #define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) -#define ACPI_BREAK_MSG(a) acpi_os_signal (ACPI_SIGNAL_BREAKPOINT,(a)) - -/* - * Generate INT3 on ACPI_ERROR (Debug only!) - */ -#define ACPI_ERROR_BREAK -#ifdef ACPI_ERROR_BREAK -#define ACPI_BREAK_ON_ERROR(lvl) if ((lvl)&ACPI_ERROR) \ - acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,"Fatal error encountered\n") -#else -#define ACPI_BREAK_ON_ERROR(lvl) -#endif /* * Master debug print macros @@ -574,17 +629,14 @@ * 1) Debug print for the current component is enabled * 2) Debug error level or trace level for the print statement is enabled */ -#define ACPI_DEBUG_PRINT(pl) acpi_ut_debug_print ACPI_PARAM_LIST(pl) -#define ACPI_DEBUG_PRINT_RAW(pl) acpi_ut_debug_print_raw ACPI_PARAM_LIST(pl) +#define ACPI_DEBUG_PRINT(plist) acpi_ut_debug_print plist +#define ACPI_DEBUG_PRINT_RAW(plist) acpi_ut_debug_print_raw plist #else /* * This is the non-debug case -- make everything go away, * leaving no executable debug code! */ -#define ACPI_MODULE_NAME(name) -#define _acpi_module_name "" - #define ACPI_DEBUG_EXEC(a) #define ACPI_NORMAL_EXEC(a) a; @@ -607,11 +659,12 @@ #define ACPI_DUMP_BUFFER(a,b) #define ACPI_DEBUG_PRINT(pl) #define ACPI_DEBUG_PRINT_RAW(pl) -#define ACPI_BREAK_MSG(a) #define return_VOID return #define return_ACPI_STATUS(s) return(s) #define return_VALUE(s) return(s) +#define return_UINT8(s) return(s) +#define return_UINT32(s) return(s) #define return_PTR(s) return(s) #endif diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 4f9063f3e951..b67da3636899 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h index dd3501f7e5d6..b667a804fc8a 100644 --- a/include/acpi/acnamesp.h +++ b/include/acpi/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -263,13 +263,11 @@ u32 acpi_ns_local(acpi_object_type type); void acpi_ns_report_error(char *module_name, u32 line_number, - u32 component_id, char *internal_name, acpi_status lookup_status); void acpi_ns_report_method_error(char *module_name, u32 line_number, - u32 component_id, char *message, struct acpi_namespace_node *node, char *path, acpi_status lookup_status); diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h index 4a326ba6d482..d130cfed8d55 100644 --- a/include/acpi/acobject.h +++ b/include/acpi/acobject.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,7 +69,7 @@ u8 type; /* acpi_object_type */\ u16 reference_count; /* For object deletion management */\ union acpi_operand_object *next_object; /* Objects linked to parent NS node */\ - u8 flags; \ + u8 flags; /* Values for flag byte above */ diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h index 64da42992199..e6d78bd9e90a 100644 --- a/include/acpi/acopcode.h +++ b/include/acpi/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 68d7edf0f697..7785d481dc3e 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -137,13 +137,19 @@ /* Exception level -- used in the global "debug_level" */ -#define ACPI_DB_ERROR ACPI_DEBUG_LEVEL (ACPI_LV_ERROR) -#define ACPI_DB_WARN ACPI_DEBUG_LEVEL (ACPI_LV_WARN) #define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) #define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) #define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) #define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) +/* + * These two levels are essentially obsolete, all instances in the + * ACPICA core code have been replaced by REPORT_ERROR and REPORT_WARNING + * (Kept here because some drivers may still use them) + */ +#define ACPI_DB_ERROR ACPI_DEBUG_LEVEL (ACPI_LV_ERROR) +#define ACPI_DB_WARN ACPI_DEBUG_LEVEL (ACPI_LV_WARN) + /* Trace level -- also used in the global "debug_level" */ #define ACPI_DB_INIT_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES) diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h index d352d40de1f3..5a1ff484af33 100644 --- a/include/acpi/acparser.h +++ b/include/acpi/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h index ccf34f9dac64..b9a39d1009bd 100644 --- a/include/acpi/acpi.h +++ b/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index c1b4e1f882e4..b425f9bb6d43 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -52,8 +52,8 @@ /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_irq_penalty_init(void); -int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *edge_level, - int *active_high_low, char **name); +int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, + int *polarity, char **name); int acpi_pci_link_free_irq(acpi_handle handle); /* ACPI PCI Interrupt Routing (pci_irq.c) */ diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 98e0b8cd14ed..970e9a6372c3 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -8,7 +8,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,9 +108,9 @@ acpi_status acpi_os_create_lock(acpi_handle * out_handle); void acpi_os_delete_lock(acpi_handle handle); -unsigned long acpi_os_acquire_lock(acpi_handle handle); +acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle); -void acpi_os_release_lock(acpi_handle handle, unsigned long flags); +void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags); /* * Memory allocation and mapping diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 2a9dbc13b0f2..66cf2ecef57a 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,6 +149,9 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler); acpi_status acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data); +acpi_status +acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags); + /* * Object manipulation and enumeration */ @@ -269,6 +272,12 @@ acpi_status(*ACPI_WALK_RESOURCE_CALLBACK) (struct acpi_resource * resource, void *context); acpi_status +acpi_get_vendor_resource(acpi_handle device_handle, + char *name, + struct acpi_vendor_uuid *uuid, + struct acpi_buffer *ret_buffer); + +acpi_status acpi_get_current_resources(acpi_handle device_handle, struct acpi_buffer *ret_buffer); @@ -280,7 +289,7 @@ acpi_get_possible_resources(acpi_handle device_handle, acpi_status acpi_walk_resources(acpi_handle device_handle, - char *path, + char *name, ACPI_WALK_RESOURCE_CALLBACK user_function, void *context); acpi_status diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h index 38e798b05d08..fa02e8083381 100644 --- a/include/acpi/acresrc.h +++ b/include/acpi/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,216 +44,284 @@ #ifndef __ACRESRC_H__ #define __ACRESRC_H__ -/* - * Function prototypes called from Acpi* APIs - */ -acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +/* Need the AML resource descriptor structs */ -acpi_status -acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +#include "amlresrc.h" -#ifdef ACPI_FUTURE_USAGE -acpi_status -acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); -#endif /* ACPI_FUTURE_USAGE */ - -acpi_status -acpi_rs_get_method_data(acpi_handle handle, - char *path, struct acpi_buffer *ret_buffer); +/* + * If possible, pack the following structures to byte alignment, since we + * don't care about performance for debug output + */ +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#pragma pack(1) +#endif -acpi_status -acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +/* + * Individual entry for the resource conversion tables + */ +typedef const struct acpi_rsconvert_info { + u8 opcode; + u8 resource_offset; + u8 aml_offset; + u8 value; + +} acpi_rsconvert_info; + +/* Resource conversion opcodes */ + +#define ACPI_RSC_INITGET 0 +#define ACPI_RSC_INITSET 1 +#define ACPI_RSC_FLAGINIT 2 +#define ACPI_RSC_1BITFLAG 3 +#define ACPI_RSC_2BITFLAG 4 +#define ACPI_RSC_COUNT 5 +#define ACPI_RSC_COUNT16 6 +#define ACPI_RSC_LENGTH 7 +#define ACPI_RSC_MOVE8 8 +#define ACPI_RSC_MOVE16 9 +#define ACPI_RSC_MOVE32 10 +#define ACPI_RSC_MOVE64 11 +#define ACPI_RSC_SET8 12 +#define ACPI_RSC_DATA8 13 +#define ACPI_RSC_ADDRESS 14 +#define ACPI_RSC_SOURCE 15 +#define ACPI_RSC_SOURCEX 16 +#define ACPI_RSC_BITMASK 17 +#define ACPI_RSC_BITMASK16 18 +#define ACPI_RSC_EXIT_NE 19 +#define ACPI_RSC_EXIT_LE 20 + +/* Resource Conversion sub-opcodes */ + +#define ACPI_RSC_COMPARE_AML_LENGTH 0 +#define ACPI_RSC_COMPARE_VALUE 1 + +#define ACPI_RSC_TABLE_SIZE(d) (sizeof (d) / sizeof (struct acpi_rsconvert_info)) + +#define ACPI_RS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_resource,f) +#define AML_OFFSET(f) (u8) ACPI_OFFSET (union aml_resource,f) + +typedef const struct acpi_rsdump_info { + u8 opcode; + u8 offset; + char *name; + const char **pointer; + +} acpi_rsdump_info; + +/* Values for the Opcode field above */ + +#define ACPI_RSD_TITLE 0 +#define ACPI_RSD_LITERAL 1 +#define ACPI_RSD_STRING 2 +#define ACPI_RSD_UINT8 3 +#define ACPI_RSD_UINT16 4 +#define ACPI_RSD_UINT32 5 +#define ACPI_RSD_UINT64 6 +#define ACPI_RSD_1BITFLAG 7 +#define ACPI_RSD_2BITFLAG 8 +#define ACPI_RSD_SHORTLIST 9 +#define ACPI_RSD_LONGLIST 10 +#define ACPI_RSD_DWORDLIST 11 +#define ACPI_RSD_ADDRESS 12 +#define ACPI_RSD_SOURCE 13 + +/* restore default alignment */ + +#pragma pack() + +/* Resource tables indexed by internal resource type */ + +extern const u8 acpi_gbl_aml_resource_sizes[]; +extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[]; + +/* Resource tables indexed by raw AML resource descriptor type */ + +extern const u8 acpi_gbl_resource_struct_sizes[]; +extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[]; + +struct acpi_vendor_walk_info { + struct acpi_vendor_uuid *uuid; + struct acpi_buffer *buffer; + acpi_status status; +}; +/* + * rscreate + */ acpi_status -acpi_rs_create_resource_list(union acpi_operand_object *byte_stream_buffer, +acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, struct acpi_buffer *output_buffer); acpi_status -acpi_rs_create_byte_stream(struct acpi_resource *linked_list_buffer, - struct acpi_buffer *output_buffer); +acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, + struct acpi_buffer *output_buffer); acpi_status acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, struct acpi_buffer *output_buffer); /* - * rsdump + * rsutils */ -#ifdef ACPI_FUTURE_USAGE -void acpi_rs_dump_resource_list(struct acpi_resource *resource); - -void acpi_rs_dump_irq_list(u8 * route_table); -#endif /* ACPI_FUTURE_USAGE */ - -/* - * rscalc - */ -acpi_status -acpi_rs_get_byte_stream_start(u8 * byte_stream_buffer, - u8 ** byte_stream_start, u32 * size); - -acpi_status -acpi_rs_get_list_length(u8 * byte_stream_buffer, - u32 byte_stream_buffer_length, acpi_size * size_needed); - -acpi_status -acpi_rs_get_byte_stream_length(struct acpi_resource *linked_list_buffer, - acpi_size * size_needed); - -acpi_status -acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, - acpi_size * buffer_size_needed); - -acpi_status -acpi_rs_byte_stream_to_list(u8 * byte_stream_buffer, - u32 byte_stream_buffer_length, u8 * output_buffer); - -acpi_status -acpi_rs_list_to_byte_stream(struct acpi_resource *linked_list, - acpi_size byte_stream_size_needed, - u8 * output_buffer); - -acpi_status -acpi_rs_io_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); - -acpi_status -acpi_rs_fixed_io_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); - acpi_status -acpi_rs_io_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); - -acpi_status -acpi_rs_fixed_io_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); - -acpi_status -acpi_rs_irq_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); - -acpi_status -acpi_rs_irq_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); - -acpi_status -acpi_rs_dma_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); acpi_status -acpi_rs_dma_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +#ifdef ACPI_FUTURE_USAGE acpi_status -acpi_rs_address16_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +#endif /* ACPI_FUTURE_USAGE */ acpi_status -acpi_rs_address16_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_get_method_data(acpi_handle handle, + char *path, struct acpi_buffer *ret_buffer); acpi_status -acpi_rs_address32_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer); +/* + * rscalc + */ acpi_status -acpi_rs_address32_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_get_list_length(u8 * aml_buffer, + u32 aml_buffer_length, acpi_size * size_needed); acpi_status -acpi_rs_address64_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer, + acpi_size * size_needed); acpi_status -acpi_rs_address64_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, + acpi_size * buffer_size_needed); acpi_status -acpi_rs_start_depend_fns_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, - acpi_size * structure_size); +acpi_rs_convert_aml_to_resources(u8 * aml_buffer, + u32 aml_buffer_length, u8 * output_buffer); acpi_status -acpi_rs_end_depend_fns_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, - acpi_size * structure_size); +acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, + acpi_size aml_size_needed, u8 * output_buffer); -acpi_status -acpi_rs_start_depend_fns_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, - acpi_size * bytes_consumed); +/* + * rsaddr + */ +void +acpi_rs_set_address_common(union aml_resource *aml, + struct acpi_resource *resource); -acpi_status -acpi_rs_end_depend_fns_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +u8 +acpi_rs_get_address_common(struct acpi_resource *resource, + union aml_resource *aml); +/* + * rsmisc + */ acpi_status -acpi_rs_memory24_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info); acpi_status -acpi_rs_memory24_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, + union aml_resource *aml, + struct acpi_rsconvert_info *info); -acpi_status -acpi_rs_memory32_range_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, - acpi_size * structure_size); +/* + * rsutils + */ +void +acpi_rs_move_data(void *destination, + void *source, u16 item_count, u8 move_type); -acpi_status -acpi_rs_fixed_memory32_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, - acpi_size * structure_size); +u8 acpi_rs_decode_bitmask(u16 mask, u8 * list); -acpi_status -acpi_rs_memory32_range_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +u16 acpi_rs_encode_bitmask(u8 * list, u8 count); -acpi_status -acpi_rs_fixed_memory32_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +acpi_rs_length +acpi_rs_get_resource_source(acpi_rs_length resource_length, + acpi_rs_length minimum_length, + struct acpi_resource_source *resource_source, + union aml_resource *aml, char *string_ptr); -acpi_status -acpi_rs_extended_irq_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +acpi_rsdesc_size +acpi_rs_set_resource_source(union aml_resource *aml, + acpi_rs_length minimum_length, + struct acpi_resource_source *resource_source); -acpi_status -acpi_rs_extended_irq_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +void +acpi_rs_set_resource_header(u8 descriptor_type, + acpi_rsdesc_size total_length, + union aml_resource *aml); -acpi_status -acpi_rs_end_tag_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +void +acpi_rs_set_resource_length(acpi_rsdesc_size total_length, + union aml_resource *aml); -acpi_status -acpi_rs_end_tag_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +/* + * rsdump + */ +void acpi_rs_dump_resource_list(struct acpi_resource *resource); -acpi_status -acpi_rs_vendor_resource(u8 * byte_stream_buffer, - acpi_size * bytes_consumed, - u8 ** output_buffer, acpi_size * structure_size); +void acpi_rs_dump_irq_list(u8 * route_table); -acpi_status -acpi_rs_vendor_stream(struct acpi_resource *linked_list, - u8 ** output_buffer, acpi_size * bytes_consumed); +/* + * Resource conversion tables + */ +extern struct acpi_rsconvert_info acpi_rs_convert_dma[]; +extern struct acpi_rsconvert_info acpi_rs_convert_end_dpf[]; +extern struct acpi_rsconvert_info acpi_rs_convert_io[]; +extern struct acpi_rsconvert_info acpi_rs_convert_fixed_io[]; +extern struct acpi_rsconvert_info acpi_rs_convert_end_tag[]; +extern struct acpi_rsconvert_info acpi_rs_convert_memory24[]; +extern struct acpi_rsconvert_info acpi_rs_convert_generic_reg[]; +extern struct acpi_rsconvert_info acpi_rs_convert_memory32[]; +extern struct acpi_rsconvert_info acpi_rs_convert_fixed_memory32[]; +extern struct acpi_rsconvert_info acpi_rs_convert_address32[]; +extern struct acpi_rsconvert_info acpi_rs_convert_address16[]; +extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[]; +extern struct acpi_rsconvert_info acpi_rs_convert_address64[]; +extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[]; + +/* These resources require separate get/set tables */ + +extern struct acpi_rsconvert_info acpi_rs_get_irq[]; +extern struct acpi_rsconvert_info acpi_rs_get_start_dpf[]; +extern struct acpi_rsconvert_info acpi_rs_get_vendor_small[]; +extern struct acpi_rsconvert_info acpi_rs_get_vendor_large[]; + +extern struct acpi_rsconvert_info acpi_rs_set_irq[]; +extern struct acpi_rsconvert_info acpi_rs_set_start_dpf[]; +extern struct acpi_rsconvert_info acpi_rs_set_vendor[]; + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * rsinfo + */ +extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[]; -u8 acpi_rs_get_resource_type(u8 resource_start_byte); +/* + * rsdump + */ +extern struct acpi_rsdump_info acpi_rs_dump_irq[]; +extern struct acpi_rsdump_info acpi_rs_dump_dma[]; +extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[]; +extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[]; +extern struct acpi_rsdump_info acpi_rs_dump_io[]; +extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[]; +extern struct acpi_rsdump_info acpi_rs_dump_vendor[]; +extern struct acpi_rsdump_info acpi_rs_dump_end_tag[]; +extern struct acpi_rsdump_info acpi_rs_dump_memory24[]; +extern struct acpi_rsdump_info acpi_rs_dump_memory32[]; +extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[]; +extern struct acpi_rsdump_info acpi_rs_dump_address16[]; +extern struct acpi_rsdump_info acpi_rs_dump_address32[]; +extern struct acpi_rsdump_info acpi_rs_dump_address64[]; +extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[]; +extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[]; +extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[]; +#endif #endif /* __ACRESRC_H__ */ diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h index 99d235339801..d8c1c2cdac0c 100644 --- a/include/acpi/acstruct.h +++ b/include/acpi/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actables.h b/include/acpi/actables.h index f92c1858b808..30a47542e1c8 100644 --- a/include/acpi/actables.h +++ b/include/acpi/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index a46f406e1c94..ed53f842dad4 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,12 @@ #define __ACTBL_H__ /* + * Note about bitfields: The u8 type is used for bitfields in ACPI tables. + * This is the only type that is even remotely portable. Anything else is not + * portable, so do not use any other bitfield types. + */ + +/* * Values for description table header signatures */ #define RSDP_NAME "RSDP" diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 67312c3a915a..cd428d57add0 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 50305ce2681a..dfc7ac1094bb 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 6213b27516e8..7ca89cde706e 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,15 @@ #ifndef __ACTYPES_H__ #define __ACTYPES_H__ -/*! [Begin] no source code translation (keep the typedefs) */ +/* + * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header + * and must be either 16, 32, or 64 + */ +#ifndef ACPI_MACHINE_WIDTH +#error ACPI_MACHINE_WIDTH not defined +#endif + +/*! [Begin] no source code translation */ /* * Data type ranges @@ -58,87 +66,150 @@ #define ACPI_UINT64_MAX (UINT64)(~((UINT64) 0)) /* 0xFFFFFFFFFFFFFFFF */ #define ACPI_ASCII_MAX 0x7F -#ifdef DEFINE_ALTERNATE_TYPES /* - * Types used only in translated source, defined here to enable - * cross-platform compilation only. + * Architecture-specific ACPICA Subsystem Data Types + * + * The goal of these types is to provide source code portability across + * 16-bit, 32-bit, and 64-bit targets. + * + * 1) The following types are of fixed size for all targets (16/32/64): + * + * BOOLEAN Logical boolean + * + * UINT8 8-bit (1 byte) unsigned value + * UINT16 16-bit (2 byte) unsigned value + * UINT32 32-bit (4 byte) unsigned value + * UINT64 64-bit (8 byte) unsigned value + * + * INT16 16-bit (2 byte) signed value + * INT32 32-bit (4 byte) signed value + * INT64 64-bit (8 byte) signed value + * + * COMPILER_DEPENDENT_UINT64/INT64 - These types are defined in the + * compiler-dependent header(s) and were introduced because there is no common + * 64-bit integer type across the various compilation models, as shown in + * the table below. + * + * Datatype LP64 ILP64 LLP64 ILP32 LP32 16bit + * char 8 8 8 8 8 8 + * short 16 16 16 16 16 16 + * _int32 32 + * int 32 64 32 32 16 16 + * long 64 64 32 32 32 32 + * long long 64 64 + * pointer 64 64 64 32 32 32 + * + * Note: ILP64 and LP32 are currently not supported. + * + * + * 2) These types represent the native word size of the target mode of the + * processor, and may be 16-bit, 32-bit, or 64-bit as required. They are + * usually used for memory allocation, efficient loop counters, and array + * indexes. The types are similar to the size_t type in the C library and are + * required because there is no C type that consistently represents the native + * data width. + * + * ACPI_SIZE 16/32/64-bit unsigned value + * ACPI_NATIVE_UINT 16/32/64-bit unsigned value + * ACPI_NATIVE_INT 16/32/64-bit signed value + * */ -typedef int s32; -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef COMPILER_DEPENDENT_UINT64 u64; - -#endif -/* - * Data types - Fixed across all compilation models (16/32/64) +/******************************************************************************* * - * BOOLEAN Logical Boolean. - * INT8 8-bit (1 byte) signed value - * UINT8 8-bit (1 byte) unsigned value - * INT16 16-bit (2 byte) signed value - * UINT16 16-bit (2 byte) unsigned value - * INT32 32-bit (4 byte) signed value - * UINT32 32-bit (4 byte) unsigned value - * INT64 64-bit (8 byte) signed value - * UINT64 64-bit (8 byte) unsigned value - * ACPI_NATIVE_INT 32-bit on IA-32, 64-bit on IA-64 signed value - * ACPI_NATIVE_UINT 32-bit on IA-32, 64-bit on IA-64 unsigned value - */ + * Common types for all compilers, all targets + * + ******************************************************************************/ -#ifndef ACPI_MACHINE_WIDTH -#error ACPI_MACHINE_WIDTH not defined -#endif +typedef unsigned char BOOLEAN; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef COMPILER_DEPENDENT_UINT64 UINT64; +typedef COMPILER_DEPENDENT_INT64 INT64; + +/*! [End] no source code translation !*/ + +/******************************************************************************* + * + * Types specific to 64-bit targets + * + ******************************************************************************/ #if ACPI_MACHINE_WIDTH == 64 -/*! [Begin] no source code translation (keep the typedefs) */ +/*! [Begin] no source code translation (keep the typedefs as-is) */ -/* - * 64-bit type definitions - */ -typedef unsigned char UINT8; -typedef unsigned char BOOLEAN; -typedef unsigned short UINT16; -typedef int INT32; typedef unsigned int UINT32; -typedef COMPILER_DEPENDENT_INT64 INT64; -typedef COMPILER_DEPENDENT_UINT64 UINT64; +typedef int INT32; /*! [End] no source code translation !*/ -typedef s64 acpi_native_int; typedef u64 acpi_native_uint; +typedef s64 acpi_native_int; typedef u64 acpi_table_ptr; typedef u64 acpi_io_address; typedef u64 acpi_physical_address; -typedef u64 acpi_size; -#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 /* No hardware alignment support in IA64 */ -#define ACPI_USE_NATIVE_DIVIDE /* Native 64-bit integer support */ #define ACPI_MAX_PTR ACPI_UINT64_MAX #define ACPI_SIZE_MAX ACPI_UINT64_MAX -#elif ACPI_MACHINE_WIDTH == 16 - -/*! [Begin] no source code translation (keep the typedefs) */ +#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 +#define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */ /* - * 16-bit type definitions + * In the case of the Itanium Processor Family (IPF), the hardware does not + * support misaligned memory transfers. Set the MISALIGNMENT_NOT_SUPPORTED flag + * to indicate that special precautions must be taken to avoid alignment faults. + * (IA64 or ia64 is currently used by existing compilers to indicate IPF.) + * + * Note: Em64_t and other X86-64 processors support misaligned transfers, + * so there is no need to define this flag. */ -typedef unsigned char UINT8; -typedef unsigned char BOOLEAN; -typedef unsigned int UINT16; -typedef long INT32; -typedef int INT16; -typedef unsigned long UINT32; +#if defined (__IA64__) || defined (__ia64__) +#define ACPI_MISALIGNMENT_NOT_SUPPORTED +#endif -struct { - UINT32 Lo; - UINT32 Hi; -}; +/******************************************************************************* + * + * Types specific to 32-bit targets + * + ******************************************************************************/ + +#elif ACPI_MACHINE_WIDTH == 32 + +/*! [Begin] no source code translation (keep the typedefs as-is) */ + +typedef unsigned int UINT32; +typedef int INT32; + +/*! [End] no source code translation !*/ + +typedef u32 acpi_native_uint; +typedef s32 acpi_native_int; + +typedef u64 acpi_table_ptr; +typedef u32 acpi_io_address; +typedef u64 acpi_physical_address; + +#define ACPI_MAX_PTR ACPI_UINT32_MAX +#define ACPI_SIZE_MAX ACPI_UINT32_MAX + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000004 + +/******************************************************************************* + * + * Types specific to 16-bit targets + * + ******************************************************************************/ + +#elif ACPI_MACHINE_WIDTH == 16 + +/*! [Begin] no source code translation (keep the typedefs as-is) */ + +typedef unsigned long UINT32; +typedef short INT16; +typedef long INT32; /*! [End] no source code translation !*/ @@ -148,61 +219,84 @@ typedef s16 acpi_native_int; typedef u32 acpi_table_ptr; typedef u32 acpi_io_address; typedef char *acpi_physical_address; -typedef u16 acpi_size; -#define ALIGNED_ADDRESS_BOUNDARY 0x00000002 -#define ACPI_MISALIGNED_TRANSFERS -#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */ #define ACPI_MAX_PTR ACPI_UINT16_MAX #define ACPI_SIZE_MAX ACPI_UINT16_MAX -/* - * (16-bit only) internal integers must be 32-bits, so - * 64-bit integers cannot be supported - */ +#define ALIGNED_ADDRESS_BOUNDARY 0x00000002 +#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */ + +/* 64-bit integers cannot be supported */ + #define ACPI_NO_INTEGER64_SUPPORT -#elif ACPI_MACHINE_WIDTH == 32 +#else -/*! [Begin] no source code translation (keep the typedefs) */ +/* ACPI_MACHINE_WIDTH must be either 64, 32, or 16 */ -/* - * 32-bit type definitions (default) - */ -typedef unsigned char UINT8; -typedef unsigned char BOOLEAN; -typedef unsigned short UINT16; -typedef int INT32; -typedef unsigned int UINT32; -typedef COMPILER_DEPENDENT_INT64 INT64; -typedef COMPILER_DEPENDENT_UINT64 UINT64; +#error unknown ACPI_MACHINE_WIDTH +#endif -/*! [End] no source code translation !*/ +/* Variable-width type, used instead of clib size_t */ -typedef s32 acpi_native_int; -typedef u32 acpi_native_uint; +typedef acpi_native_uint acpi_size; -typedef u64 acpi_table_ptr; -typedef u32 acpi_io_address; -typedef u64 acpi_physical_address; -typedef u32 acpi_size; +/******************************************************************************* + * + * OS- or compiler-dependent types + * + * If the defaults below are not appropriate for the host system, they can + * be defined in the compiler-specific or OS-specific header, and this will + * take precedence. + * + ******************************************************************************/ -#define ALIGNED_ADDRESS_BOUNDARY 0x00000004 -#define ACPI_MISALIGNED_TRANSFERS -#define ACPI_MAX_PTR ACPI_UINT32_MAX -#define ACPI_SIZE_MAX ACPI_UINT32_MAX +/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */ -#else -#error unknown ACPI_MACHINE_WIDTH +#ifndef acpi_uintptr_t +#define acpi_uintptr_t void * #endif /* - * This type is used for bitfields in ACPI tables. The only type that is - * even remotely portable is u8. Anything else is not portable, so - * do not add any more bitfield types. + * If acpi_cache_t was not defined in the OS-dependent header, + * define it now. This is typically the case where the local cache + * manager implementation is to be used (ACPI_USE_LOCAL_CACHE) + */ +#ifndef acpi_cache_t +#define acpi_cache_t struct acpi_memory_list +#endif + +/* + * Allow the CPU flags word to be defined per-OS to simplify the use of the + * lock and unlock OSL interfaces. + */ +#ifndef acpi_cpu_flags +#define acpi_cpu_flags acpi_native_uint +#endif + +/* + * ACPI_PRINTF_LIKE is used to tag functions as "printf-like" because + * some compilers can catch printf format string problems */ -typedef u8 UINT8_BIT; -typedef acpi_native_uint ACPI_PTRDIFF; +#ifndef ACPI_PRINTF_LIKE +#define ACPI_PRINTF_LIKE(c) +#endif + +/* + * Some compilers complain about unused variables. Sometimes we don't want to + * use all the variables (for example, _acpi_module_name). This allows us + * to to tell the compiler in a per-variable manner that a variable + * is unused + */ +#ifndef ACPI_UNUSED_VAR +#define ACPI_UNUSED_VAR +#endif + +/******************************************************************************* + * + * Independent types + * + ******************************************************************************/ /* * Pointer overlays to avoid lots of typecasting for @@ -234,18 +328,8 @@ struct acpi_pointer { #define ACPI_LOGMODE_PHYSPTR ACPI_LOGICAL_ADDRESSING | ACPI_PHYSICAL_POINTER #define ACPI_LOGMODE_LOGPTR ACPI_LOGICAL_ADDRESSING | ACPI_LOGICAL_POINTER -/* - * If acpi_cache_t was not defined in the OS-dependent header, - * define it now. This is typically the case where the local cache - * manager implementation is to be used (ACPI_USE_LOCAL_CACHE) - */ -#ifndef acpi_cache_t -#define acpi_cache_t struct acpi_memory_list -#endif +/* Logical defines and NULL */ -/* - * Useful defines - */ #ifdef FALSE #undef FALSE #endif @@ -261,12 +345,12 @@ struct acpi_pointer { #endif /* - * Local datatypes + * Mescellaneous types */ typedef u32 acpi_status; /* All ACPI Exceptions */ typedef u32 acpi_name; /* 4-byte ACPI name */ typedef char *acpi_string; /* Null terminated ASCII string */ -typedef void *acpi_handle; /* Actually a ptr to an Node */ +typedef void *acpi_handle; /* Actually a ptr to a NS Node */ struct uint64_struct { u32 lo; @@ -323,7 +407,7 @@ typedef u64 acpi_integer; /* * Constants with special meanings */ -#define ACPI_ROOT_OBJECT (acpi_handle) ACPI_PTR_ADD (char, NULL, ACPI_MAX_PTR) +#define ACPI_ROOT_OBJECT ACPI_ADD_PTR (acpi_handle, NULL, ACPI_MAX_PTR) /* * Initialization sequence @@ -470,37 +554,6 @@ typedef u32 acpi_object_type; #define ACPI_TYPE_NOT_FOUND 0xFF /* - * Bitmapped ACPI types. Used internally only - */ -#define ACPI_BTYPE_ANY 0x00000000 -#define ACPI_BTYPE_INTEGER 0x00000001 -#define ACPI_BTYPE_STRING 0x00000002 -#define ACPI_BTYPE_BUFFER 0x00000004 -#define ACPI_BTYPE_PACKAGE 0x00000008 -#define ACPI_BTYPE_FIELD_UNIT 0x00000010 -#define ACPI_BTYPE_DEVICE 0x00000020 -#define ACPI_BTYPE_EVENT 0x00000040 -#define ACPI_BTYPE_METHOD 0x00000080 -#define ACPI_BTYPE_MUTEX 0x00000100 -#define ACPI_BTYPE_REGION 0x00000200 -#define ACPI_BTYPE_POWER 0x00000400 -#define ACPI_BTYPE_PROCESSOR 0x00000800 -#define ACPI_BTYPE_THERMAL 0x00001000 -#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 -#define ACPI_BTYPE_DDB_HANDLE 0x00004000 -#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 -#define ACPI_BTYPE_REFERENCE 0x00010000 -#define ACPI_BTYPE_RESOURCE 0x00020000 - -#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) - -#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) -#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) -#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) -#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ -#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF - -/* * All I/O */ #define ACPI_READ 0 @@ -853,6 +906,14 @@ struct acpi_compatible_id_list { #define ACPI_VALID_CID 0x0010 #define ACPI_VALID_SXDS 0x0020 +/* Flags for _STA method */ + +#define ACPI_STA_DEVICE_PRESENT 0x01 +#define ACPI_STA_DEVICE_ENABLED 0x02 +#define ACPI_STA_DEVICE_UI 0x04 +#define ACPI_STA_DEVICE_OK 0x08 +#define ACPI_STA_BATTERY_PRESENT 0x10 + #define ACPI_COMMON_OBJ_INFO \ acpi_object_type type; /* ACPI object type */ \ acpi_name name /* ACPI object Name */ @@ -895,6 +956,8 @@ struct acpi_mem_space_context { /* * Definitions for Resource Attributes */ +typedef u16 acpi_rs_length; /* Resource Length field is fixed at 16 bits */ +typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (length+3) = (64_k-1)+3 */ /* * Memory Attributes @@ -916,7 +979,9 @@ struct acpi_mem_space_context { #define ACPI_ISA_ONLY_RANGES (u8) 0x02 #define ACPI_ENTIRE_RANGE (ACPI_NON_ISA_ONLY_RANGES | ACPI_ISA_ONLY_RANGES) -#define ACPI_SPARSE_TRANSLATION (u8) 0x03 +/* Type of translation - 1=Sparse, 0=Dense */ + +#define ACPI_SPARSE_TRANSLATION (u8) 0x01 /* * IO Port Descriptor Decode @@ -927,8 +992,8 @@ struct acpi_mem_space_context { /* * IRQ Attributes */ -#define ACPI_EDGE_SENSITIVE (u8) 0x00 -#define ACPI_LEVEL_SENSITIVE (u8) 0x01 +#define ACPI_LEVEL_SENSITIVE (u8) 0x00 +#define ACPI_EDGE_SENSITIVE (u8) 0x01 #define ACPI_ACTIVE_HIGH (u8) 0x00 #define ACPI_ACTIVE_LOW (u8) 0x01 @@ -975,27 +1040,45 @@ struct acpi_mem_space_context { #define ACPI_CONSUMER (u8) 0x01 /* + * If possible, pack the following structures to byte alignment + */ +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#pragma pack(1) +#endif + +/* UUID data structures for use in vendor-defined resource descriptors */ + +struct acpi_uuid { + u8 data[ACPI_UUID_LENGTH]; +}; + +struct acpi_vendor_uuid { + u8 subtype; + u8 data[ACPI_UUID_LENGTH]; +}; + +/* * Structures used to describe device resources */ struct acpi_resource_irq { - u32 edge_level; - u32 active_high_low; - u32 shared_exclusive; - u32 number_of_interrupts; - u32 interrupts[1]; + u8 triggering; + u8 polarity; + u8 sharable; + u8 interrupt_count; + u8 interrupts[1]; }; struct acpi_resource_dma { - u32 type; - u32 bus_master; - u32 transfer; - u32 number_of_channels; - u32 channels[1]; + u8 type; + u8 bus_master; + u8 transfer; + u8 channel_count; + u8 channels[1]; }; -struct acpi_resource_start_dpf { - u32 compatibility_priority; - u32 performance_robustness; +struct acpi_resource_start_dependent { + u8 compatibility_priority; + u8 performance_robustness; }; /* @@ -1004,179 +1087,217 @@ struct acpi_resource_start_dpf { */ struct acpi_resource_io { - u32 io_decode; - u32 min_base_address; - u32 max_base_address; - u32 alignment; - u32 range_length; + u8 io_decode; + u8 alignment; + u8 address_length; + u16 minimum; + u16 maximum; }; struct acpi_resource_fixed_io { - u32 base_address; - u32 range_length; + u16 address; + u8 address_length; }; struct acpi_resource_vendor { - u32 length; - u8 reserved[1]; + u16 byte_length; + u8 byte_data[1]; +}; + +/* Vendor resource with UUID info (introduced in ACPI 3.0) */ + +struct acpi_resource_vendor_typed { + u16 byte_length; + u8 uuid_subtype; + u8 uuid[ACPI_UUID_LENGTH]; + u8 byte_data[1]; }; struct acpi_resource_end_tag { u8 checksum; }; -struct acpi_resource_mem24 { - u32 read_write_attribute; - u32 min_base_address; - u32 max_base_address; - u32 alignment; - u32 range_length; +struct acpi_resource_memory24 { + u8 write_protect; + u16 minimum; + u16 maximum; + u16 alignment; + u16 address_length; }; -struct acpi_resource_mem32 { - u32 read_write_attribute; - u32 min_base_address; - u32 max_base_address; +struct acpi_resource_memory32 { + u8 write_protect; + u32 minimum; + u32 maximum; u32 alignment; - u32 range_length; + u32 address_length; }; -struct acpi_resource_fixed_mem32 { - u32 read_write_attribute; - u32 range_base_address; - u32 range_length; +struct acpi_resource_fixed_memory32 { + u8 write_protect; + u32 address; + u32 address_length; }; struct acpi_memory_attribute { - u16 cache_attribute; - u16 read_write_attribute; + u8 write_protect; + u8 caching; + u8 range_type; + u8 translation; }; struct acpi_io_attribute { - u16 range_attribute; - u16 translation_attribute; -}; - -struct acpi_bus_attribute { - u16 reserved1; - u16 reserved2; + u8 range_type; + u8 translation; + u8 translation_type; + u8 reserved1; }; union acpi_resource_attribute { - struct acpi_memory_attribute memory; + struct acpi_memory_attribute mem; struct acpi_io_attribute io; - struct acpi_bus_attribute bus; + + /* Used for the *word_space macros */ + + u8 type_specific; }; struct acpi_resource_source { - u32 index; - u32 string_length; + u8 index; + u16 string_length; char *string_ptr; }; /* Fields common to all address descriptors, 16/32/64 bit */ #define ACPI_RESOURCE_ADDRESS_COMMON \ - u32 resource_type; \ - u32 producer_consumer; \ - u32 decode; \ - u32 min_address_fixed; \ - u32 max_address_fixed; \ - union acpi_resource_attribute attribute; + u8 resource_type; \ + u8 producer_consumer; \ + u8 decode; \ + u8 min_address_fixed; \ + u8 max_address_fixed; \ + union acpi_resource_attribute info; struct acpi_resource_address { ACPI_RESOURCE_ADDRESS_COMMON}; struct acpi_resource_address16 { - ACPI_RESOURCE_ADDRESS_COMMON u32 granularity; - u32 min_address_range; - u32 max_address_range; - u32 address_translation_offset; - u32 address_length; + ACPI_RESOURCE_ADDRESS_COMMON u16 granularity; + u16 minimum; + u16 maximum; + u16 translation_offset; + u16 address_length; struct acpi_resource_source resource_source; }; struct acpi_resource_address32 { ACPI_RESOURCE_ADDRESS_COMMON u32 granularity; - u32 min_address_range; - u32 max_address_range; - u32 address_translation_offset; + u32 minimum; + u32 maximum; + u32 translation_offset; u32 address_length; struct acpi_resource_source resource_source; }; struct acpi_resource_address64 { ACPI_RESOURCE_ADDRESS_COMMON u64 granularity; - u64 min_address_range; - u64 max_address_range; - u64 address_translation_offset; + u64 minimum; + u64 maximum; + u64 translation_offset; u64 address_length; - u64 type_specific_attributes; struct acpi_resource_source resource_source; }; -struct acpi_resource_ext_irq { - u32 producer_consumer; - u32 edge_level; - u32 active_high_low; - u32 shared_exclusive; - u32 number_of_interrupts; +struct acpi_resource_extended_address64 { + ACPI_RESOURCE_ADDRESS_COMMON u8 revision_iD; + u64 granularity; + u64 minimum; + u64 maximum; + u64 translation_offset; + u64 address_length; + u64 type_specific; +}; + +struct acpi_resource_extended_irq { + u8 producer_consumer; + u8 triggering; + u8 polarity; + u8 sharable; + u8 interrupt_count; struct acpi_resource_source resource_source; u32 interrupts[1]; }; +struct acpi_resource_generic_register { + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 access_size; + u64 address; +}; + /* ACPI_RESOURCE_TYPEs */ -#define ACPI_RSTYPE_IRQ 0 -#define ACPI_RSTYPE_DMA 1 -#define ACPI_RSTYPE_START_DPF 2 -#define ACPI_RSTYPE_END_DPF 3 -#define ACPI_RSTYPE_IO 4 -#define ACPI_RSTYPE_FIXED_IO 5 -#define ACPI_RSTYPE_VENDOR 6 -#define ACPI_RSTYPE_END_TAG 7 -#define ACPI_RSTYPE_MEM24 8 -#define ACPI_RSTYPE_MEM32 9 -#define ACPI_RSTYPE_FIXED_MEM32 10 -#define ACPI_RSTYPE_ADDRESS16 11 -#define ACPI_RSTYPE_ADDRESS32 12 -#define ACPI_RSTYPE_ADDRESS64 13 -#define ACPI_RSTYPE_EXT_IRQ 14 - -typedef u32 acpi_resource_type; +#define ACPI_RESOURCE_TYPE_IRQ 0 +#define ACPI_RESOURCE_TYPE_DMA 1 +#define ACPI_RESOURCE_TYPE_START_DEPENDENT 2 +#define ACPI_RESOURCE_TYPE_END_DEPENDENT 3 +#define ACPI_RESOURCE_TYPE_IO 4 +#define ACPI_RESOURCE_TYPE_FIXED_IO 5 +#define ACPI_RESOURCE_TYPE_VENDOR 6 +#define ACPI_RESOURCE_TYPE_END_TAG 7 +#define ACPI_RESOURCE_TYPE_MEMORY24 8 +#define ACPI_RESOURCE_TYPE_MEMORY32 9 +#define ACPI_RESOURCE_TYPE_FIXED_MEMORY32 10 +#define ACPI_RESOURCE_TYPE_ADDRESS16 11 +#define ACPI_RESOURCE_TYPE_ADDRESS32 12 +#define ACPI_RESOURCE_TYPE_ADDRESS64 13 +#define ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 14 /* ACPI 3.0 */ +#define ACPI_RESOURCE_TYPE_EXTENDED_IRQ 15 +#define ACPI_RESOURCE_TYPE_GENERIC_REGISTER 16 +#define ACPI_RESOURCE_TYPE_MAX 16 union acpi_resource_data { struct acpi_resource_irq irq; struct acpi_resource_dma dma; - struct acpi_resource_start_dpf start_dpf; + struct acpi_resource_start_dependent start_dpf; struct acpi_resource_io io; struct acpi_resource_fixed_io fixed_io; - struct acpi_resource_vendor vendor_specific; + struct acpi_resource_vendor vendor; + struct acpi_resource_vendor_typed vendor_typed; struct acpi_resource_end_tag end_tag; - struct acpi_resource_mem24 memory24; - struct acpi_resource_mem32 memory32; - struct acpi_resource_fixed_mem32 fixed_memory32; - struct acpi_resource_address address; /* Common 16/32/64 address fields */ + struct acpi_resource_memory24 memory24; + struct acpi_resource_memory32 memory32; + struct acpi_resource_fixed_memory32 fixed_memory32; struct acpi_resource_address16 address16; struct acpi_resource_address32 address32; struct acpi_resource_address64 address64; - struct acpi_resource_ext_irq extended_irq; + struct acpi_resource_extended_address64 ext_address64; + struct acpi_resource_extended_irq extended_irq; + struct acpi_resource_generic_register generic_reg; + + /* Common fields */ + + struct acpi_resource_address address; /* Common 16/32/64 address fields */ }; struct acpi_resource { - acpi_resource_type id; + u32 type; u32 length; union acpi_resource_data data; }; -#define ACPI_RESOURCE_LENGTH 12 -#define ACPI_RESOURCE_LENGTH_NO_DATA 8 /* Id + Length fields */ +/* restore default alignment */ + +#pragma pack() -#define ACPI_SIZEOF_RESOURCE(type) (ACPI_RESOURCE_LENGTH_NO_DATA + sizeof (type)) +#define ACPI_RS_SIZE_MIN 12 +#define ACPI_RS_SIZE_NO_DATA 8 /* Id + Length fields */ +#define ACPI_RS_SIZE(type) (u32) (ACPI_RS_SIZE_NO_DATA + sizeof (type)) #define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length) -#ifdef ACPI_MISALIGNED_TRANSFERS +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED #define ACPI_ALIGN_RESOURCE_SIZE(length) (length) #else #define ACPI_ALIGN_RESOURCE_SIZE(length) ACPI_ROUND_UP_TO_NATIVE_WORD(length) diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h index c1086452696e..0927765df6aa 100644 --- a/include/acpi/acutils.h +++ b/include/acpi/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,39 @@ #ifndef _ACUTILS_H #define _ACUTILS_H +extern const u8 acpi_gbl_resource_aml_sizes[]; + +/* Strings used by the disassembler and debugger resource dump routines */ + +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +extern const char *acpi_gbl_BMdecode[2]; +extern const char *acpi_gbl_config_decode[4]; +extern const char *acpi_gbl_consume_decode[2]; +extern const char *acpi_gbl_DECdecode[2]; +extern const char *acpi_gbl_HEdecode[2]; +extern const char *acpi_gbl_io_decode[2]; +extern const char *acpi_gbl_LLdecode[2]; +extern const char *acpi_gbl_max_decode[2]; +extern const char *acpi_gbl_MEMdecode[4]; +extern const char *acpi_gbl_min_decode[2]; +extern const char *acpi_gbl_MTPdecode[4]; +extern const char *acpi_gbl_RNGdecode[4]; +extern const char *acpi_gbl_RWdecode[2]; +extern const char *acpi_gbl_SHRdecode[2]; +extern const char *acpi_gbl_SIZdecode[4]; +extern const char *acpi_gbl_TRSdecode[2]; +extern const char *acpi_gbl_TTPdecode[2]; +extern const char *acpi_gbl_TYPdecode[4]; +#endif + +/* Types for Resource descriptor entries */ + +#define ACPI_INVALID_RESOURCE 0 +#define ACPI_FIXED_LENGTH 1 +#define ACPI_VARIABLE_LENGTH 2 +#define ACPI_SMALL_VARIABLE_LENGTH 3 + typedef acpi_status(*acpi_pkg_callback) (u8 object_type, union acpi_operand_object * source_object, @@ -159,7 +192,6 @@ extern const u8 _acpi_ctype[]; #define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) #define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) -#define ACPI_IS_ASCII(c) ((c) < 0x80) #endif /* ACPI_USE_SYSTEM_CLIBRARY */ @@ -243,21 +275,22 @@ acpi_ut_ptr_exit(u32 line_number, const char *function_name, char *module_name, u32 component_id, u8 * ptr); -void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id); +void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); -void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id); +void acpi_ut_report_error(char *module_name, u32 line_number); -void -acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id); +void acpi_ut_report_info(char *module_name, u32 line_number); -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); +void acpi_ut_report_warning(char *module_name, u32 line_number); + +/* Error and message reporting interfaces */ void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print(u32 requested_debug_level, u32 line_number, const char *function_name, char *module_name, - u32 component_id, char *format, ...) ACPI_PRINTF_LIKE_FUNC; + u32 component_id, char *format, ...) ACPI_PRINTF_LIKE(6); void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw(u32 requested_debug_level, @@ -265,7 +298,24 @@ acpi_ut_debug_print_raw(u32 requested_debug_level, const char *function_name, char *module_name, u32 component_id, - char *format, ...) ACPI_PRINTF_LIKE_FUNC; + char *format, ...) ACPI_PRINTF_LIKE(6); + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_error(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_exception(char *module_name, + u32 line_number, + acpi_status status, char *format, ...) ACPI_PRINTF_LIKE(4); + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_warning(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_info(char *module_name, + u32 line_number, char *format, ...) ACPI_PRINTF_LIKE(3); /* * utdelete - Object deletion and reference counts @@ -419,7 +469,19 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); #define ACPI_ANY_BASE 0 -u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc); +acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index); + +u32 acpi_ut_get_descriptor_length(void *aml); + +u16 acpi_ut_get_resource_length(void *aml); + +u8 acpi_ut_get_resource_header_length(void *aml); + +u8 acpi_ut_get_resource_type(void *aml); + +acpi_status +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, + u8 ** end_tag); u8 acpi_ut_generate_checksum(u8 * buffer, u32 length); diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h index 7fdf5299f501..37964a59aef8 100644 --- a/include/acpi/amlcode.h +++ b/include/acpi/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h index 051786e4b210..fb4735315ad3 100644 --- a/include/acpi/amlresrc.h +++ b/include/acpi/amlresrc.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,182 +92,168 @@ struct asl_resource_node { struct asl_resource_node *next; }; +/* Macros used to generate AML resource length fields */ + +#define ACPI_AML_SIZE_LARGE(r) (sizeof (r) - sizeof (struct aml_resource_large_header)) +#define ACPI_AML_SIZE_SMALL(r) (sizeof (r) - sizeof (struct aml_resource_small_header)) + /* * Resource descriptors defined in the ACPI specification. * * Packing/alignment must be BYTE because these descriptors - * are used to overlay the AML byte stream. + * are used to overlay the raw AML byte stream. */ #pragma pack(1) -struct asl_irq_format_desc { - u8 descriptor_type; - u16 irq_mask; +/* + * SMALL descriptors + */ +#define AML_RESOURCE_SMALL_HEADER_COMMON \ + u8 descriptor_type; + +struct aml_resource_small_header { +AML_RESOURCE_SMALL_HEADER_COMMON}; + +struct aml_resource_irq { + AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask; u8 flags; }; -struct asl_irq_noflags_desc { - u8 descriptor_type; - u16 irq_mask; +struct aml_resource_irq_noflags { + AML_RESOURCE_SMALL_HEADER_COMMON u16 irq_mask; }; -struct asl_dma_format_desc { - u8 descriptor_type; - u8 dma_channel_mask; +struct aml_resource_dma { + AML_RESOURCE_SMALL_HEADER_COMMON u8 dma_channel_mask; u8 flags; }; -struct asl_start_dependent_desc { - u8 descriptor_type; - u8 flags; +struct aml_resource_start_dependent { + AML_RESOURCE_SMALL_HEADER_COMMON u8 flags; }; -struct asl_start_dependent_noprio_desc { - u8 descriptor_type; -}; +struct aml_resource_start_dependent_noprio { +AML_RESOURCE_SMALL_HEADER_COMMON}; -struct asl_end_dependent_desc { - u8 descriptor_type; -}; +struct aml_resource_end_dependent { +AML_RESOURCE_SMALL_HEADER_COMMON}; -struct asl_io_port_desc { - u8 descriptor_type; - u8 information; - u16 address_min; - u16 address_max; +struct aml_resource_io { + AML_RESOURCE_SMALL_HEADER_COMMON u8 flags; + u16 minimum; + u16 maximum; u8 alignment; - u8 length; + u8 address_length; }; -struct asl_fixed_io_port_desc { - u8 descriptor_type; - u16 base_address; - u8 length; +struct aml_resource_fixed_io { + AML_RESOURCE_SMALL_HEADER_COMMON u16 address; + u8 address_length; }; -struct asl_small_vendor_desc { - u8 descriptor_type; - u8 vendor_defined[7]; -}; +struct aml_resource_vendor_small { +AML_RESOURCE_SMALL_HEADER_COMMON}; -struct asl_end_tag_desc { - u8 descriptor_type; - u8 checksum; +struct aml_resource_end_tag { + AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum; }; -/* LARGE descriptors */ +/* + * LARGE descriptors + */ +#define AML_RESOURCE_LARGE_HEADER_COMMON \ + u8 descriptor_type;\ + u16 resource_length; + +struct aml_resource_large_header { +AML_RESOURCE_LARGE_HEADER_COMMON}; -struct asl_memory_24_desc { - u8 descriptor_type; - u16 length; - u8 information; - u16 address_min; - u16 address_max; +struct aml_resource_memory24 { + AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; + u16 minimum; + u16 maximum; u16 alignment; - u16 range_length; + u16 address_length; }; -struct asl_large_vendor_desc { - u8 descriptor_type; - u16 length; - u8 vendor_defined[1]; -}; +struct aml_resource_vendor_large { +AML_RESOURCE_LARGE_HEADER_COMMON}; -struct asl_memory_32_desc { - u8 descriptor_type; - u16 length; - u8 information; - u32 address_min; - u32 address_max; +struct aml_resource_memory32 { + AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; + u32 minimum; + u32 maximum; u32 alignment; - u32 range_length; + u32 address_length; }; -struct asl_fixed_memory_32_desc { - u8 descriptor_type; - u16 length; - u8 information; - u32 base_address; - u32 range_length; +struct aml_resource_fixed_memory32 { + AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; + u32 address; + u32 address_length; }; -struct asl_extended_address_desc { - u8 descriptor_type; - u16 length; - u8 resource_type; - u8 flags; - u8 specific_flags; - u8 revision_iD; +#define AML_RESOURCE_ADDRESS_COMMON \ + u8 resource_type; \ + u8 flags; \ + u8 specific_flags; + +struct aml_resource_address { +AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON}; + +struct aml_resource_extended_address64 { + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON u8 revision_iD; u8 reserved; u64 granularity; - u64 address_min; - u64 address_max; + u64 minimum; + u64 maximum; u64 translation_offset; u64 address_length; - u64 type_specific_attributes; - u8 optional_fields[2]; /* Used for length calculation only */ + u64 type_specific; }; -#define ASL_EXTENDED_ADDRESS_DESC_REVISION 1 /* ACPI 3.0 */ +#define AML_RESOURCE_EXTENDED_ADDRESS_REVISION 1 /* ACPI 3.0 */ -struct asl_qword_address_desc { - u8 descriptor_type; - u16 length; - u8 resource_type; - u8 flags; - u8 specific_flags; - u64 granularity; - u64 address_min; - u64 address_max; +struct aml_resource_address64 { + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON u64 granularity; + u64 minimum; + u64 maximum; u64 translation_offset; u64 address_length; - u8 optional_fields[2]; }; -struct asl_dword_address_desc { - u8 descriptor_type; - u16 length; - u8 resource_type; - u8 flags; - u8 specific_flags; - u32 granularity; - u32 address_min; - u32 address_max; +struct aml_resource_address32 { + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON u32 granularity; + u32 minimum; + u32 maximum; u32 translation_offset; u32 address_length; - u8 optional_fields[2]; }; -struct asl_word_address_desc { - u8 descriptor_type; - u16 length; - u8 resource_type; - u8 flags; - u8 specific_flags; - u16 granularity; - u16 address_min; - u16 address_max; +struct aml_resource_address16 { + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_ADDRESS_COMMON u16 granularity; + u16 minimum; + u16 maximum; u16 translation_offset; u16 address_length; - u8 optional_fields[2]; }; -struct asl_extended_xrupt_desc { - u8 descriptor_type; - u16 length; - u8 flags; - u8 table_length; - u32 interrupt_number[1]; +struct aml_resource_extended_irq { + AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; + u8 interrupt_count; + u32 interrupts[1]; /* res_source_index, res_source optional fields follow */ }; -struct asl_general_register_desc { - u8 descriptor_type; - u16 length; - u8 address_space_id; +struct aml_resource_generic_register { + AML_RESOURCE_LARGE_HEADER_COMMON u8 address_space_id; u8 bit_width; u8 bit_offset; - u8 access_size; /* ACPI 3.0, was Reserved */ + u8 access_size; /* ACPI 3.0, was previously Reserved */ u64 address; }; @@ -277,26 +263,39 @@ struct asl_general_register_desc { /* Union of all resource descriptors, so we can allocate the worst case */ -union asl_resource_desc { - struct asl_irq_format_desc irq; - struct asl_dma_format_desc dma; - struct asl_start_dependent_desc std; - struct asl_end_dependent_desc end; - struct asl_io_port_desc iop; - struct asl_fixed_io_port_desc fio; - struct asl_small_vendor_desc smv; - struct asl_end_tag_desc et; - - struct asl_memory_24_desc M24; - struct asl_large_vendor_desc lgv; - struct asl_memory_32_desc M32; - struct asl_fixed_memory_32_desc F32; - struct asl_qword_address_desc qas; - struct asl_dword_address_desc das; - struct asl_word_address_desc was; - struct asl_extended_address_desc eas; - struct asl_extended_xrupt_desc exx; - struct asl_general_register_desc grg; +union aml_resource { + /* Descriptor headers */ + + struct aml_resource_small_header small_header; + struct aml_resource_large_header large_header; + + /* Small resource descriptors */ + + struct aml_resource_irq irq; + struct aml_resource_dma dma; + struct aml_resource_start_dependent start_dpf; + struct aml_resource_end_dependent end_dpf; + struct aml_resource_io io; + struct aml_resource_fixed_io fixed_io; + struct aml_resource_vendor_small vendor_small; + struct aml_resource_end_tag end_tag; + + /* Large resource descriptors */ + + struct aml_resource_memory24 memory24; + struct aml_resource_generic_register generic_reg; + struct aml_resource_vendor_large vendor_large; + struct aml_resource_memory32 memory32; + struct aml_resource_fixed_memory32 fixed_memory32; + struct aml_resource_address16 address16; + struct aml_resource_address32 address32; + struct aml_resource_address64 address64; + struct aml_resource_extended_address64 ext_address64; + struct aml_resource_extended_irq extended_irq; + + /* Utility overlays */ + + struct aml_resource_address address; u32 u32_item; u16 u16_item; u8 U8item; diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h index 91f4a12a99a1..3fa81d55cd0c 100644 --- a/include/acpi/pdc_intel.h +++ b/include/acpi/pdc_intel.h @@ -15,9 +15,7 @@ #define ACPI_PDC_C_C1_FFH (0x0100) #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ - ACPI_PDC_C_C1_HALT) - -#define ACPI_PDC_EST_CAPABILITY_SMP_MSR (ACPI_PDC_EST_CAPABILITY_SMP | \ + ACPI_PDC_C_C1_HALT | \ ACPI_PDC_P_FFH) #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 16609c1ab2eb..223ec6467108 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +68,7 @@ #define ACPI_APPLICATION #define ACPI_DEBUGGER #define ACPI_DISASSEMBLER +#define ACPI_MUTEX_DEBUG #endif #ifdef ACPI_ASL_COMPILER @@ -148,6 +149,9 @@ #elif defined(NETWARE) #include "acnetware.h" +#elif defined(__sun) +#include "acsolaris.h" + #else /* All other environments */ @@ -157,13 +161,6 @@ #define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_UINT64 unsigned long long -/* - * This macro is used to tag functions as "printf-like" because - * some compilers can catch printf format string problems. MSVC - * doesn't, so this is proprocessed away. - */ -#define ACPI_PRINTF_LIKE_FUNC - #endif /* @@ -205,6 +202,8 @@ * *****************************************************************************/ +#define ACPI_IS_ASCII(c) ((c) < 0x80) + #ifdef ACPI_USE_SYSTEM_CLIBRARY /* * Use the standard C library headers. @@ -234,7 +233,7 @@ #define ACPI_STRCAT(d,s) (void) strcat((d), (s)) #define ACPI_STRNCAT(d,s,n) strncat((d), (s), (acpi_size)(n)) #define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (acpi_size)(n)) -#define ACPI_MEMCMP(s1,s2,n) memcmp((s1), (s2), (acpi_size)(n)) +#define ACPI_MEMCMP(s1,s2,n) memcmp((const char *)(s1), (const char *)(s2), (acpi_size)(n)) #define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (acpi_size)(n)) #define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (acpi_size)(n)) @@ -246,7 +245,6 @@ #define ACPI_IS_UPPER(i) isupper((int) (i)) #define ACPI_IS_PRINT(i) isprint((int) (i)) #define ACPI_IS_ALPHA(i) isalpha((int) (i)) -#define ACPI_IS_ASCII(i) isascii((int) (i)) #else @@ -273,8 +271,8 @@ typedef char *va_list; /* * Storage alignment properties */ -#define _AUPBND (sizeof (acpi_native_int) - 1) -#define _ADNBND (sizeof (acpi_native_int) - 1) +#define _AUPBND (sizeof (acpi_native_uint) - 1) +#define _ADNBND (sizeof (acpi_native_uint) - 1) /* * Variable argument list macro definitions @@ -296,7 +294,7 @@ typedef char *va_list; #define ACPI_STRCAT(d,s) (void) acpi_ut_strcat ((d), (s)) #define ACPI_STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (acpi_size)(n)) #define ACPI_STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s), (acpi_size)(n)) -#define ACPI_MEMCMP(s1,s2,n) acpi_ut_memcmp((s1), (s2), (acpi_size)(n)) +#define ACPI_MEMCMP(s1,s2,n) acpi_ut_memcmp((const char *)(s1), (const char *)(s2), (acpi_size)(n)) #define ACPI_MEMCPY(d,s,n) (void) acpi_ut_memcpy ((d), (s), (acpi_size)(n)) #define ACPI_MEMSET(d,v,n) (void) acpi_ut_memset ((d), (v), (acpi_size)(n)) #define ACPI_TOUPPER acpi_ut_to_upper diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h index 4c0e0ba09ba0..da80933963db 100644 --- a/include/acpi/platform/acgcc.h +++ b/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,12 +48,14 @@ #define ACPI_GET_FUNCTION_NAME __FUNCTION__ -/* This macro is used to tag functions as "printf-like" because +/* + * This macro is used to tag functions as "printf-like" because * some compilers (like GCC) can catch printf format string problems. */ -#define ACPI_PRINTF_LIKE_FUNC __attribute__ ((__format__ (__printf__, 6, 7))) +#define ACPI_PRINTF_LIKE(c) __attribute__ ((__format__ (__printf__, c, c+1))) -/* Some compilers complain about unused variables. Sometimes we don't want to +/* + * Some compilers complain about unused variables. Sometimes we don't want to * use all the variables (for example, _acpi_module_name). This allows us * to to tell the compiler warning in a per-variable manner that a variable * is unused. diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index c93e6562f0e1..2e6d54569ee8 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2005, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,6 +71,10 @@ #define acpi_cache_t kmem_cache_t #endif +/* Full namespace pathname length limit - arbitrary */ + +#define ACPI_PATHNAME_MAX 256 + #else /* !__KERNEL__ */ #include <stdarg.h> @@ -98,4 +102,6 @@ #include "acgcc.h" +#define acpi_cpu_flags unsigned long + #endif /* __ACLINUX_H__ */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 7a00d5089de9..badf0277b1be 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -62,9 +62,6 @@ struct acpi_processor_power { u32 bm_activity; int count; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; - - /* the _PDC objects passed by the driver, if any */ - struct acpi_object_list *pdc; }; /* Performance Management */ @@ -96,8 +93,6 @@ struct acpi_processor_performance { unsigned int state_count; struct acpi_processor_px *states; - /* the _PDC objects passed by the driver, if any */ - struct acpi_object_list *pdc; }; /* Throttling Control */ @@ -151,6 +146,9 @@ struct acpi_processor { struct acpi_processor_performance *performance; struct acpi_processor_throttling throttling; struct acpi_processor_limit limit; + + /* the _PDC objects for this processor, if any */ + struct acpi_object_list *pdc; }; struct acpi_processor_errata { @@ -178,22 +176,12 @@ int acpi_processor_notify_smm(struct module *calling_module); extern struct acpi_processor *processors[NR_CPUS]; extern struct acpi_processor_errata errata; -int acpi_processor_set_pdc(struct acpi_processor *pr, - struct acpi_object_list *pdc_in); +void arch_acpi_processor_init_pdc(struct acpi_processor *pr); -#ifdef ARCH_HAS_POWER_PDC_INIT -void acpi_processor_power_init_pdc(struct acpi_processor_power *pow, - unsigned int cpu); +#ifdef ARCH_HAS_POWER_INIT void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu); #else -static inline void acpi_processor_power_init_pdc(struct acpi_processor_power - *pow, unsigned int cpu) -{ - pow->pdc = NULL; - return; -} - static inline void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu) @@ -235,9 +223,6 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) /* in processor_throttling.c */ int acpi_processor_get_throttling_info(struct acpi_processor *pr); int acpi_processor_set_throttling(struct acpi_processor *pr, int state); -ssize_t acpi_processor_write_throttling(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); extern struct file_operations acpi_processor_throttling_fops; /* in processor_idle.c */ @@ -249,9 +234,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr, /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); -ssize_t acpi_processor_write_limit(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); extern struct file_operations acpi_processor_limit_fops; #ifdef CONFIG_CPU_FREQ diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h index 9dc7256cf979..62d0d6681aa9 100644 --- a/include/asm-alpha/dma-mapping.h +++ b/include/asm-alpha/dma-mapping.h @@ -30,6 +30,7 @@ #else /* no PCI - no IOMMU. */ +struct scatterlist; void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index cc9c7e8cced5..f3b7b1a59c56 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -572,7 +572,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) if something tries to do an invalid cmpxchg(). */ extern void __cmpxchg_called_with_bad_pointer(void); -static inline unsigned long +static __always_inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) { switch (size) { diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index 740c297eb11c..46a0402696de 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -38,8 +38,6 @@ struct clk { struct clk_functions { int (*clk_enable)(struct clk *clk); void (*clk_disable)(struct clk *clk); - int (*clk_use)(struct clk *clk); - void (*clk_unuse)(struct clk *clk); long (*clk_round_rate)(struct clk *clk, unsigned long rate); int (*clk_set_rate)(struct clk *clk, unsigned long rate); int (*clk_set_parent)(struct clk *clk, struct clk *parent); diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h index f5bcc9a1aed6..b726acfcab14 100644 --- a/include/asm-arm/arch-omap/io.h +++ b/include/asm-arm/arch-omap/io.h @@ -116,7 +116,11 @@ typedef struct { volatile u32 offset[4096]; } __regbase32; ->offset[((vaddr)&4095)>>2] #define __REG32(paddr) __REGV32(io_p2v(paddr)) -extern void omap_map_common_io(void); +extern void omap1_map_common_io(void); +extern void omap1_init_common_hw(void); + +extern void omap2_map_common_io(void); +extern void omap2_init_common_hw(void); #else diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index dae138b9cac5..1409c5bd703f 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -108,6 +108,7 @@ #define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ #define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ +#define DALGN __REG(0x400000a0) /* DMA Alignment Register */ #define DINT __REG(0x400000f0) /* DMA Interrupt Register */ #define DRCMR(n) __REG2(0x40000100, (n)<<2) @@ -1614,8 +1615,21 @@ #define SSCR0_National (0x2 << 4) /* National Microwire */ #define SSCR0_ECS (1 << 6) /* External clock select */ #define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ +#if defined(CONFIG_PXA25x) #define SSCR0_SCR (0x0000ff00) /* Serial Clock Rate (mask) */ #define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */ +#elif defined(CONFIG_PXA27x) +#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */ +#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */ +#define SSCR0_EDSS (1 << 20) /* Extended data size select */ +#define SSCR0_NCS (1 << 21) /* Network clock select */ +#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ +#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ +#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ +#define SSCR0_SlotsPerFrm(c) ((x) - 1) /* Time slots per frame [1..8] */ +#define SSCR0_ADC (1 << 30) /* Audio clock select */ +#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ +#endif #define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ #define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S index abfbe45cd17c..5f8223e700d3 100644 --- a/include/asm-arm/arch-s3c2410/debug-macro.S +++ b/include/asm-arm/arch-s3c2410/debug-macro.S @@ -25,7 +25,7 @@ .macro addruart, rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 - ldreq \rx, = S3C2410_PA_UART + ldreq \rx, = S3C24XX_PA_UART ldrne \rx, = S3C24XX_VA_UART #if CONFIG_DEBUG_S3C2410_UART != 0 add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART) @@ -44,7 +44,7 @@ 1003: mrc p15, 0, \rd, c1, c0 tst \rd, #1 - addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) + addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] @@ -75,7 +75,7 @@ 1003: mrc p15, 0, \rd, c1, c0 tst \rd, #1 - addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) + addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] diff --git a/include/asm-arm/arch-s3c2410/h1940-latch.h b/include/asm-arm/arch-s3c2410/h1940-latch.h new file mode 100644 index 000000000000..c5802411f43d --- /dev/null +++ b/include/asm-arm/arch-s3c2410/h1940-latch.h @@ -0,0 +1,64 @@ +/* linux/include/asm-arm/arch-s3c2410/h1940-latch.h + * + * (c) 2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * iPAQ H1940 series - latch definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_H1940_LATCH_H +#define __ASM_ARCH_H1940_LATCH_H + + +#ifndef __ASSEMBLY__ +#define H1940_LATCH ((void __iomem *)0xF8000000) +#else +#define H1940_LATCH 0xF8000000 +#endif + +#define H1940_PA_LATCH (S3C2410_CS2) + +/* SD layer latch */ + +#define H1940_LATCH_SDQ1 (1<<16) +#define H1940_LATCH_LCD_P1 (1<<17) +#define H1940_LATCH_LCD_P2 (1<<18) +#define H1940_LATCH_LCD_P3 (1<<19) +#define H1940_LATCH_MAX1698_nSHUTDOWN (1<<20) /* LCD backlight */ +#define H1940_LATCH_LED_RED (1<<21) +#define H1940_LATCH_SDQ7 (1<<22) +#define H1940_LATCH_USB_DP (1<<23) + +/* CPU layer latch */ + +#define H1940_LATCH_UDA_POWER (1<<24) +#define H1940_LATCH_AUDIO_POWER (1<<25) +#define H1940_LATCH_SM803_ENABLE (1<<26) +#define H1940_LATCH_LCD_P4 (1<<27) +#define H1940_LATCH_CPUQ5 (1<<28) /* untraced */ +#define H1940_LATCH_BLUETOOTH_POWER (1<<29) /* active high */ +#define H1940_LATCH_LED_GREEN (1<<30) +#define H1940_LATCH_LED_FLASH (1<<31) + +/* default settings */ + +#define H1940_LATCH_DEFAULT \ + H1940_LATCH_LCD_P4 | \ + H1940_LATCH_SM803_ENABLE | \ + H1940_LATCH_SDQ1 | \ + H1940_LATCH_LCD_P1 | \ + H1940_LATCH_LCD_P2 | \ + H1940_LATCH_LCD_P3 | \ + H1940_LATCH_MAX1698_nSHUTDOWN | \ + H1940_LATCH_CPUQ5 + +/* control functions */ + +extern void h1940_latch_control(unsigned int clear, unsigned int set); + +#endif /* __ASM_ARCH_H1940_LATCH_H */ diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h index 1c9de29cafef..a2330bf83695 100644 --- a/include/asm-arm/arch-s3c2410/hardware.h +++ b/include/asm-arm/arch-s3c2410/hardware.h @@ -17,6 +17,7 @@ * 14-Sep-2004 BJD Added misccr and getpin to gpio * 01-Oct-2004 BJD Added the new gpio functions * 16-Oct-2004 BJD Removed the clock variables + * 15-Jan-2006 LCVR Added s3c2400_gpio_getirq() */ #ifndef __ASM_ARCH_HARDWARE_H @@ -55,6 +56,12 @@ extern unsigned int s3c2410_gpio_getcfg(unsigned int pin); extern int s3c2410_gpio_getirq(unsigned int pin); +#ifdef CONFIG_CPU_S3C2400 + +extern int s3c2400_gpio_getirq(unsigned int pin); + +#endif /* CONFIG_CPU_S3C2400 */ + /* s3c2410_gpio_irqfilter * * set the irq filtering on the given pin diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h index 1833ea5c4220..c380d264a847 100644 --- a/include/asm-arm/arch-s3c2410/map.h +++ b/include/asm-arm/arch-s3c2410/map.h @@ -14,6 +14,7 @@ * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out * 10-Feb-2005 BJD Added CAMIF definition from guillaume.gourat@nexvision.tv * 10-Mar-2005 LCVR Added support to S3C2400, changed {VA,SZ} names + * 15-Jan-2006 LCVR Added S3C24XX_PA macros for common S3C24XX resources */ #ifndef __ASM_ARCH_MAP_H @@ -188,5 +189,42 @@ #define S3C2400_SDRAM_PA (S3C2400_CS6) +/* Use a single interface for common resources between S3C24XX cpus */ + +#ifdef CONFIG_CPU_S3C2400 +#define S3C24XX_PA_IRQ S3C2400_PA_IRQ +#define S3C24XX_PA_MEMCTRL S3C2400_PA_MEMCTRL +#define S3C24XX_PA_USBHOST S3C2400_PA_USBHOST +#define S3C24XX_PA_DMA S3C2400_PA_DMA +#define S3C24XX_PA_CLKPWR S3C2400_PA_CLKPWR +#define S3C24XX_PA_LCD S3C2400_PA_LCD +#define S3C24XX_PA_UART S3C2400_PA_UART +#define S3C24XX_PA_TIMER S3C2400_PA_TIMER +#define S3C24XX_PA_USBDEV S3C2400_PA_USBDEV +#define S3C24XX_PA_WATCHDOG S3C2400_PA_WATCHDOG +#define S3C24XX_PA_IIC S3C2400_PA_IIC +#define S3C24XX_PA_IIS S3C2400_PA_IIS +#define S3C24XX_PA_GPIO S3C2400_PA_GPIO +#define S3C24XX_PA_RTC S3C2400_PA_RTC +#define S3C24XX_PA_ADC S3C2400_PA_ADC +#define S3C24XX_PA_SPI S3C2400_PA_SPI +#else +#define S3C24XX_PA_IRQ S3C2410_PA_IRQ +#define S3C24XX_PA_MEMCTRL S3C2410_PA_MEMCTRL +#define S3C24XX_PA_USBHOST S3C2410_PA_USBHOST +#define S3C24XX_PA_DMA S3C2410_PA_DMA +#define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR +#define S3C24XX_PA_LCD S3C2410_PA_LCD +#define S3C24XX_PA_UART S3C2410_PA_UART +#define S3C24XX_PA_TIMER S3C2410_PA_TIMER +#define S3C24XX_PA_USBDEV S3C2410_PA_USBDEV +#define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG +#define S3C24XX_PA_IIC S3C2410_PA_IIC +#define S3C24XX_PA_IIS S3C2410_PA_IIS +#define S3C24XX_PA_GPIO S3C2410_PA_GPIO +#define S3C24XX_PA_RTC S3C2410_PA_RTC +#define S3C24XX_PA_ADC S3C2410_PA_ADC +#define S3C24XX_PA_SPI S3C2410_PA_SPI +#endif #endif /* __ASM_ARCH_MAP_H */ diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h index 7f1be48ad67e..9697f93afe74 100644 --- a/include/asm-arm/arch-s3c2410/regs-gpio.h +++ b/include/asm-arm/arch-s3c2410/regs-gpio.h @@ -22,6 +22,7 @@ * 28-Mar-2005 LCVR Fixed definition of GPB10 * 26-Oct-2005 BJD Added generic configuration types * 27-Nov-2005 LCVR Added definitions to S3C2400 registers + * 15-Jan-2006 LCVR Written S3C24XX_GPIO_BASE() macro */ @@ -39,6 +40,27 @@ #define S3C2410_GPIO_BANKG (32*6) #define S3C2410_GPIO_BANKH (32*7) +#ifdef CONFIG_CPU_S3C2400 +#define S3C24XX_GPIO_BASE(x) S3C2400_GPIO_BASE(x) +#define S3C24XX_MISCCR S3C2400_MISCCR +#else +#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x) +#define S3C24XX_MISCCR S3C2410_MISCCR +#endif /* CONFIG_CPU_S3C2400 */ + + +/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */ + +#define S3C2400_BANKNUM(pin) (((pin) & ~31) / 32) +#define S3C2400_BASEA2B(pin) ((((pin) & ~31) >> 2)) +#define S3C2400_BASEC2H(pin) ((S3C2400_BANKNUM(pin) * 10) + \ + (2 * (S3C2400_BANKNUM(pin)-2))) + +#define S3C2400_GPIO_BASE(pin) (pin < S3C2410_GPIO_BANKC ? \ + S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \ + S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO) + + #define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO) #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31) diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h index ce1bbbaad6d3..83b01254c4ac 100644 --- a/include/asm-arm/arch-s3c2410/regs-serial.h +++ b/include/asm-arm/arch-s3c2410/regs-serial.h @@ -39,9 +39,9 @@ #define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 ) #define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 ) -#define S3C2410_PA_UART0 (S3C2410_PA_UART) -#define S3C2410_PA_UART1 (S3C2410_PA_UART + 0x4000 ) -#define S3C2410_PA_UART2 (S3C2410_PA_UART + 0x8000 ) +#define S3C2410_PA_UART0 (S3C24XX_PA_UART) +#define S3C2410_PA_UART1 (S3C24XX_PA_UART + 0x4000 ) +#define S3C2410_PA_UART2 (S3C24XX_PA_UART + 0x8000 ) #define S3C2410_URXH (0x24) #define S3C2410_UTXH (0x20) diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h index ddd1578a7ee0..4367ec054b51 100644 --- a/include/asm-arm/arch-s3c2410/uncompress.h +++ b/include/asm-arm/arch-s3c2410/uncompress.h @@ -35,13 +35,13 @@ #undef S3C2410_GPIOREG #undef S3C2410_WDOGREG -#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x))) -#define S3C2410_WDOGREG(x) ((S3C2410_PA_WATCHDOG + (x))) +#define S3C2410_GPIOREG(x) ((S3C24XX_PA_GPIO + (x))) +#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x))) /* how many bytes we allow into the FIFO at a time in FIFO mode */ #define FIFO_MAX (14) -#define uart_base S3C2410_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT) +#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C2410_LOWLEVEL_UART_PORT) static __inline__ void uart_wr(unsigned int reg, unsigned int val) diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h index d4256d5f3a7c..747bdd31a74b 100644 --- a/include/asm-arm/checksum.h +++ b/include/asm-arm/checksum.h @@ -77,7 +77,7 @@ ip_fast_csum(unsigned char * iph, unsigned int ihl) mov %0, %0, lsr #16" : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1) : "1" (iph), "2" (ihl) - : "cc"); + : "cc", "memory"); return sum; } diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h index 3351b77fab36..e8ea67c97c73 100644 --- a/include/asm-arm/mach/map.h +++ b/include/asm-arm/mach/map.h @@ -26,6 +26,7 @@ struct meminfo; #define MT_MEMORY 5 #define MT_ROM 6 #define MT_IXP2000_DEVICE 7 +#define MT_NONSHARED_DEVICE 8 extern void create_memmap_holes(struct meminfo *); extern void memtable_init(struct meminfo *); diff --git a/include/asm-arm/mutex.h b/include/asm-arm/mutex.h index 6caa59f1f595..cb29d84e690d 100644 --- a/include/asm-arm/mutex.h +++ b/include/asm-arm/mutex.h @@ -23,72 +23,71 @@ * simply bail out immediately through the slow path where the lock will be * reattempted until it succeeds. */ -#define __mutex_fastpath_lock(count, fail_fn) \ -do { \ - int __ex_flag, __res; \ - \ - typecheck(atomic_t *, count); \ - typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ - \ - __asm__ ( \ - "ldrex %0, [%2] \n" \ - "sub %0, %0, #1 \n" \ - "strex %1, %0, [%2] \n" \ - \ - : "=&r" (__res), "=&r" (__ex_flag) \ - : "r" (&(count)->counter) \ - : "cc","memory" ); \ - \ - if (unlikely(__res || __ex_flag)) \ - fail_fn(count); \ -} while (0) - -#define __mutex_fastpath_lock_retval(count, fail_fn) \ -({ \ - int __ex_flag, __res; \ - \ - typecheck(atomic_t *, count); \ - typecheck_fn(fastcall int (*)(atomic_t *), fail_fn); \ - \ - __asm__ ( \ - "ldrex %0, [%2] \n" \ - "sub %0, %0, #1 \n" \ - "strex %1, %0, [%2] \n" \ - \ - : "=&r" (__res), "=&r" (__ex_flag) \ - : "r" (&(count)->counter) \ - : "cc","memory" ); \ - \ - __res |= __ex_flag; \ - if (unlikely(__res != 0)) \ - __res = fail_fn(count); \ - __res; \ -}) +static inline void +__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) +{ + int __ex_flag, __res; + + __asm__ ( + + "ldrex %0, [%2] \n\t" + "sub %0, %0, #1 \n\t" + "strex %1, %0, [%2] " + + : "=&r" (__res), "=&r" (__ex_flag) + : "r" (&(count)->counter) + : "cc","memory" ); + + __res |= __ex_flag; + if (unlikely(__res != 0)) + fail_fn(count); +} + +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *)) +{ + int __ex_flag, __res; + + __asm__ ( + + "ldrex %0, [%2] \n\t" + "sub %0, %0, #1 \n\t" + "strex %1, %0, [%2] " + + : "=&r" (__res), "=&r" (__ex_flag) + : "r" (&(count)->counter) + : "cc","memory" ); + + __res |= __ex_flag; + if (unlikely(__res != 0)) + __res = fail_fn(count); + return __res; +} /* * Same trick is used for the unlock fast path. However the original value, * rather than the result, is used to test for success in order to have * better generated assembly. */ -#define __mutex_fastpath_unlock(count, fail_fn) \ -do { \ - int __ex_flag, __res, __orig; \ - \ - typecheck(atomic_t *, count); \ - typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ - \ - __asm__ ( \ - "ldrex %0, [%3] \n" \ - "add %1, %0, #1 \n" \ - "strex %2, %1, [%3] \n" \ - \ - : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) \ - : "r" (&(count)->counter) \ - : "cc","memory" ); \ - \ - if (unlikely(__orig || __ex_flag)) \ - fail_fn(count); \ -} while (0) +static inline void +__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) +{ + int __ex_flag, __res, __orig; + + __asm__ ( + + "ldrex %0, [%3] \n\t" + "add %1, %0, #1 \n\t" + "strex %2, %1, [%3] " + + : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) + : "r" (&(count)->counter) + : "cc","memory" ); + + __orig |= __ex_flag; + if (unlikely(__orig != 0)) + fail_fn(count); +} /* * If the unlock was done on a contended lock, or if the unlock simply fails @@ -110,12 +109,12 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) __asm__ ( - "1: ldrex %0, [%3] \n" - "subs %1, %0, #1 \n" - "strexeq %2, %1, [%3] \n" - "movlt %0, #0 \n" - "cmpeq %2, #0 \n" - "bgt 1b \n" + "1: ldrex %0, [%3] \n\t" + "subs %1, %0, #1 \n\t" + "strexeq %2, %1, [%3] \n\t" + "movlt %0, #0 \n\t" + "cmpeq %2, #0 \n\t" + "bgt 1b " : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) : "r" (&count->counter) diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index 5a0d19b466b0..70e00d08345e 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -168,6 +168,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) #define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) #define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) +#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) /* * - coarse table (not used) diff --git a/include/asm-arm26/bitops.h b/include/asm-arm26/bitops.h index 15cc6f2da792..d87f8634e625 100644 --- a/include/asm-arm26/bitops.h +++ b/include/asm-arm26/bitops.h @@ -186,7 +186,7 @@ extern void _change_bit_le(int nr, volatile unsigned long * p); extern int _test_and_set_bit_le(int nr, volatile unsigned long * p); extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p); extern int _test_and_change_bit_le(int nr, volatile unsigned long * p); -extern int _find_first_zero_bit_le(void * p, unsigned size); +extern int _find_first_zero_bit_le(const unsigned long * p, unsigned size); extern int _find_next_zero_bit_le(void * p, int size, int offset); extern int _find_first_bit_le(const unsigned long *p, unsigned size); extern int _find_next_bit_le(const unsigned long *p, int size, int offset); @@ -326,7 +326,7 @@ static inline int sched_find_first_bit(unsigned long *b) #define minix_test_and_clear_bit(nr,p) \ __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define minix_find_first_zero_bit(p,sz) \ - _find_first_zero_bit_le(p,sz) + _find_first_zero_bit_le((unsigned long *)(p),sz) #endif /* __KERNEL__ */ diff --git a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h index dc28daab8aa8..87c19d2bb6a8 100644 --- a/include/asm-arm26/hardirq.h +++ b/include/asm-arm26/hardirq.h @@ -4,6 +4,7 @@ #include <linux/config.h> #include <linux/cache.h> #include <linux/threads.h> +#include <asm/irq.h> typedef struct { unsigned int __softirq_pending; @@ -26,13 +27,6 @@ typedef struct { extern asmlinkage void __do_softirq(void); -#define irq_exit() \ - do { \ - preempt_count() -= IRQ_EXIT_OFFSET; \ - if (!in_interrupt() && local_softirq_pending()) \ - __do_softirq(); \ - preempt_enable_no_resched(); \ - } while (0) #endif diff --git a/include/asm-arm26/posix_types.h b/include/asm-arm26/posix_types.h index b88344ad390c..f8d1eb4f4cb1 100644 --- a/include/asm-arm26/posix_types.h +++ b/include/asm-arm26/posix_types.h @@ -44,6 +44,7 @@ typedef unsigned int __kernel_gid32_t; typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; #ifdef __GNUC__ typedef long long __kernel_loff_t; diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h index ca4ccfc4b578..702884926a55 100644 --- a/include/asm-arm26/system.h +++ b/include/asm-arm26/system.h @@ -98,9 +98,8 @@ extern unsigned int user_debug; * spin_unlock_irq() and friends are implemented. This avoids * us needlessly decrementing and incrementing the preempt count. */ -#define prepare_arch_switch(rq,next) local_irq_enable() -#define finish_arch_switch(rq,prev) spin_unlock(&(rq)->lock) -#define task_running(rq,p) ((rq)->curr == (p)) +#define prepare_arch_switch(next) local_irq_enable() +#define finish_arch_switch(prev) spin_unlock(&(rq)->lock) /* * switch_to(prev, next) should switch from task `prev' to `next' diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h index d3eb0f1e4208..b7fef1572dc0 100644 --- a/include/asm-cris/bitops.h +++ b/include/asm-cris/bitops.h @@ -290,7 +290,7 @@ static inline int find_next_zero_bit (const unsigned long * addr, int size, int tmp = *p; found_first: - tmp |= ~0UL >> size; + tmp |= ~0UL << size; found_middle: return result + ffz(tmp); } diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h index 02be7b3a8a83..f686b519878e 100644 --- a/include/asm-frv/bitops.h +++ b/include/asm-frv/bitops.h @@ -209,7 +209,7 @@ static inline int find_next_zero_bit(const void *addr, int size, int offset) tmp = *p; found_first: - tmp |= ~0UL >> size; + tmp |= ~0UL << size; found_middle: return result + ffz(tmp); } diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h index a5576e02dd1d..ea426abf01d3 100644 --- a/include/asm-frv/thread_info.h +++ b/include/asm-frv/thread_info.h @@ -129,6 +129,7 @@ register struct thread_info *__current_thread_info asm("gr15"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_IRET 5 /* return with iret */ +#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 /* OOM killer killed process */ @@ -138,6 +139,7 @@ register struct thread_info *__current_thread_info asm("gr15"); #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_IRET (1 << TIF_IRET) +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h index cde376a7a857..4d994d2e99e3 100644 --- a/include/asm-frv/unistd.h +++ b/include/asm-frv/unistd.h @@ -486,6 +486,7 @@ static inline pid_t wait(int * wait_stat) /* #define __ARCH_WANT_SYS_SIGPENDING */ #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #endif /* diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h index c0411ec9d651..ff7c2b721594 100644 --- a/include/asm-h8300/bitops.h +++ b/include/asm-h8300/bitops.h @@ -227,7 +227,7 @@ static __inline__ int find_next_zero_bit (const unsigned long * addr, int size, tmp = *p; found_first: - tmp |= ~0UL >> size; + tmp |= ~0UL << size; found_middle: return result + ffz(tmp); } diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h index df4ed323aa4d..55059abf9c95 100644 --- a/include/asm-i386/acpi.h +++ b/include/asm-i386/acpi.h @@ -179,7 +179,7 @@ extern void acpi_reserve_bootmem(void); extern u8 x86_acpiid_to_apicid[]; -#define ARCH_HAS_POWER_PDC_INIT 1 +#define ARCH_HAS_POWER_INIT 1 #endif /*__KERNEL__*/ diff --git a/include/asm-i386/edac.h b/include/asm-i386/edac.h new file mode 100644 index 000000000000..3e7dd0ab68ce --- /dev/null +++ b/include/asm-i386/edac.h @@ -0,0 +1,18 @@ +#ifndef ASM_EDAC_H +#define ASM_EDAC_H + +/* ECC atomic, DMA, SMP and interrupt safe scrub function */ + +static __inline__ void atomic_scrub(void *va, u32 size) +{ + unsigned long *virt_addr = va; + u32 i; + + for (i = 0; i < size / 4; i++, virt_addr++) + /* Very carefully read and write to memory atomically + * so we are interrupt, DMA and SMP safe. + */ + __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr)); +} + +#endif diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index e7a271d39309..44b9db806474 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h @@ -61,7 +61,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (op == FUTEX_OP_SET) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); else { -#if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML) +#ifndef CONFIG_X86_BSWAP if (boot_cpu_data.x86 == 3) ret = -ENOSYS; else diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h index 73296d9924fb..997ca5d17876 100644 --- a/include/asm-i386/page.h +++ b/include/asm-i386/page.h @@ -110,10 +110,10 @@ extern int page_is_ram(unsigned long pagenr); #endif /* __ASSEMBLY__ */ #ifdef __ASSEMBLY__ -#define __PAGE_OFFSET (0xC0000000) +#define __PAGE_OFFSET CONFIG_PAGE_OFFSET #define __PHYSICAL_START CONFIG_PHYSICAL_START #else -#define __PAGE_OFFSET (0xC0000000UL) +#define __PAGE_OFFSET ((unsigned long)CONFIG_PAGE_OFFSET) #define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START) #endif #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START) diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h index 76524b4052ac..026fd231488d 100644 --- a/include/asm-i386/signal.h +++ b/include/asm-i386/signal.h @@ -218,7 +218,6 @@ static __inline__ int sigfindinword(unsigned long word) } struct pt_regs; -extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); #define ptrace_signal_deliver(regs, cookie) \ do { \ diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 36a92ed6a9d0..399145a247f2 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -507,7 +507,7 @@ struct alt_instr { #define smp_rmb() rmb() #define smp_wmb() wmb() #define smp_read_barrier_depends() read_barrier_depends() -#define set_mb(var, value) do { xchg(&var, value); } while (0) +#define set_mb(var, value) do { (void) xchg(&var, value); } while (0) #else #define smp_mb() barrier() #define smp_rmb() barrier() diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h index 2493e77e8c30..e20e99551d71 100644 --- a/include/asm-i386/thread_info.h +++ b/include/asm-i386/thread_info.h @@ -140,6 +140,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__; #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SECCOMP 8 /* secure computing */ +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 @@ -152,6 +153,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__; #define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU) #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1<<TIF_SECCOMP) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) /* work to do on interrupt/exception return */ diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index d7e19eb344b7..af503a122b23 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h @@ -27,6 +27,15 @@ #ifndef _ASM_I386_TOPOLOGY_H #define _ASM_I386_TOPOLOGY_H +#ifdef CONFIG_SMP +#define topology_physical_package_id(cpu) \ + (phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu]) +#define topology_core_id(cpu) \ + (cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu]) +#define topology_core_siblings(cpu) (cpu_core_map[cpu]) +#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) +#endif + #ifdef CONFIG_NUMA #include <asm/mpspec.h> diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 481c3c0ea720..dc81a55dd94d 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -300,8 +300,24 @@ #define __NR_inotify_add_watch 292 #define __NR_inotify_rm_watch 293 #define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 -#define NR_syscalls 295 +#define NR_syscalls 311 /* * user-visible error numbers are in the range -1 - -128: see @@ -417,6 +433,7 @@ __syscall_return(type,__res); \ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #endif #ifdef __KERNEL_SYSCALLS__ diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h index e62b95301d51..93f45c5f189f 100644 --- a/include/asm-ia64/ide.h +++ b/include/asm-ia64/ide.h @@ -17,14 +17,6 @@ #include <linux/irq.h> -#ifndef MAX_HWIFS -# ifdef CONFIG_PCI -#define MAX_HWIFS 10 -# else -#define MAX_HWIFS 6 -# endif -#endif - #define IDE_ARCH_OBSOLETE_DEFAULTS static inline int ide_default_irq(unsigned long base) diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 09b99029ac1a..23c8e1be1911 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -559,6 +559,23 @@ ia64_eoi (void) #define cpu_relax() ia64_hint(ia64_hint_pause) +static inline int +ia64_get_irr(unsigned int vector) +{ + unsigned int reg = vector / 64; + unsigned int bit = vector % 64; + u64 irr; + + switch (reg) { + case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break; + case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break; + case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break; + case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break; + } + + return test_bit(bit, &irr); +} + static inline void ia64_set_lrr0 (unsigned long val) { diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 313cad0628d0..0b210abbe003 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -658,15 +658,7 @@ ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, return isrv.status; } -/* Flush all the processor and platform level instruction and/or data caches */ -static inline s64 -ia64_sal_cache_flush (u64 cache_type) -{ - struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); - return isrv.status; -} - +extern s64 ia64_sal_cache_flush (u64 cache_type); /* Initialize all the processor and platform level instruction and data caches */ static inline s64 diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h index bb8906285fab..f483eeb95dd1 100644 --- a/include/asm-ia64/semaphore.h +++ b/include/asm-ia64/semaphore.h @@ -61,7 +61,7 @@ static inline void down (struct semaphore *sem) { might_sleep(); - if (atomic_dec_return(&sem->count) < 0) + if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1) __down(sem); } @@ -75,7 +75,7 @@ down_interruptible (struct semaphore * sem) int ret = 0; might_sleep(); - if (atomic_dec_return(&sem->count) < 0) + if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1) ret = __down_interruptible(sem); return ret; } @@ -85,7 +85,7 @@ down_trylock (struct semaphore *sem) { int ret = 0; - if (atomic_dec_return(&sem->count) < 0) + if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1) ret = __down_trylock(sem); return ret; } @@ -93,7 +93,7 @@ down_trylock (struct semaphore *sem) static inline void up (struct semaphore * sem) { - if (atomic_inc_return(&sem->count) <= 0) + if (ia64_fetchadd(1, &sem->count.counter, rel) <= -1) __up(sem); } diff --git a/include/asm-ia64/sn/bte.h b/include/asm-ia64/sn/bte.h index f50da3d91d07..01e5b4103235 100644 --- a/include/asm-ia64/sn/bte.h +++ b/include/asm-ia64/sn/bte.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -100,13 +100,28 @@ #define BTE_LNSTAT_STORE(_bte, _x) \ HUB_S(_bte->bte_base_addr, (_x)) #define BTE_SRC_STORE(_bte, _x) \ - HUB_S(_bte->bte_source_addr, (_x)) +({ \ + u64 __addr = ((_x) & ~AS_MASK); \ + if (is_shub2()) \ + __addr = SH2_TIO_PHYS_TO_DMA(__addr); \ + HUB_S(_bte->bte_source_addr, __addr); \ +}) #define BTE_DEST_STORE(_bte, _x) \ - HUB_S(_bte->bte_destination_addr, (_x)) +({ \ + u64 __addr = ((_x) & ~AS_MASK); \ + if (is_shub2()) \ + __addr = SH2_TIO_PHYS_TO_DMA(__addr); \ + HUB_S(_bte->bte_destination_addr, __addr); \ +}) #define BTE_CTRL_STORE(_bte, _x) \ HUB_S(_bte->bte_control_addr, (_x)) #define BTE_NOTIF_STORE(_bte, _x) \ - HUB_S(_bte->bte_notify_addr, (_x)) +({ \ + u64 __addr = ia64_tpa((_x) & ~AS_MASK); \ + if (is_shub2()) \ + __addr = SH2_TIO_PHYS_TO_DMA(__addr); \ + HUB_S(_bte->bte_notify_addr, __addr); \ +}) #define BTE_START_TRANSFER(_bte, _len, _mode) \ is_shub2() ? BTE_CTRL_STORE(_bte, IBLS_BUSY | (_mode << 24) | _len) \ diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h index a3431372c6e7..60a51a406eec 100644 --- a/include/asm-ia64/sn/intr.h +++ b/include/asm-ia64/sn/intr.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_INTR_H @@ -11,26 +11,26 @@ #include <linux/rcupdate.h> -#define SGI_UART_VECTOR (0xe9) +#define SGI_UART_VECTOR 0xe9 /* Reserved IRQs : Note, not to exceed IA64_SN2_FIRST_DEVICE_VECTOR */ -#define SGI_XPC_ACTIVATE (0x30) -#define SGI_II_ERROR (0x31) -#define SGI_XBOW_ERROR (0x32) -#define SGI_PCIASIC_ERROR (0x33) -#define SGI_ACPI_SCI_INT (0x34) -#define SGI_TIOCA_ERROR (0x35) -#define SGI_TIO_ERROR (0x36) -#define SGI_TIOCX_ERROR (0x37) -#define SGI_MMTIMER_VECTOR (0x38) -#define SGI_XPC_NOTIFY (0xe7) - -#define IA64_SN2_FIRST_DEVICE_VECTOR (0x3c) -#define IA64_SN2_LAST_DEVICE_VECTOR (0xe6) - -#define SN2_IRQ_RESERVED (0x1) -#define SN2_IRQ_CONNECTED (0x2) -#define SN2_IRQ_SHARED (0x4) +#define SGI_XPC_ACTIVATE 0x30 +#define SGI_II_ERROR 0x31 +#define SGI_XBOW_ERROR 0x32 +#define SGI_PCIASIC_ERROR 0x33 +#define SGI_ACPI_SCI_INT 0x34 +#define SGI_TIOCA_ERROR 0x35 +#define SGI_TIO_ERROR 0x36 +#define SGI_TIOCX_ERROR 0x37 +#define SGI_MMTIMER_VECTOR 0x38 +#define SGI_XPC_NOTIFY 0xe7 + +#define IA64_SN2_FIRST_DEVICE_VECTOR 0x3c +#define IA64_SN2_LAST_DEVICE_VECTOR 0xe6 + +#define SN2_IRQ_RESERVED 0x1 +#define SN2_IRQ_CONNECTED 0x2 +#define SN2_IRQ_SHARED 0x4 // The SN PROM irq struct struct sn_irq_info { diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h index e68a80853d5d..9ca642cad338 100644 --- a/include/asm-ia64/sn/sn_feature_sets.h +++ b/include/asm-ia64/sn/sn_feature_sets.h @@ -8,7 +8,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2005-2006 Silicon Graphics, Inc. All rights reserved. */ @@ -27,14 +27,12 @@ extern int sn_prom_feature_available(int id); * "false" for new features. * * Use: - * if (sn_prom_feature_available(PRF_FEATURE_XXX)) + * if (sn_prom_feature_available(PRF_XXX)) * ... */ -/* - * Example: feature XXX - */ -#define PRF_FEATURE_XXX 0 +#define PRF_PAL_CACHE_FLUSH_SAFE 0 +#define PRF_DEVICE_FLUSH_LIST 1 @@ -51,7 +49,7 @@ extern int sn_prom_feature_available(int id); * * By default, features are disabled unless explicitly enabled. */ -#define OSF_MCA_SLV_TO_OS_INIT_SLV 0 -#define OSF_FEAT_LOG_SBES 1 +#define OSF_MCA_SLV_TO_OS_INIT_SLV 0 +#define OSF_FEAT_LOG_SBES 1 #endif /* _ASM_IA64_SN_FEATURE_SETS_H */ diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h index 203945ae034e..9bd2f9bf329b 100644 --- a/include/asm-ia64/sn/xp.h +++ b/include/asm-ia64/sn/xp.h @@ -18,6 +18,7 @@ #include <linux/cache.h> #include <linux/hardirq.h> +#include <linux/mutex.h> #include <asm/sn/types.h> #include <asm/sn/bte.h> @@ -359,7 +360,7 @@ typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid, * the channel. */ struct xpc_registration { - struct semaphore sema; + struct mutex mutex; xpc_channel_func func; /* function to call */ void *key; /* pointer to user's key */ u16 nentries; /* #of msg entries in local msg queue */ diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h index 87e9cd588510..0c36928ffd8b 100644 --- a/include/asm-ia64/sn/xpc.h +++ b/include/asm-ia64/sn/xpc.h @@ -19,6 +19,8 @@ #include <linux/interrupt.h> #include <linux/sysctl.h> #include <linux/device.h> +#include <linux/mutex.h> +#include <linux/completion.h> #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/sn/bte.h> @@ -335,8 +337,7 @@ struct xpc_openclose_args { * and consumed by the intended recipient. */ struct xpc_notify { - struct semaphore sema; /* notify semaphore */ - volatile u8 type; /* type of notification */ + volatile u8 type; /* type of notification */ /* the following two fields are only used if type == XPC_N_CALL */ xpc_notify_func func; /* user's notify function */ @@ -465,8 +466,8 @@ struct xpc_channel { xpc_channel_func func; /* user's channel function */ void *key; /* pointer to user's key */ - struct semaphore msg_to_pull_sema; /* next msg to pull serialization */ - struct semaphore wdisconnect_sema; /* wait for channel disconnect */ + struct mutex msg_to_pull_mutex; /* next msg to pull serialization */ + struct completion wdisconnect_wait; /* wait for channel disconnect */ struct xpc_openclose_args *local_openclose_args; /* args passed on */ /* opening or closing of channel */ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 80c5a234e259..062538715623 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -249,32 +249,7 @@ extern void ia64_load_extra (struct task_struct *task); # define switch_to(prev,next,last) __switch_to(prev, next, last) #endif -/* - * On IA-64, we don't want to hold the runqueue's lock during the low-level context-switch, - * because that could cause a deadlock. Here is an example by Erich Focht: - * - * Example: - * CPU#0: - * schedule() - * -> spin_lock_irq(&rq->lock) - * -> context_switch() - * -> wrap_mmu_context() - * -> read_lock(&tasklist_lock) - * - * CPU#1: - * sys_wait4() or release_task() or forget_original_parent() - * -> write_lock(&tasklist_lock) - * -> do_notify_parent() - * -> wake_up_parent() - * -> try_to_wake_up() - * -> spin_lock_irq(&parent_rq->lock) - * - * If the parent's rq happens to be on CPU#0, we'll wait for the rq->lock - * of that CPU which will not be released, because there we wait for the - * tasklist_lock to become available. - */ #define __ARCH_WANT_UNLOCKED_CTXSW - #define ARCH_HAS_PREFETCH_SWITCH_STACK #define ia64_platform_is(x) (strcmp(x, platform_name) == 0) diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index d8aae4da3978..3ee19dfa46df 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -18,6 +18,10 @@ #include <asm/smp.h> #ifdef CONFIG_NUMA + +/* Nodes w/o CPUs are preferred for memory allocations, see build_zonelists */ +#define PENALTY_FOR_NODE_WITH_CPUS 255 + /* * Returns the number of the node containing CPU 'cpu' */ @@ -98,6 +102,13 @@ void build_cpu_to_node_map(void); #endif /* CONFIG_NUMA */ +#ifdef CONFIG_SMP +#define topology_physical_package_id(cpu) (cpu_data(cpu)->socket_id) +#define topology_core_id(cpu) (cpu_data(cpu)->core_id) +#define topology_core_siblings(cpu) (cpu_core_map[cpu]) +#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) +#endif + #include <asm-generic/topology.h> #endif /* _ASM_IA64_TOPOLOGY_H */ diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 962f9bd1bdff..019956c613e4 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -270,12 +270,27 @@ #define __NR_inotify_add_watch 1278 #define __NR_inotify_rm_watch 1279 #define __NR_migrate_pages 1280 +#define __NR_openat 1281 +#define __NR_mkdirat 1282 +#define __NR_mknodat 1283 +#define __NR_fchownat 1284 +#define __NR_futimesat 1285 +#define __NR_newfstatat 1286 +#define __NR_unlinkat 1287 +#define __NR_renameat 1288 +#define __NR_linkat 1289 +#define __NR_symlinkat 1290 +#define __NR_readlinkat 1291 +#define __NR_fchmodat 1292 +#define __NR_faccessat 1293 +/* 1294, 1295 reserved for pselect/ppoll */ +#define __NR_unshare 1296 #ifdef __KERNEL__ #include <linux/config.h> -#define NR_syscalls 270 /* length of syscall table */ +#define NR_syscalls 273 /* length of syscall table */ #define __ARCH_WANT_SYS_RT_SIGACTION diff --git a/include/asm-m68knommu/hardirq.h b/include/asm-m68knommu/hardirq.h index e8659e739a64..476180f4cba2 100644 --- a/include/asm-m68knommu/hardirq.h +++ b/include/asm-m68knommu/hardirq.h @@ -4,6 +4,7 @@ #include <linux/config.h> #include <linux/cache.h> #include <linux/threads.h> +#include <asm/irq.h> typedef struct { unsigned int __softirq_pending; diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h index 2e7e651c3e3f..1ce0518ace2e 100644 --- a/include/asm-mips/abi.h +++ b/include/asm-mips/abi.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005 by Ralf Baechle + * Copyright (C) 2005, 06 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2005 MIPS Technologies, Inc. */ #ifndef _ASM_ABI_H @@ -13,7 +13,7 @@ #include <asm/siginfo.h> struct mips_abi { - int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs); + void (* const do_signal)(struct pt_regs *regs); int (* const setup_frame)(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set); diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index 3b0c8aaf6e8b..8e802059fe67 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h @@ -644,20 +644,26 @@ static inline unsigned long ffz(unsigned long word) } /* - * flz - find last zero in word. + * fls - find last bit set. * @word: The word to search * - * Returns 0..SZLONG-1 - * Undefined if no zero exists, so code should check against ~0UL first. + * Returns 1..SZLONG + * Returns 0 if no bit exists */ -static inline unsigned long flz(unsigned long word) +static inline unsigned long fls(unsigned long word) { -#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) - return __ilog2(~word); -#else #ifdef CONFIG_32BIT - int r = 31, s; - word = ~word; +#ifdef CONFIG_CPU_MIPS32 + __asm__ ("clz %0, %1" : "=r" (word) : "r" (word)); + + return 32 - word; +#else + { + int r = 32, s; + + if (word == 0) + return 0; + s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s; s = 8; if ((word & 0xff000000)) s = 0; r -= s; word <<= s; s = 4; if ((word & 0xf0000000)) s = 0; r -= s; word <<= s; @@ -665,10 +671,23 @@ static inline unsigned long flz(unsigned long word) s = 1; if ((word & 0x80000000)) s = 0; r -= s; return r; + } #endif +#endif /* CONFIG_32BIT */ + #ifdef CONFIG_64BIT - int r = 63, s; - word = ~word; +#ifdef CONFIG_CPU_MIPS64 + + __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word)); + + return 64 - word; +#else + { + int r = 64, s; + + if (word == 0) + return 0; + s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s; s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s; s = 8; if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s; @@ -677,24 +696,11 @@ static inline unsigned long flz(unsigned long word) s = 1; if ((word & 0x8000000000000000UL)) s = 0; r -= s; return r; + } #endif -#endif +#endif /* CONFIG_64BIT */ } -/* - * fls - find last bit set. - * @word: The word to search - * - * Returns 1..SZLONG - * Returns 0 if no bit exists - */ -static inline unsigned long fls(unsigned long word) -{ - if (word == 0) - return 0; - - return flz(~word) + 1; -} #define fls64(x) generic_fls64(x) /* diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h index d1fe9e5c62e4..584f8128fffd 100644 --- a/include/asm-mips/byteorder.h +++ b/include/asm-mips/byteorder.h @@ -8,10 +8,39 @@ #ifndef _ASM_BYTEORDER_H #define _ASM_BYTEORDER_H +#include <linux/config.h> +#include <linux/compiler.h> #include <asm/types.h> #ifdef __GNUC__ +#ifdef CONFIG_CPU_MIPSR2 + +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__( + " wsbh %0, %1 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch__swab16(x) ___arch__swab16(x) + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ + __asm__( + " wsbh %0, %1 \n" + " rotr %0, %0, 16 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch__swab32(x) ___arch__swab32(x) + +#endif /* CONFIG_CPU_MIPSR2 */ + #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __BYTEORDER_HAS_U64__ # define __SWAB_64_THRU_32__ diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index a18ba2edc0b6..aeae9fabf4a9 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h @@ -49,8 +49,7 @@ static inline void flush_dcache_page(struct page *page) extern void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); -extern void (*flush_icache_range)(unsigned long __user start, - unsigned long __user end); +extern void (*flush_icache_range)(unsigned long start, unsigned long end); #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h index 2fc90632f88c..6111a0ce58c4 100644 --- a/include/asm-mips/hazards.h +++ b/include/asm-mips/hazards.h @@ -100,7 +100,7 @@ __asm__( " .macro _ssnop \n\t" - " sll $0, $2, 1 \n\t" + " sll $0, $0, 1 \n\t" " .endm \n\t" " \n\t" " .macro _ehb \n\t" diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h index abdf54ee64cf..774348734fa0 100644 --- a/include/asm-mips/interrupt.h +++ b/include/asm-mips/interrupt.h @@ -47,6 +47,17 @@ static inline void local_irq_enable(void) * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs * no nops at all. */ +/* + * For TX49, operating only IE bit is not enough. + * + * If mfc0 $12 follows store and the mfc0 is last instruction of a + * page and fetching the next instruction causes TLB miss, the result + * of the mfc0 might wrongly contain EXL bit. + * + * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 + * + * Workaround: mask EXL bit of the result or place a nop before mfc0. + */ __asm__ ( " .macro local_irq_disable\n" " .set push \n" @@ -55,8 +66,8 @@ __asm__ ( " di \n" #else " mfc0 $1,$12 \n" - " ori $1,1 \n" - " xori $1,1 \n" + " ori $1,0x1f \n" + " xori $1,0x1f \n" " .set noreorder \n" " mtc0 $1,$12 \n" #endif @@ -96,8 +107,8 @@ __asm__ ( " andi \\result, 1 \n" #else " mfc0 \\result, $12 \n" - " ori $1, \\result, 1 \n" - " xori $1, 1 \n" + " ori $1, \\result, 0x1f \n" + " xori $1, 0x1f \n" " .set noreorder \n" " mtc0 $1, $12 \n" #endif @@ -114,6 +125,7 @@ __asm__ __volatile__( \ __asm__ ( " .macro local_irq_restore flags \n" + " .set push \n" " .set noreorder \n" " .set noat \n" #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) @@ -135,14 +147,13 @@ __asm__ ( #else " mfc0 $1, $12 \n" " andi \\flags, 1 \n" - " ori $1, 1 \n" - " xori $1, 1 \n" + " ori $1, 0x1f \n" + " xori $1, 0x1f \n" " or \\flags, $1 \n" " mtc0 \\flags, $12 \n" #endif " irq_disable_hazard \n" - " .set at \n" - " .set reorder \n" + " .set pop \n" " .endm \n"); #define local_irq_restore(flags) \ diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h index d42685747e7d..5a4c8a54b8f4 100644 --- a/include/asm-mips/io.h +++ b/include/asm-mips/io.h @@ -18,7 +18,6 @@ #include <linux/types.h> #include <asm/addrspace.h> -#include <asm/bug.h> #include <asm/byteorder.h> #include <asm/cpu.h> #include <asm/cpu-features.h> @@ -57,38 +56,38 @@ * variations of functions: non-prefixed ones that preserve the value * and prefixed ones that preserve byte addresses. The latters are * typically used for moving raw data between a peripheral and memory (cf. - * string I/O functions), hence the "mem_" prefix. + * string I/O functions), hence the "__mem_" prefix. */ #if defined(CONFIG_SWAP_IO_SPACE) # define ioswabb(x) (x) -# define mem_ioswabb(x) (x) +# define __mem_ioswabb(x) (x) # ifdef CONFIG_SGI_IP22 /* * IP22 seems braindead enough to swap 16bits values in hardware, but * not 32bits. Go figure... Can't tell without documentation. */ # define ioswabw(x) (x) -# define mem_ioswabw(x) le16_to_cpu(x) +# define __mem_ioswabw(x) le16_to_cpu(x) # else # define ioswabw(x) le16_to_cpu(x) -# define mem_ioswabw(x) (x) +# define __mem_ioswabw(x) (x) # endif # define ioswabl(x) le32_to_cpu(x) -# define mem_ioswabl(x) (x) +# define __mem_ioswabl(x) (x) # define ioswabq(x) le64_to_cpu(x) -# define mem_ioswabq(x) (x) +# define __mem_ioswabq(x) (x) #else # define ioswabb(x) (x) -# define mem_ioswabb(x) (x) +# define __mem_ioswabb(x) (x) # define ioswabw(x) (x) -# define mem_ioswabw(x) cpu_to_le16(x) +# define __mem_ioswabw(x) cpu_to_le16(x) # define ioswabl(x) (x) -# define mem_ioswabl(x) cpu_to_le32(x) +# define __mem_ioswabl(x) cpu_to_le32(x) # define ioswabq(x) (x) -# define mem_ioswabq(x) cpu_to_le32(x) +# define __mem_ioswabq(x) cpu_to_le32(x) #endif @@ -343,7 +342,7 @@ static inline void pfx##write##bwlq(type val, \ BUG(); \ } \ \ -static inline type pfx##read##bwlq(volatile void __iomem *mem) \ +static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ { \ volatile type *__mem; \ type __val; \ @@ -418,7 +417,7 @@ __BUILD_MEMORY_SINGLE(bus, bwlq, type, 1) \ __BUILD_MEMORY_PFX(__raw_, bwlq, type) \ __BUILD_MEMORY_PFX(, bwlq, type) \ -__BUILD_MEMORY_PFX(mem_, bwlq, type) \ +__BUILD_MEMORY_PFX(__mem_, bwlq, type) \ BUILDIO_MEM(b, u8) BUILDIO_MEM(w, u16) @@ -431,7 +430,7 @@ BUILDIO_MEM(q, u64) #define BUILDIO_IOPORT(bwlq, type) \ __BUILD_IOPORT_PFX(, bwlq, type) \ - __BUILD_IOPORT_PFX(mem_, bwlq, type) + __BUILD_IOPORT_PFX(__mem_, bwlq, type) BUILDIO_IOPORT(b, u8) BUILDIO_IOPORT(w, u16) @@ -465,7 +464,7 @@ static inline void writes##bwlq(volatile void __iomem *mem, \ const volatile type *__addr = addr; \ \ while (count--) { \ - mem_write##bwlq(*__addr, mem); \ + __mem_write##bwlq(*__addr, mem); \ __addr++; \ } \ } \ @@ -476,7 +475,7 @@ static inline void reads##bwlq(volatile void __iomem *mem, void *addr, \ volatile type *__addr = addr; \ \ while (count--) { \ - *__addr = mem_read##bwlq(mem); \ + *__addr = __mem_read##bwlq(mem); \ __addr++; \ } \ } @@ -489,7 +488,7 @@ static inline void outs##bwlq(unsigned long port, const void *addr, \ const volatile type *__addr = addr; \ \ while (count--) { \ - mem_out##bwlq(*__addr, port); \ + __mem_out##bwlq(*__addr, port); \ __addr++; \ } \ } \ @@ -500,7 +499,7 @@ static inline void ins##bwlq(unsigned long port, void *addr, \ volatile type *__addr = addr; \ \ while (count--) { \ - *__addr = mem_in##bwlq(port); \ + *__addr = __mem_in##bwlq(port); \ __addr++; \ } \ } diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index 8e1d7ed7d8e3..4686e17c206c 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -1198,7 +1198,11 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]; /* UARTS 0-3 */ #define UART_BASE UART0_ADDR +#ifdef CONFIG_SOC_AU1200 +#define UART_DEBUG_BASE UART1_ADDR +#else #define UART_DEBUG_BASE UART3_ADDR +#endif #define UART_RX 0 /* Receive buffer */ #define UART_TX 4 /* Transmit buffer */ diff --git a/include/asm-mips/cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h index 78e1df2095fb..78e1df2095fb 100644 --- a/include/asm-mips/cobalt/cobalt.h +++ b/include/asm-mips/mach-cobalt/cobalt.h diff --git a/include/asm-mips/mach-cobalt/cpu-feature-overrides.h b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h new file mode 100644 index 000000000000..ace8c5ef9701 --- /dev/null +++ b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h @@ -0,0 +1,56 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef __ASM_COBALT_CPU_FEATURE_OVERRIDES_H +#define __ASM_COBALT_CPU_FEATURE_OVERRIDES_H + +#include <linux/config.h> + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 1 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_watch 0 +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 0 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_subset_pcaches 0 +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 0 + +#ifdef CONFIG_64BIT +#define cpu_has_llsc 0 +#else +#define cpu_has_llsc 1 +#endif + +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define cpu_has_vtag_icache 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_icache_snoops_remote_store 0 +#define cpu_has_dsp 0 + +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#endif /* __ASM_COBALT_CPU_FEATURE_OVERRIDES_H */ diff --git a/include/asm-mips/cobalt/mach-gt64120.h b/include/asm-mips/mach-cobalt/mach-gt64120.h index 587fc4378f44..587fc4378f44 100644 --- a/include/asm-mips/cobalt/mach-gt64120.h +++ b/include/asm-mips/mach-cobalt/mach-gt64120.h diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h index b80c30725cf6..36070b5654ab 100644 --- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h +++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h @@ -18,7 +18,7 @@ * so, for 64bit IP32 kernel we just don't use ll/sc. * This does not affect luserland. */ -#if defined(CONFIG_CPU_R5000) && defined(CONFIG_64BIT) +#if (defined(CONFIG_CPU_R5000) || defined(CONFIG_CPU_NEVADA)) && defined(CONFIG_64BIT) #define cpu_has_llsc 0 #else #define cpu_has_llsc 1 diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h index a5ea9d828aee..cc53196efa40 100644 --- a/include/asm-mips/r4kcache.h +++ b/include/asm-mips/r4kcache.h @@ -166,123 +166,6 @@ static inline void invalidate_tcache_page(unsigned long addr) : "r" (base), \ "i" (op)); -static inline void blast_dcache16(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.dcache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; - unsigned long ws_end = current_cpu_data.dcache.ways << - current_cpu_data.dcache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Writeback_Inv_D); -} - -static inline void blast_dcache16_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - - do { - cache16_unroll32(start,Hit_Writeback_Inv_D); - start += 0x200; - } while (start < end); -} - -static inline void blast_dcache16_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; - unsigned long ws_end = current_cpu_data.dcache.ways << - current_cpu_data.dcache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Writeback_Inv_D); -} - -static inline void blast_icache16(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.icache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_icache16_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - - do { - cache16_unroll32(start,Hit_Invalidate_I); - start += 0x200; - } while (start < end); -} - -static inline void blast_icache16_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_scache16(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.scache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - -static inline void blast_scache16_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = page + PAGE_SIZE; - - do { - cache16_unroll32(start,Hit_Writeback_Inv_SD); - start += 0x200; - } while (start < end); -} - -static inline void blast_scache16_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) - cache16_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - #define cache32_unroll32(base,op) \ __asm__ __volatile__( \ " .set push \n" \ @@ -309,123 +192,6 @@ static inline void blast_scache16_page_indexed(unsigned long page) : "r" (base), \ "i" (op)); -static inline void blast_dcache32(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.dcache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; - unsigned long ws_end = current_cpu_data.dcache.ways << - current_cpu_data.dcache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Writeback_Inv_D); -} - -static inline void blast_dcache32_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - - do { - cache32_unroll32(start,Hit_Writeback_Inv_D); - start += 0x400; - } while (start < end); -} - -static inline void blast_dcache32_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; - unsigned long ws_end = current_cpu_data.dcache.ways << - current_cpu_data.dcache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Writeback_Inv_D); -} - -static inline void blast_icache32(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.icache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_icache32_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - - do { - cache32_unroll32(start,Hit_Invalidate_I); - start += 0x400; - } while (start < end); -} - -static inline void blast_icache32_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_scache32(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.scache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - -static inline void blast_scache32_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = page + PAGE_SIZE; - - do { - cache32_unroll32(start,Hit_Writeback_Inv_SD); - start += 0x400; - } while (start < end); -} - -static inline void blast_scache32_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) - cache32_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - #define cache64_unroll32(base,op) \ __asm__ __volatile__( \ " .set push \n" \ @@ -452,84 +218,6 @@ static inline void blast_scache32_page_indexed(unsigned long page) : "r" (base), \ "i" (op)); -static inline void blast_icache64(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.icache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x800) - cache64_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_icache64_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - - do { - cache64_unroll32(start,Hit_Invalidate_I); - start += 0x800; - } while (start < end); -} - -static inline void blast_icache64_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; - unsigned long ws_end = current_cpu_data.icache.ways << - current_cpu_data.icache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x800) - cache64_unroll32(addr|ws,Index_Invalidate_I); -} - -static inline void blast_scache64(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.scache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x800) - cache64_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - -static inline void blast_scache64_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = page + PAGE_SIZE; - - do { - cache64_unroll32(start,Hit_Writeback_Inv_SD); - start += 0x800; - } while (start < end); -} - -static inline void blast_scache64_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x800) - cache64_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - #define cache128_unroll32(base,op) \ __asm__ __volatile__( \ " .set push \n" \ @@ -556,43 +244,55 @@ static inline void blast_scache64_page_indexed(unsigned long page) : "r" (base), \ "i" (op)); -static inline void blast_scache128(void) -{ - unsigned long start = INDEX_BASE; - unsigned long end = start + current_cpu_data.scache.waysize; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x1000) - cache128_unroll32(addr|ws,Index_Writeback_Inv_SD); -} - -static inline void blast_scache128_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = page + PAGE_SIZE; - - do { - cache128_unroll32(start,Hit_Writeback_Inv_SD); - start += 0x1000; - } while (start < end); -} - -static inline void blast_scache128_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = start + PAGE_SIZE; - unsigned long ws_inc = 1UL << current_cpu_data.scache.waybit; - unsigned long ws_end = current_cpu_data.scache.ways << - current_cpu_data.scache.waybit; - unsigned long ws, addr; - - for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x1000) - cache128_unroll32(addr|ws,Index_Writeback_Inv_SD); -} +/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \ +static inline void blast_##pfx##cache##lsize(void) \ +{ \ + unsigned long start = INDEX_BASE; \ + unsigned long end = start + current_cpu_data.desc.waysize; \ + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ + unsigned long ws_end = current_cpu_data.desc.ways << \ + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws,indexop); \ +} \ + \ +static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ +{ \ + unsigned long start = page; \ + unsigned long end = page + PAGE_SIZE; \ + \ + do { \ + cache##lsize##_unroll32(start,hitop); \ + start += lsize * 32; \ + } while (start < end); \ +} \ + \ +static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ +{ \ + unsigned long start = page; \ + unsigned long end = start + PAGE_SIZE; \ + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ + unsigned long ws_end = current_cpu_data.desc.ways << \ + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws,indexop); \ +} + +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) #endif /* _ASM_R4KCACHE_H */ diff --git a/include/asm-mips/reboot.h b/include/asm-mips/reboot.h index 2f10ebcbe141..e48c0bfab257 100644 --- a/include/asm-mips/reboot.h +++ b/include/asm-mips/reboot.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1997, 1999, 2001 by Ralf Baechle + * Copyright (C) 1997, 1999, 2001, 06 by Ralf Baechle * Copyright (C) 2001 MIPS Technologies, Inc. */ #ifndef _ASM_REBOOT_H @@ -11,6 +11,5 @@ extern void (*_machine_restart)(char *command); extern void (*_machine_halt)(void); -extern void (*_machine_power_off)(void); #endif /* _ASM_REBOOT_H */ diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h index 5a06f6d13899..907da600fddd 100644 --- a/include/asm-mips/string.h +++ b/include/asm-mips/string.h @@ -141,26 +141,4 @@ extern void *memcpy(void *__to, __const__ void *__from, size_t __n); #define __HAVE_ARCH_MEMMOVE extern void *memmove(void *__dest, __const__ void *__src, size_t __n); -#ifdef CONFIG_32BIT -#define __HAVE_ARCH_MEMSCAN -static __inline__ void *memscan(void *__addr, int __c, size_t __size) -{ - char *__end = (char *)__addr + __size; - unsigned char __uc = (unsigned char) __c; - - __asm__(".set\tpush\n\t" - ".set\tnoat\n\t" - ".set\treorder\n\t" - "1:\tbeq\t%0,%1,2f\n\t" - "addiu\t%0,1\n\t" - "lbu\t$1,-1(%0)\n\t" - "bne\t$1,%z4,1b\n" - "2:\t.set\tpop" - : "=r" (__addr), "=r" (__end) - : "0" (__addr), "1" (__end), "Jr" (__uc)); - - return __addr; -} -#endif /* CONFIG_32BIT */ - #endif /* _ASM_STRING_H */ diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index 1612b3fe1080..fa193f861e71 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h @@ -114,6 +114,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ #define TIF_SECCOMP 5 /* secure computing */ +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 18 @@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1<<TIF_SECCOMP) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) diff --git a/include/asm-mips/tx4927/tx4927.h b/include/asm-mips/tx4927/tx4927.h index 3bb7f0087d68..de85bd2245f7 100644 --- a/include/asm-mips/tx4927/tx4927.h +++ b/include/asm-mips/tx4927/tx4927.h @@ -2,7 +2,7 @@ * Author: MontaVista Software, Inc. * source@mvista.com * - * Copyright 2001-2002 MontaVista Software Inc. + * Copyright 2001-2006 MontaVista Software Inc. * * 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 @@ -30,10 +30,10 @@ #include <asm/tx4927/tx4927_mips.h> /* - This register naming came from the intergrate cpu/controoler name TX4927 + This register naming came from the integrated CPU/controller name TX4927 followed by the device name from table 4.2.2 on page 4-3 and then followed by the register name from table 4.2.3 on pages 4-4 to 4-8. The manaul - used is "TMPR4927BT Preliminary Rev 0.1 20.Jul.2001". + used was "TMPR4927BT Preliminary Rev 0.1 20.Jul.2001". */ #define TX4927_SIO_0_BASE @@ -251,8 +251,8 @@ /* TX4927 Timer 0 (32-bit registers) */ #define TX4927_TMR0_BASE 0xf000 -#define TX4927_TMR0_TMTCR0 0xf004 -#define TX4927_TMR0_TMTISR0 0xf008 +#define TX4927_TMR0_TMTCR0 0xf000 +#define TX4927_TMR0_TMTISR0 0xf004 #define TX4927_TMR0_TMCPRA0 0xf008 #define TX4927_TMR0_TMCPRB0 0xf00c #define TX4927_TMR0_TMITMR0 0xf010 @@ -264,8 +264,8 @@ /* TX4927 Timer 1 (32-bit registers) */ #define TX4927_TMR1_BASE 0xf100 -#define TX4927_TMR1_TMTCR1 0xf104 -#define TX4927_TMR1_TMTISR1 0xf108 +#define TX4927_TMR1_TMTCR1 0xf100 +#define TX4927_TMR1_TMTISR1 0xf104 #define TX4927_TMR1_TMCPRA1 0xf108 #define TX4927_TMR1_TMCPRB1 0xf10c #define TX4927_TMR1_TMITMR1 0xf110 @@ -277,13 +277,12 @@ /* TX4927 Timer 2 (32-bit registers) */ #define TX4927_TMR2_BASE 0xf200 -#define TX4927_TMR2_TMTCR2 0xf104 -#define TX4927_TMR2_TMTISR2 0xf208 +#define TX4927_TMR2_TMTCR2 0xf200 +#define TX4927_TMR2_TMTISR2 0xf204 #define TX4927_TMR2_TMCPRA2 0xf208 -#define TX4927_TMR2_TMCPRB2 0xf20c #define TX4927_TMR2_TMITMR2 0xf210 #define TX4927_TMR2_TMCCDR2 0xf220 -#define TX4927_TMR2_TMPGMR2 0xf230 +#define TX4927_TMR2_TMWTMR2 0xf240 #define TX4927_TMR2_TMTRR2 0xf2f0 #define TX4927_TMR2_LIMIT 0xf2ff diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h index 165f6b8b217f..66c064690f41 100644 --- a/include/asm-mips/tx4927/tx4927_pci.h +++ b/include/asm-mips/tx4927/tx4927_pci.h @@ -253,6 +253,16 @@ struct tx4927_pcic_reg { #define TX4927_CCFG_PCIDIVMODE_5 0x00001000 #define TX4927_CCFG_PCIDIVMODE_6 0x00001800 +#define TX4937_CCFG_PCIDIVMODE_MASK 0x00001c00 +#define TX4937_CCFG_PCIDIVMODE_8 0x00000000 +#define TX4937_CCFG_PCIDIVMODE_4 0x00000400 +#define TX4937_CCFG_PCIDIVMODE_9 0x00000800 +#define TX4937_CCFG_PCIDIVMODE_4_5 0x00000c00 +#define TX4937_CCFG_PCIDIVMODE_10 0x00001000 +#define TX4937_CCFG_PCIDIVMODE_5 0x00001400 +#define TX4937_CCFG_PCIDIVMODE_11 0x00001800 +#define TX4937_CCFG_PCIDIVMODE_5_5 0x00001c00 + /* PCFG : Pin Configuration */ #define TX4927_PCFG_PCICLKEN_ALL 0x003f0000 #define TX4927_PCFG_PCICLKEN(ch) (0x00010000<<(ch)) diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h index 41bb96bb2120..91d813a37823 100644 --- a/include/asm-mips/uaccess.h +++ b/include/asm-mips/uaccess.h @@ -202,49 +202,49 @@ struct __large_struct { unsigned long buf[100]; }; * Yuck. We need two variants, one for 64bit operation and one * for 32 bit mode and old iron. */ -#ifdef __mips64 -#define __GET_USER_DW(ptr) __get_user_asm("ld", ptr) -#else -#define __GET_USER_DW(ptr) __get_user_asm_ll32(ptr) +#ifdef CONFIG_32BIT +#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr) +#endif +#ifdef CONFIG_64BIT +#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr) #endif -#define __get_user_nocheck(x,ptr,size) \ -({ \ - __typeof(*(ptr)) __gu_val = (__typeof(*(ptr))) 0; \ - long __gu_err = 0; \ - \ +extern void __get_user_unknown(void); + +#define __get_user_common(val, size, ptr) \ +do { \ switch (size) { \ - case 1: __get_user_asm("lb", ptr); break; \ - case 2: __get_user_asm("lh", ptr); break; \ - case 4: __get_user_asm("lw", ptr); break; \ - case 8: __GET_USER_DW(ptr); break; \ + case 1: __get_user_asm(val, "lb", ptr); break; \ + case 2: __get_user_asm(val, "lh", ptr); break; \ + case 4: __get_user_asm(val, "lw", ptr); break; \ + case 8: __GET_USER_DW(val, ptr); break; \ default: __get_user_unknown(); break; \ } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ +} while (0) + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err; \ + \ + __get_user_common((x), size, ptr); \ __gu_err; \ }) #define __get_user_check(x,ptr,size) \ ({ \ - const __typeof__(*(ptr)) __user * __gu_addr = (ptr); \ - __typeof__(*(ptr)) __gu_val = 0; \ long __gu_err = -EFAULT; \ + const void __user * __gu_ptr = (ptr); \ + \ + if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ + __get_user_common((x), size, __gu_ptr); \ \ - if (likely(access_ok(VERIFY_READ, __gu_addr, size))) { \ - switch (size) { \ - case 1: __get_user_asm("lb", __gu_addr); break; \ - case 2: __get_user_asm("lh", __gu_addr); break; \ - case 4: __get_user_asm("lw", __gu_addr); break; \ - case 8: __GET_USER_DW(__gu_addr); break; \ - default: __get_user_unknown(); break; \ - } \ - } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) -#define __get_user_asm(insn, addr) \ +#define __get_user_asm(val, insn, addr) \ { \ + long __gu_tmp; \ + \ __asm__ __volatile__( \ "1: " insn " %1, %3 \n" \ "2: \n" \ @@ -255,14 +255,16 @@ struct __large_struct { unsigned long buf[100]; }; " .section __ex_table,\"a\" \n" \ " "__UA_ADDR "\t1b, 3b \n" \ " .previous \n" \ - : "=r" (__gu_err), "=r" (__gu_val) \ + : "=r" (__gu_err), "=r" (__gu_tmp) \ : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ + \ + (val) = (__typeof__(val)) __gu_tmp; \ } /* * Get a long long 64 using 32 bit registers. */ -#define __get_user_asm_ll32(addr) \ +#define __get_user_asm_ll32(val, addr) \ { \ __asm__ __volatile__( \ "1: lw %1, (%3) \n" \ @@ -278,21 +280,20 @@ struct __large_struct { unsigned long buf[100]; }; " " __UA_ADDR " 1b, 4b \n" \ " " __UA_ADDR " 2b, 4b \n" \ " .previous \n" \ - : "=r" (__gu_err), "=&r" (__gu_val) \ + : "=r" (__gu_err), "=&r" (val) \ : "0" (0), "r" (addr), "i" (-EFAULT)); \ } -extern void __get_user_unknown(void); - /* * Yuck. We need two variants, one for 64bit operation and one * for 32 bit mode and old iron. */ -#ifdef __mips64 -#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr) -#else +#ifdef CONFIG_32BIT #define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr) #endif +#ifdef CONFIG_64BIT +#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr) +#endif #define __put_user_nocheck(x,ptr,size) \ ({ \ diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index 89ea8b60e945..e7ff9b187783 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -307,17 +307,33 @@ #define __NR_inotify_init (__NR_Linux + 284) #define __NR_inotify_add_watch (__NR_Linux + 285) #define __NR_inotify_rm_watch (__NR_Linux + 286) - +#define __NR_migrate_pages (__NR_Linux + 287) +#define __NR_openat (__NR_Linux + 288) +#define __NR_mkdirat (__NR_Linux + 289) +#define __NR_mknodat (__NR_Linux + 290) +#define __NR_fchownat (__NR_Linux + 291) +#define __NR_futimesat (__NR_Linux + 292) +#define __NR_newfstatat (__NR_Linux + 293) +#define __NR_unlinkat (__NR_Linux + 294) +#define __NR_renameat (__NR_Linux + 295) +#define __NR_linkat (__NR_Linux + 296) +#define __NR_symlinkat (__NR_Linux + 297) +#define __NR_readlinkat (__NR_Linux + 298) +#define __NR_fchmodat (__NR_Linux + 299) +#define __NR_faccessat (__NR_Linux + 300) +#define __NR_pselect6 (__NR_Linux + 301) +#define __NR_ppoll (__NR_Linux + 302) +#define __NR_unshare (__NR_Linux + 303) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 286 +#define __NR_Linux_syscalls 303 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 283 +#define __NR_O32_Linux_syscalls 303 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -571,16 +587,33 @@ #define __NR_inotify_init (__NR_Linux + 243) #define __NR_inotify_add_watch (__NR_Linux + 244) #define __NR_inotify_rm_watch (__NR_Linux + 245) +#define __NR_migrate_pages (__NR_Linux + 246) +#define __NR_openat (__NR_Linux + 247) +#define __NR_mkdirat (__NR_Linux + 248) +#define __NR_mknodat (__NR_Linux + 249) +#define __NR_fchownat (__NR_Linux + 250) +#define __NR_futimesat (__NR_Linux + 251) +#define __NR_newfstatat (__NR_Linux + 252) +#define __NR_unlinkat (__NR_Linux + 253) +#define __NR_renameat (__NR_Linux + 254) +#define __NR_linkat (__NR_Linux + 255) +#define __NR_symlinkat (__NR_Linux + 256) +#define __NR_readlinkat (__NR_Linux + 257) +#define __NR_fchmodat (__NR_Linux + 258) +#define __NR_faccessat (__NR_Linux + 259) +#define __NR_pselect6 (__NR_Linux + 260) +#define __NR_ppoll (__NR_Linux + 261) +#define __NR_unshare (__NR_Linux + 262) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 245 +#define __NR_Linux_syscalls 262 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 242 +#define __NR_64_Linux_syscalls 262 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -838,16 +871,33 @@ #define __NR_inotify_init (__NR_Linux + 247) #define __NR_inotify_add_watch (__NR_Linux + 248) #define __NR_inotify_rm_watch (__NR_Linux + 249) +#define __NR_migrate_pages (__NR_Linux + 250) +#define __NR_openat (__NR_Linux + 251) +#define __NR_mkdirat (__NR_Linux + 252) +#define __NR_mknodat (__NR_Linux + 253) +#define __NR_fchownat (__NR_Linux + 254) +#define __NR_futimesat (__NR_Linux + 255) +#define __NR_newfstatat (__NR_Linux + 256) +#define __NR_unlinkat (__NR_Linux + 257) +#define __NR_renameat (__NR_Linux + 258) +#define __NR_linkat (__NR_Linux + 259) +#define __NR_symlinkat (__NR_Linux + 260) +#define __NR_readlinkat (__NR_Linux + 261) +#define __NR_fchmodat (__NR_Linux + 262) +#define __NR_faccessat (__NR_Linux + 263) +#define __NR_pselect6 (__NR_Linux + 264) +#define __NR_ppoll (__NR_Linux + 265) +#define __NR_unshare (__NR_Linux + 266) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 249 +#define __NR_Linux_syscalls 266 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 246 +#define __NR_N32_Linux_syscalls 266 #ifndef __ASSEMBLY__ diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index 2ca56d34aaad..4dc7253ff5d0 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h @@ -1,9 +1,13 @@ +/* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2006 Kyle McMartin <kyle@parisc-linux.org> + */ + #ifndef _ASM_PARISC_ATOMIC_H_ #define _ASM_PARISC_ATOMIC_H_ #include <linux/config.h> +#include <linux/types.h> #include <asm/system.h> -/* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>. */ /* * Atomic operations that C can't guarantee us. Useful for @@ -46,15 +50,6 @@ extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned; # define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0) #endif -/* Note that we need not lock read accesses - aligned word writes/reads - * are atomic, so a reader never sees unconsistent values. - * - * Cache-line alignment would conflict with, for example, linux/module.h - */ - -typedef struct { volatile int counter; } atomic_t; - - /* This should get optimized out since it's never called. ** Or get a link error if xchg is used "wrong". */ @@ -69,10 +64,9 @@ extern unsigned long __xchg64(unsigned long, unsigned long *); #endif /* optimizer better get rid of switch since size is a constant */ -static __inline__ unsigned long __xchg(unsigned long x, __volatile__ void * ptr, - int size) +static __inline__ unsigned long +__xchg(unsigned long x, __volatile__ void * ptr, int size) { - switch(size) { #ifdef __LP64__ case 8: return __xchg64(x,(unsigned long *) ptr); @@ -129,7 +123,13 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) (unsigned long)_n_, sizeof(*(ptr))); \ }) +/* Note that we need not lock read accesses - aligned word writes/reads + * are atomic, so a reader never sees unconsistent values. + * + * Cache-line alignment would conflict with, for example, linux/module.h + */ +typedef struct { volatile int counter; } atomic_t; /* It's possible to reduce all atomic operations to either * __atomic_add_return, atomic_set and atomic_read (the latter @@ -210,12 +210,66 @@ static __inline__ int atomic_read(const atomic_t *v) #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) -#define ATOMIC_INIT(i) { (i) } +#define ATOMIC_INIT(i) ((atomic_t) { (i) }) #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() +#ifdef __LP64__ + +typedef struct { volatile s64 counter; } atomic64_t; + +#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) + +static __inline__ int +__atomic64_add_return(s64 i, atomic64_t *v) +{ + int ret; + unsigned long flags; + _atomic_spin_lock_irqsave(v, flags); + + ret = (v->counter += i); + + _atomic_spin_unlock_irqrestore(v, flags); + return ret; +} + +static __inline__ void +atomic64_set(atomic64_t *v, s64 i) +{ + unsigned long flags; + _atomic_spin_lock_irqsave(v, flags); + + v->counter = i; + + _atomic_spin_unlock_irqrestore(v, flags); +} + +static __inline__ s64 +atomic64_read(const atomic64_t *v) +{ + return v->counter; +} + +#define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)i),(v)))) +#define atomic64_sub(i,v) ((void)(__atomic64_add_return(-((s64)i),(v)))) +#define atomic64_inc(v) ((void)(__atomic64_add_return( 1,(v)))) +#define atomic64_dec(v) ((void)(__atomic64_add_return( -1,(v)))) + +#define atomic64_add_return(i,v) (__atomic64_add_return( ((s64)i),(v))) +#define atomic64_sub_return(i,v) (__atomic64_add_return(-((s64)i),(v))) +#define atomic64_inc_return(v) (__atomic64_add_return( 1,(v))) +#define atomic64_dec_return(v) (__atomic64_add_return( -1,(v))) + +#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) + +#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) +#define atomic64_dec_and_test(v) (atomic64_dec_return(v) == 0) + +#endif /* __LP64__ */ + #include <asm-generic/atomic.h> -#endif + +#endif /* _ASM_PARISC_ATOMIC_H_ */ diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index 1bc3c83ee74b..c53af9ff41b5 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -183,4 +183,10 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long __flush_cache_page(vma, vmaddr); } + +#ifdef CONFIG_DEBUG_RODATA +void mark_rodata_ro(void); #endif + +#endif /* _PARISC_CACHEFLUSH_H */ + diff --git a/include/asm-parisc/compat_ucontext.h b/include/asm-parisc/compat_ucontext.h index a1228a3d2071..2f7292afde3c 100644 --- a/include/asm-parisc/compat_ucontext.h +++ b/include/asm-parisc/compat_ucontext.h @@ -1,8 +1,7 @@ #ifndef _ASM_PARISC_COMPAT_UCONTEXT_H #define _ASM_PARISC_COMPAT_UCONTEXT_H -#include<linux/compat.h> -#include<asm/compat_signal.h> +#include <linux/compat.h> /* 32-bit ucontext as seen from an 64-bit kernel */ struct compat_ucontext { diff --git a/include/asm-parisc/grfioctl.h b/include/asm-parisc/grfioctl.h index 6a910311b56b..671e06042b40 100644 --- a/include/asm-parisc/grfioctl.h +++ b/include/asm-parisc/grfioctl.h @@ -58,7 +58,7 @@ #define CRT_ID_ELK_1024DB 0x27849CA5 /* Elk 1024x768 double buffer */ #define CRT_ID_ELK_GS S9000_ID_A1924A /* Elk 1280x1024 GreyScale */ #define CRT_ID_CRX24 S9000_ID_A1439A /* Piranha */ -#define CRT_ID_VISUALIZE_EG 0x2D08C0A7 /* Graffiti (built-in B132+/B160L) */ +#define CRT_ID_VISUALIZE_EG 0x2D08C0A7 /* Graffiti, A4450A (built-in B132+/B160L) */ #define CRT_ID_THUNDER 0x2F23E5FC /* Thunder 1 VISUALIZE 48*/ #define CRT_ID_THUNDER2 0x2F8D570E /* Thunder 2 VISUALIZE 48 XP*/ #define CRT_ID_HCRX S9000_ID_HCRX /* Hyperdrive HCRX */ diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index f277254159b7..fe7f6a2f5aa7 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -18,6 +18,18 @@ */ #define PCI_MAX_BUSSES 256 + +/* To be used as: mdelay(pci_post_reset_delay); + * + * post_reset is the time the kernel should stall to prevent anyone from + * accessing the PCI bus once #RESET is de-asserted. + * PCI spec somewhere says 1 second but with multi-PCI bus systems, + * this makes the boot time much longer than necessary. + * 20ms seems to work for all the HP PCI implementations to date. + */ +#define pci_post_reset_delay 50 + + /* ** pci_hba_data (aka H2P_OBJECT in HP/UX) ** @@ -83,7 +95,7 @@ static __inline__ int pci_is_lmmio(struct pci_hba_data *hba, unsigned long a) /* ** Convert between PCI (IO_VIEW) addresses and processor (PA_VIEW) addresses. -** See pcibios.c for more conversions used by Generic PCI code. +** See pci.c for more conversions used by Generic PCI code. ** ** Platform characteristics/firmware guarantee that ** (1) PA_VIEW - IO_VIEW = lmmio_offset for both LMMIO and ELMMIO @@ -191,9 +203,6 @@ struct pci_bios_ops { */ extern struct pci_port_ops *pci_port; extern struct pci_bios_ops *pci_bios; -extern int pci_post_reset_delay; /* delay after de-asserting #RESET */ -extern int pci_hba_count; -extern struct pci_hba_data *parisc_pci_hba[]; #ifdef CONFIG_PCI extern void pcibios_register_hba(struct pci_hba_data *); diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h index 6291d6692e5d..3122fad38a1b 100644 --- a/include/asm-parisc/pgalloc.h +++ b/include/asm-parisc/pgalloc.h @@ -137,7 +137,6 @@ static inline void pte_free_kernel(pte_t *pte) #define pte_free(page) pte_free_kernel(page_address(page)) -extern int do_check_pgt_cache(int, int); #define check_pgt_cache() do { } while (0) #endif diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index b4554711c3e7..4e34c6b44059 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -213,7 +213,7 @@ extern void *vmalloc_start; #define PAGE_COPY PAGE_EXECREAD #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED) +#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) #define PAGE_FLUSH __pgprot(_PAGE_FLUSH) diff --git a/include/asm-parisc/rt_sigframe.h b/include/asm-parisc/rt_sigframe.h index 5623c032b64c..f0dd3b30f6c4 100644 --- a/include/asm-parisc/rt_sigframe.h +++ b/include/asm-parisc/rt_sigframe.h @@ -1,10 +1,6 @@ #ifndef _ASM_PARISC_RT_SIGFRAME_H #define _ASM_PARISC_RT_SIGFRAME_H -#ifdef CONFIG_COMPAT -#include <asm/compat_rt_sigframe.h> -#endif - #define SIGRETURN_TRAMP 4 #define SIGRESTARTBLOCK_TRAMP 5 #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP) diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h index 80b7b98c70a1..c56fccbf34ad 100644 --- a/include/asm-parisc/unistd.h +++ b/include/asm-parisc/unistd.h @@ -761,8 +761,27 @@ #define __NR_keyctl (__NR_Linux + 266) #define __NR_ioprio_set (__NR_Linux + 267) #define __NR_ioprio_get (__NR_Linux + 268) +#define __NR_inotify_init (__NR_Linux + 269) +#define __NR_inotify_add_watch (__NR_Linux + 270) +#define __NR_inotify_rm_watch (__NR_Linux + 271) +#define __NR_migrate_pages (__NR_Linux + 272) +#define __NR_pselect6 (__NR_Linux + 273) +#define __NR_ppoll (__NR_Linux + 274) +#define __NR_openat (__NR_Linux + 275) +#define __NR_mkdirat (__NR_Linux + 276) +#define __NR_mknodat (__NR_Linux + 277) +#define __NR_fchownat (__NR_Linux + 278) +#define __NR_futimesat (__NR_Linux + 279) +#define __NR_newfstatat (__NR_Linux + 280) +#define __NR_unlinkat (__NR_Linux + 281) +#define __NR_renameat (__NR_Linux + 282) +#define __NR_linkat (__NR_Linux + 283) +#define __NR_symlinkat (__NR_Linux + 284) +#define __NR_readlinkat (__NR_Linux + 285) +#define __NR_fchmodat (__NR_Linux + 286) +#define __NR_faccessat (__NR_Linux + 287) -#define __NR_Linux_syscalls 269 +#define __NR_Linux_syscalls 288 #define HPUX_GATEWAY_ADDR 0xC0000004 #define LINUX_GATEWAY_ADDR 0x100 diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h index accb80c9a339..aacaabd28ac1 100644 --- a/include/asm-powerpc/compat.h +++ b/include/asm-powerpc/compat.h @@ -126,6 +126,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr) return (void __user *)(unsigned long)uptr; } +static inline compat_uptr_t ptr_to_compat(void __user *uptr) +{ + return (u32)(unsigned long)uptr; +} + static inline void __user *compat_alloc_user_space(long len) { struct pt_regs *regs = current->thread.regs; diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 837756ab7dc7..2ac63f569592 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h @@ -15,7 +15,6 @@ #include <linux/mm.h> #include <asm/scatterlist.h> #include <asm/io.h> -#include <asm/bug.h> #define DMA_ERROR_CODE (~(dma_addr_t)0x0) diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index 640a6459f2f4..bda2f217e6fe 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -33,6 +33,7 @@ #ifdef CONFIG_KEXEC +#ifndef __ASSEMBLY__ #ifdef __powerpc64__ /* * This function is responsible for capturing register states if coming @@ -104,7 +105,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs) { } #endif /* !__powerpc64 __ */ -#ifndef __ASSEMBLY__ #define MAX_NOTE_BYTES 1024 #ifdef __powerpc64__ @@ -121,6 +121,8 @@ extern void default_machine_kexec(struct kimage *image); extern int default_machine_kexec_prepare(struct kimage *image); extern void default_machine_crash_shutdown(struct pt_regs *regs); +extern void machine_kexec_simple(struct kimage *image); + #endif /* ! __ASSEMBLY__ */ #endif /* CONFIG_KEXEC */ #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/pmac_pfunc.h b/include/asm-powerpc/pmac_pfunc.h index d9728c80f86d..cef61304ffc2 100644 --- a/include/asm-powerpc/pmac_pfunc.h +++ b/include/asm-powerpc/pmac_pfunc.h @@ -167,6 +167,7 @@ struct pmf_irq_client { void *data; struct module *owner; struct list_head link; + struct pmf_function *func; }; @@ -187,9 +188,7 @@ extern int pmf_register_irq_client(struct device_node *np, const char *name, struct pmf_irq_client *client); -extern void pmf_unregister_irq_client(struct device_node *np, - const char *name, - struct pmf_irq_client *client); +extern void pmf_unregister_irq_client(struct pmf_irq_client *client); /* * Called by the handlers when an irq happens diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 5b2bd4eefb01..cbd297f44cce 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -222,5 +222,7 @@ extern int of_address_to_resource(struct device_node *dev, int index, extern int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r); +extern void kdump_move_device_tree(void); + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 82ce47607774..2dc93632f210 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -521,6 +521,11 @@ struct smu_sdbp_cpupiddata { extern struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size); +/* Get "sdb" partition data from an SMU satellite */ +extern struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, + int id, unsigned int *size); + + #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index 7e09d7cda933..c044ec16a879 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h @@ -37,7 +37,7 @@ struct thread_info { int preempt_count; /* 0 => preemptable, <0 => BUG */ struct restart_block restart_block; - void *nvgprs_frame; + void __user *nvgprs_frame; /* low level flags - has atomic operations done on it */ unsigned long flags ____cacheline_aligned_in_smp; }; @@ -122,6 +122,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */ #define TIF_SAVE_NVGPRS 13 /* Save r14-r31 in signal frame */ #define TIF_NOERROR 14 /* Force successful syscall return */ +#define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) @@ -138,10 +139,12 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_RESTOREALL (1<<TIF_RESTOREALL) #define _TIF_SAVE_NVGPRS (1<<TIF_SAVE_NVGPRS) #define _TIF_NOERROR (1<<TIF_NOERROR) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) #define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ - _TIF_NEED_RESCHED | _TIF_RESTOREALL) + _TIF_NEED_RESCHED | _TIF_RESTOREALL | \ + _TIF_RESTORE_SIGMASK) #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS) #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 19eaac3fbbf9..35556993f066 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -298,8 +298,11 @@ #define __NR_inotify_rm_watch 277 #define __NR_spu_run 278 #define __NR_spu_create 279 +#define __NR_pselect6 280 +#define __NR_ppoll 281 +#define __NR_unshare 282 -#define __NR_syscalls 280 +#define __NR_syscalls 283 #ifdef __KERNEL__ #define __NR__exit __NR_exit @@ -444,11 +447,13 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #ifdef CONFIG_PPC32 #define __ARCH_WANT_OLD_STAT #endif #ifdef CONFIG_PPC64 #define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #endif /* diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 61232760cc3b..3628899f48bb 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -518,8 +518,8 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr static inline int __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { - return ((((volatile char *) addr) - [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)))) != 0; + return (((volatile char *) addr) + [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0; } #define test_bit(nr,addr) \ diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h index 77b10d6adabd..c744ff33b1df 100644 --- a/include/asm-s390/dasd.h +++ b/include/asm-s390/dasd.h @@ -8,8 +8,6 @@ * any future changes wrt the API will result in a change of the APIVERSION reported * to userspace by the DASDAPIVER-ioctl * - * $Revision: 1.6 $ - * */ #ifndef DASD_H @@ -206,7 +204,8 @@ typedef struct attrib_data_t { * * Here ist how the ioctl-nr should be used: * 0 - 31 DASD driver itself - * 32 - 239 still open + * 32 - 229 still open + * 230 - 239 DASD extended error reporting * 240 - 255 reserved for EMC *******************************************************************************/ @@ -238,12 +237,22 @@ typedef struct attrib_data_t { #define BIODASDPSRD _IOR(DASD_IOCTL_LETTER,4,dasd_rssd_perf_stats_t) /* Get Attributes (cache operations) */ #define BIODASDGATTR _IOR(DASD_IOCTL_LETTER,5,attrib_data_t) +/* retrieve extended error-reporting value */ +#define BIODASDEERGET _IOR(DASD_IOCTL_LETTER,6,int) /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t) /* Set Attributes (cache operations) */ #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) +/* retrieve extended error-reporting value */ +#define BIODASDEERSET _IOW(DASD_IOCTL_LETTER,3,int) + + +/* remove all records from the eer buffer */ +#define DASD_EER_PURGE _IO(DASD_IOCTL_LETTER,230) +/* set the number of pages that are used for the internal eer buffer */ +#define DASD_EER_SETBUFSIZE _IOW(DASD_IOCTL_LETTER,230,int) #endif /* DASD_H */ diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h index 71f55eb2350a..b05825dd16d7 100644 --- a/include/asm-s390/io.h +++ b/include/asm-s390/io.h @@ -90,10 +90,16 @@ extern void iounmap(void *addr); #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b)) #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b)) #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b)) +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel #define memset_io(a,b,c) memset(__io_virt(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c)) diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h index 7bc15f0231db..a2f37a9353d3 100644 --- a/include/asm-s390/qdio.h +++ b/include/asm-s390/qdio.h @@ -11,8 +11,6 @@ #ifndef __QDIO_H__ #define __QDIO_H__ -#define VERSION_QDIO_H "$Revision: 1.57 $" - /* note, that most of the typedef's are from ingo. */ #include <linux/interrupt.h> diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h index 348a88137445..da3fd4a7bb32 100644 --- a/include/asm-s390/setup.h +++ b/include/asm-s390/setup.h @@ -8,6 +8,8 @@ #ifndef _ASM_S390_SETUP_H #define _ASM_S390_SETUP_H +#ifdef __KERNEL__ + #include <asm/types.h> #define PARMAREA 0x10400 @@ -114,7 +116,7 @@ extern u16 ipl_devno; IPL_PARMBLOCK_ORIGIN) #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.length) -#else +#else /* __ASSEMBLY__ */ #ifndef __s390x__ #define IPL_DEVICE 0x10404 @@ -127,6 +129,6 @@ extern u16 ipl_devno; #endif /* __s390x__ */ #define COMMAND_LINE 0x10480 -#endif - -#endif +#endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ +#endif /* _ASM_S390_SETUP_H */ diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index a2ae7628bbaa..9c6e9c300eb9 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h @@ -101,6 +101,7 @@ smp_call_function_on(void (*func) (void *info), void *info, func(info); return 0; } +#define smp_cpu_not_running(cpu) 1 #define smp_get_cpu(cpu) ({ 0; }) #define smp_put_cpu(cpu) ({ 0; }) #endif diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index f3797a52c4ea..8e0c7ed73d03 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h @@ -2,7 +2,7 @@ * include/asm-s390/thread_info.h * * S390 version - * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 2002,2006 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) */ @@ -88,7 +88,7 @@ static inline struct thread_info *current_thread_info(void) * thread information flags bit numbers */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_RESTORE_SIGMASK 1 /* restore signal mask in do_signal() */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ @@ -102,7 +102,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_MEMDIE 19 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) -#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h index ea0788967c51..fcd6c256a2d1 100644 --- a/include/asm-s390/timer.h +++ b/include/asm-s390/timer.h @@ -1,7 +1,7 @@ /* * include/asm-s390/timer.h * - * (C) Copyright IBM Corp. 2003 + * (C) Copyright IBM Corp. 2003,2006 * Virtual CPU timer * * Author: Jan Glauber (jang@de.ibm.com) @@ -10,6 +10,8 @@ #ifndef _ASM_S390_TIMER_H #define _ASM_S390_TIMER_H +#ifdef __KERNEL__ + #include <linux/timer.h> #define VTIMER_MAX_SLICE (0x7ffffffffffff000LL) @@ -43,4 +45,6 @@ extern void add_virt_timer_periodic(void *new); extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); extern int del_virt_timer(struct vtimer_list *timer); -#endif +#endif /* __KERNEL__ */ + +#endif /* _ASM_S390_TIMER_H */ diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index be104f21c70a..0b7c0ca4c3d7 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -61,7 +61,7 @@ #define segment_eq(a,b) ((a).ar4 == (b).ar4) -static inline int __access_ok(const void *addr, unsigned long size) +static inline int __access_ok(const void __user *addr, unsigned long size) { return 1; } @@ -208,25 +208,25 @@ extern int __put_user_bad(void) __attribute__((noreturn)); case 1: { \ unsigned char __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 2: { \ unsigned short __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 4: { \ unsigned int __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 8: { \ unsigned long long __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ default: \ diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index 2861cdc243ad..657d582e8149 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -279,8 +279,25 @@ #define __NR_inotify_init 284 #define __NR_inotify_add_watch 285 #define __NR_inotify_rm_watch 286 +/* Number 287 is reserved for new sys_migrate_pages */ +#define __NR_openat 288 +#define __NR_mkdirat 289 +#define __NR_mknodat 290 +#define __NR_fchownat 291 +#define __NR_futimesat 292 +#define __NR_fstatat64 293 +#define __NR_unlinkat 294 +#define __NR_renameat 295 +#define __NR_linkat 296 +#define __NR_symlinkat 297 +#define __NR_readlinkat 298 +#define __NR_fchmodat 299 +#define __NR_faccessat 300 +#define __NR_pselect6 301 +#define __NR_ppoll 302 +#define __NR_unshare 303 -#define NR_syscalls 287 +#define NR_syscalls 304 /* * There are some system calls that are not present on 64 bit, some @@ -342,6 +359,7 @@ #undef __NR_fcntl64 #undef __NR_sendfile64 #undef __NR_fadvise64_64 +#undef __NR_fstatat64 #define __NR_select 142 #define __NR_getrlimit 191 /* SuS compliant getrlimit */ @@ -364,6 +382,7 @@ #define __NR_setgid 214 #define __NR_setfsuid 215 #define __NR_setfsgid 216 +#define __NR_newfstatat 293 #endif @@ -539,11 +558,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND # ifndef CONFIG_64BIT # define __ARCH_WANT_STAT64 # define __ARCH_WANT_SYS_TIME # endif -# define __ARCH_WANT_COMPAT_SYS_TIME +# ifdef CONFIG_COMPAT +# define __ARCH_WANT_COMPAT_SYS_TIME +# define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND +# endif #endif #ifdef __KERNEL_SYSCALLS__ diff --git a/include/asm-sh/bus-sh.h b/include/asm-sh/bus-sh.h deleted file mode 100644 index e42d63b65cb5..000000000000 --- a/include/asm-sh/bus-sh.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * include/asm-sh/bus-sh.h - * - * Copyright (C) 2004 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#ifndef __ASM_SH_BUS_SH_H -#define __ASM_SH_BUS_SH_H - -extern struct bus_type sh_bus_types[]; - -struct sh_dev { - struct device dev; - char *name; - unsigned int dev_id; - unsigned int bus_id; - struct resource res; - void *mapbase; - unsigned int irq[6]; - u64 *dma_mask; - u64 coherent_dma_mask; -}; - -#define to_sh_dev(d) container_of((d), struct sh_dev, dev) - -#define sh_get_drvdata(d) dev_get_drvdata(&(d)->dev) -#define sh_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) - -struct sh_driver { - struct device_driver drv; - unsigned int dev_id; - unsigned int bus_id; - int (*probe)(struct sh_dev *); - int (*remove)(struct sh_dev *); - int (*suspend)(struct sh_dev *, pm_message_t); - int (*resume)(struct sh_dev *); -}; - -#define to_sh_driver(d) container_of((d), struct sh_driver, drv) -#define sh_name(d) ((d)->dev.driver->name) - -/* - * Device ID numbers for bus types - */ -enum { - SH_DEV_ID_USB_OHCI, -}; - -#define SH_NR_BUSES 1 -#define SH_BUS_NAME_VIRT "shbus" - -enum { - SH_BUS_VIRT, -}; - -/* arch/sh/kernel/cpu/bus.c */ -extern int sh_device_register(struct sh_dev *dev); -extern void sh_device_unregister(struct sh_dev *dev); -extern int sh_driver_register(struct sh_driver *drv); -extern void sh_driver_unregister(struct sh_driver *drv); - -#endif /* __ASM_SH_BUS_SH_H */ - diff --git a/include/asm-sh/cpu-sh3/mmu_context.h b/include/asm-sh/cpu-sh3/mmu_context.h index 5cfaa6bcf1ed..a844ea0965b6 100644 --- a/include/asm-sh/cpu-sh3/mmu_context.h +++ b/include/asm-sh/cpu-sh3/mmu_context.h @@ -24,5 +24,15 @@ #define MMU_NTLB_WAYS 4 #define MMU_CONTROL_INIT 0x007 /* SV=0, TF=1, IX=1, AT=1 */ +#define TRA 0xffffffd0 +#define EXPEVT 0xffffffd4 + +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ + defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) +#define INTEVT 0xa4000000 /* INTEVTE2(0xa4000000) */ +#else +#define INTEVT 0xffffffd8 +#endif + #endif /* __ASM_CPU_SH3_MMU_CONTEXT_H */ diff --git a/include/asm-sh/cpu-sh4/mmu_context.h b/include/asm-sh/cpu-sh4/mmu_context.h index 5b64d041f0b9..ff4c5fbbfaf0 100644 --- a/include/asm-sh/cpu-sh4/mmu_context.h +++ b/include/asm-sh/cpu-sh4/mmu_context.h @@ -23,7 +23,11 @@ #define MMU_PAGE_ASSOC_BIT 0x80 #define MMU_NTLB_ENTRIES 64 /* for 7750 */ +#ifdef CONFIG_SH_STORE_QUEUES +#define MMU_CONTROL_INIT 0x05 /* SQMD=0, SV=0, TI=1, AT=1 */ +#else #define MMU_CONTROL_INIT 0x205 /* SQMD=1, SV=0, TI=1, AT=1 */ +#endif #define MMU_ITLB_DATA_ARRAY 0xF3000000 #define MMU_UTLB_DATA_ARRAY 0xF7000000 @@ -35,5 +39,9 @@ #define MMU_I_ENTRY_SHIFT 8 #define MMU_ITLB_VALID 0x100 +#define TRA 0xff000020 +#define EXPEVT 0xff000024 +#define INTEVT 0xff000028 + #endif /* __ASM_CPU_SH4_MMU_CONTEXT_H */ diff --git a/include/asm-sh/ioctls.h b/include/asm-sh/ioctls.h index 1866f3f90028..9d84a2d445a2 100644 --- a/include/asm-sh/ioctls.h +++ b/include/asm-sh/ioctls.h @@ -94,6 +94,6 @@ #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */ #define TIOCMIWAIT _IO('T', 92) /* 0x545C */ /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* 0x545D */ /* read serial port inline interrupt counts */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ #endif /* __ASM_SH_IOCTLS_H */ diff --git a/include/asm-sh/irq-sh73180.h b/include/asm-sh/irq-sh73180.h index bf2e4310ffac..d705252be260 100644 --- a/include/asm-sh/irq-sh73180.h +++ b/include/asm-sh/irq-sh73180.h @@ -25,11 +25,6 @@ #undef DMA_IPR_POS #undef DMA_PRIORITY -#undef NR_IRQS - -#undef __irq_demux -#undef irq_demux - #undef INTC_IMCR0 #undef INTC_IMCR1 #undef INTC_IMCR2 @@ -229,33 +224,6 @@ #define SIU_IPR_POS 1 #define SIU_PRIORITY 3 - -/* ONCHIP_NR_IRQS */ -#define NR_IRQS 109 - -/* In a generic kernel, NR_IRQS is an upper bound, and we should use - * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value. - */ -#define ACTUAL_NR_IRQS NR_IRQS - - -extern void disable_irq(unsigned int); -extern void disable_irq_nosync(unsigned int); -extern void enable_irq(unsigned int); - -/* - * Simple Mask Register Support - */ -extern void make_maskreg_irq(unsigned int irq); -extern unsigned short *irq_mask_register; - -/* - * Function for "on chip support modules". - */ -extern void make_ipr_irq(unsigned int irq, unsigned int addr, - int pos, int priority); -extern void make_imask_irq(unsigned int irq); - #define PORT_PACR 0xA4050100UL #define PORT_PBCR 0xA4050102UL #define PORT_PCCR 0xA4050104UL @@ -343,8 +311,6 @@ extern void make_imask_irq(unsigned int irq); #define IRQ6_PRIORITY 1 #define IRQ7_PRIORITY 1 -extern int shmse_irq_demux(int irq); -#define __irq_demux(irq) shmse_irq_demux(irq) -#define irq_demux(irq) __irq_demux(irq) +int shmse_irq_demux(int irq); #endif /* __ASM_SH_IRQ_SH73180_H */ diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h index 8c8ca1281084..7f90315cd830 100644 --- a/include/asm-sh/irq-sh7780.h +++ b/include/asm-sh/irq-sh7780.h @@ -299,29 +299,6 @@ #define GPIO_IPR_POS 2 #define GPIO_PRIORITY 3 -/* ONCHIP_NR_IRQS */ -#define NR_IRQS 150 /* 111 + 16 */ - -/* In a generic kernel, NR_IRQS is an upper bound, and we should use - * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value. - */ -#define ACTUAL_NR_IRQS NR_IRQS - -extern void disable_irq(unsigned int); -extern void disable_irq_nosync(unsigned int); -extern void enable_irq(unsigned int); - -/* - * Simple Mask Register Support - */ -extern void make_maskreg_irq(unsigned int irq); -extern unsigned short *irq_mask_register; - -/* - * Function for "on chip support modules". - */ -extern void make_imask_irq(unsigned int irq); - #define INTC_TMU0_MSK 0 #define INTC_TMU3_MSK 1 #define INTC_RTC_MSK 2 diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 060ec3c27207..42b8394c04ed 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -245,6 +245,7 @@ #endif /* ST40STB1 */ #endif /* 775x / SH4-202 / ST40STB1 */ +#endif /* 7780 */ /* NR_IRQS is made from three components: * 1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules @@ -274,8 +275,11 @@ # define ONCHIP_NR_IRQS 72 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) # define ONCHIP_NR_IRQS 144 -#elif defined(CONFIG_CPU_SUBTYPE_SH7300) +#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \ + defined(CONFIG_CPU_SUBTYPE_SH73180) # define ONCHIP_NR_IRQS 109 +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +# define ONCHIP_NR_IRQS 111 #elif defined(CONFIG_SH_UNKNOWN) /* Most be last */ # define ONCHIP_NR_IRQS 144 #endif @@ -306,6 +310,8 @@ # define OFFCHIP_NR_IRQS 96 #elif defined (CONFIG_SH_TITAN) # define OFFCHIP_NR_IRQS 4 +#elif defined(CONFIG_SH_R7780RP) +# define OFFCHIP_NR_IRQS 16 #elif defined(CONFIG_SH_UNKNOWN) # define OFFCHIP_NR_IRQS 16 /* Must also be last */ #else @@ -550,7 +556,7 @@ extern int ipr_irq_demux(int irq); #define INTC_ICR_IRLM (1<<7) #endif -#else +#ifdef CONFIG_CPU_SUBTYPE_SH7780 #include <asm/irq-sh7780.h> #endif diff --git a/include/asm-sh/microdev/irq.h b/include/asm-sh/microdev.h index 47f6f77a65f0..018332a9e590 100644 --- a/include/asm-sh/microdev/irq.h +++ b/include/asm-sh/microdev.h @@ -1,32 +1,27 @@ /* - * linux/include/asm-sh/irq_microdev.h + * linux/include/asm-sh/microdev.h * * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) * - * IRQ functions for the SuperH SH4-202 MicroDev board. + * Definitions for the SuperH SH4-202 MicroDev board. * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. - * */ - - -#ifndef _ASM_SH_IRQ_MICRODEV_H -#define _ASM_SH_IRQ_MICRODEV_H +#ifndef __ASM_SH_MICRODEV_H +#define __ASM_SH_MICRODEV_H extern void init_microdev_irq(void); extern void microdev_print_fpga_intc_status(void); - - /* - * The following are useful macros for manipulating the - * interrupt controller (INTC) on the CPU-board FPGA. - * It should be noted that there is an INTC on the FPGA, - * and a seperate INTC on the SH4-202 core - these are - * two different things, both of which need to be prorammed - * to correctly route - unfortunately, they have the - * same name and abbreviations! - */ +/* + * The following are useful macros for manipulating the interrupt + * controller (INTC) on the CPU-board FPGA. should be noted that there + * is an INTC on the FPGA, and a seperate INTC on the SH4-202 core - + * these are two different things, both of which need to be prorammed to + * correctly route - unfortunately, they have the same name and + * abbreviations! + */ #define MICRODEV_FPGA_INTC_BASE 0xa6110000ul /* INTC base address on CPU-board FPGA */ #define MICRODEV_FPGA_INTENB_REG (MICRODEV_FPGA_INTC_BASE+0ul) /* Interrupt Enable Register on INTC on CPU-board FPGA */ #define MICRODEV_FPGA_INTDSB_REG (MICRODEV_FPGA_INTC_BASE+8ul) /* Interrupt Disable Register on INTC on CPU-board FPGA */ @@ -38,10 +33,10 @@ extern void microdev_print_fpga_intc_status(void); #define MICRODEV_FPGA_INTREQ_REG (MICRODEV_FPGA_INTC_BASE+0x38ul) /* Interrupt Request Register on INTC on CPU-board FPGA */ - /* - * The following are the IRQ numbers for the Linux Kernel for external interrupts. - * i.e. the numbers seen by 'cat /proc/interrupt'. - */ +/* + * The following are the IRQ numbers for the Linux Kernel for external + * interrupts. i.e. the numbers seen by 'cat /proc/interrupt'. + */ #define MICRODEV_LINUX_IRQ_KEYBOARD 1 /* SuperIO Keyboard */ #define MICRODEV_LINUX_IRQ_SERIAL1 2 /* SuperIO Serial #1 */ #define MICRODEV_LINUX_IRQ_ETHERNET 3 /* on-board Ethnernet */ @@ -51,10 +46,11 @@ extern void microdev_print_fpga_intc_status(void); #define MICRODEV_LINUX_IRQ_IDE2 13 /* SuperIO IDE #2 */ #define MICRODEV_LINUX_IRQ_IDE1 14 /* SuperIO IDE #1 */ - /* - * The following are the IRQ numbers for the INTC on the FPGA for external interrupts. - * i.e. the bits in the INTC registers in the FPGA. - */ +/* + * The following are the IRQ numbers for the INTC on the FPGA for + * external interrupts. i.e. the bits in the INTC registers in the + * FPGA. + */ #define MICRODEV_FPGA_IRQ_KEYBOARD 1 /* SuperIO Keyboard */ #define MICRODEV_FPGA_IRQ_SERIAL1 3 /* SuperIO Serial #1 */ #define MICRODEV_FPGA_IRQ_SERIAL2 4 /* SuperIO Serial #2 */ @@ -69,4 +65,16 @@ extern void microdev_print_fpga_intc_status(void); #define MICRODEV_IRQ_PCI_INTC 10 #define MICRODEV_IRQ_PCI_INTD 11 -#endif /* _ASM_SH_IRQ_MICRODEV_H */ +#define __IO_PREFIX microdev +#include <asm/io_generic.h> + +#if defined(CONFIG_PCI) +unsigned char microdev_pci_inb(unsigned long port); +unsigned short microdev_pci_inw(unsigned long port); +unsigned long microdev_pci_inl(unsigned long port); +void microdev_pci_outb(unsigned char data, unsigned long port); +void microdev_pci_outw(unsigned short data, unsigned long port); +void microdev_pci_outl(unsigned long data, unsigned long port); +#endif + +#endif /* __ASM_SH_MICRODEV_H */ diff --git a/include/asm-sh/microdev/io.h b/include/asm-sh/microdev/io.h deleted file mode 100644 index f2ca4ac8c88a..000000000000 --- a/include/asm-sh/microdev/io.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * linux/include/asm-sh/io_microdev.h - * - * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) - * - * IO functions for the SuperH SH4-202 MicroDev board. - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - */ - - -#ifndef _ASM_SH_IO_MICRODEV_H -#define _ASM_SH_IO_MICRODEV_H - -extern unsigned long microdev_isa_port2addr(unsigned long offset); - -extern unsigned char microdev_inb(unsigned long port); -extern unsigned short microdev_inw(unsigned long port); -extern unsigned int microdev_inl(unsigned long port); - -extern void microdev_outb(unsigned char value, unsigned long port); -extern void microdev_outw(unsigned short value, unsigned long port); -extern void microdev_outl(unsigned int value, unsigned long port); - -extern unsigned char microdev_inb_p(unsigned long port); -extern unsigned short microdev_inw_p(unsigned long port); -extern unsigned int microdev_inl_p(unsigned long port); - -extern void microdev_outb_p(unsigned char value, unsigned long port); -extern void microdev_outw_p(unsigned short value, unsigned long port); -extern void microdev_outl_p(unsigned int value, unsigned long port); - -extern void microdev_insb(unsigned long port, void *addr, unsigned long count); -extern void microdev_insw(unsigned long port, void *addr, unsigned long count); -extern void microdev_insl(unsigned long port, void *addr, unsigned long count); - -extern void microdev_outsb(unsigned long port, const void *addr, unsigned long count); -extern void microdev_outsw(unsigned long port, const void *addr, unsigned long count); -extern void microdev_outsl(unsigned long port, const void *addr, unsigned long count); - -#if defined(CONFIG_PCI) -extern unsigned char microdev_pci_inb(unsigned long port); -extern unsigned short microdev_pci_inw(unsigned long port); -extern unsigned long microdev_pci_inl(unsigned long port); -extern void microdev_pci_outb(unsigned char data, unsigned long port); -extern void microdev_pci_outw(unsigned short data, unsigned long port); -extern void microdev_pci_outl(unsigned long data, unsigned long port); -#endif - -#endif /* _ASM_SH_IO_MICRODEV_H */ - diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index c4904797d6df..fa5bd2d8803e 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -12,7 +12,6 @@ #include <asm/page.h> #include <asm/types.h> #include <asm/cache.h> -#include <linux/threads.h> #include <asm/ptrace.h> /* @@ -30,7 +29,7 @@ * CPU type and hardware bug flags. Kept separately for each CPU. * * Each one of these also needs a CONFIG_CPU_SUBTYPE_xxx entry - * in arch/sh/Kconfig, as well as an entry in arch/sh/kernel/setup.c + * in arch/sh/mm/Kconfig, as well as an entry in arch/sh/kernel/setup.c * for parsing the subtype in get_cpu_subtype(). */ enum cpu_type { @@ -44,7 +43,7 @@ enum cpu_type { /* SH-4 types */ CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R, CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501, - CPU_SH73180, + CPU_SH73180, CPU_SH7770, CPU_SH7780, CPU_SH7781, /* Unknown subtype */ CPU_SH_NONE @@ -52,14 +51,8 @@ enum cpu_type { struct sh_cpuinfo { enum cpu_type type; - char hard_math; unsigned long loops_per_jiffy; - unsigned int cpu_clock, master_clock, bus_clock, module_clock; -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - unsigned int memory_clock; -#endif - struct cache_info icache; struct cache_info dcache; @@ -131,7 +124,7 @@ union sh_fpu_union { struct sh_fpu_soft_struct soft; }; -/* +/* * Processor flags */ @@ -140,6 +133,7 @@ union sh_fpu_union { #define CPU_HAS_MMU_PAGE_ASSOC 0x0004 /* SH3: TLB way selection bit support */ #define CPU_HAS_DSP 0x0008 /* SH-DSP: DSP support */ #define CPU_HAS_PERF_COUNTER 0x0010 /* Hardware performance counters */ +#define CPU_HAS_PTEA 0x0020 /* PTEA register */ struct thread_struct { unsigned long sp; @@ -160,10 +154,10 @@ extern int ubc_usercnt; #define INIT_THREAD { \ sizeof(init_stack) + (long) &init_stack, /* sp */ \ 0, /* pc */ \ - 0, 0, \ - 0, \ - 0, \ - {{{0,}},} /* fpu state */ \ + 0, 0, \ + 0, \ + 0, \ + {{{0,}},} /* fpu state */ \ } /* @@ -171,7 +165,7 @@ extern int ubc_usercnt; */ #define start_thread(regs, new_pc, new_sp) \ set_fs(USER_DS); \ - regs->pr = 0; \ + regs->pr = 0; \ regs->sr = SR_FD; /* User mode. */ \ regs->pc = new_pc; \ regs->regs[15] = new_sp @@ -239,16 +233,16 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); #define save_fpu(tsk) do { } while (0) #endif -#define unlazy_fpu(tsk, regs) do { \ +#define unlazy_fpu(tsk, regs) do { \ if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - save_fpu(tsk, regs); \ + save_fpu(tsk, regs); \ } \ } while (0) -#define clear_fpu(tsk, regs) do { \ - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ - release_fpu(regs); \ +#define clear_fpu(tsk, regs) do { \ + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ + clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ + release_fpu(regs); \ } \ } while (0) diff --git a/include/asm-sh64/ioctls.h b/include/asm-sh64/ioctls.h index 08f3c1f2e419..6b0c04f63c57 100644 --- a/include/asm-sh64/ioctls.h +++ b/include/asm-sh64/ioctls.h @@ -111,6 +111,6 @@ #define TIOCSERSETMULTI 0x40a8545b /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */ #define TIOCMIWAIT 0x545c /* _IO('T', 92) wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x802c545d /* _IOR('T', 93, struct async_icount) 0x545D */ /* read serial port inline interrupt counts */ +#define TIOCGICOUNT 0x545d /* read serial port inline interrupt counts */ #endif /* __ASM_SH64_IOCTLS_H */ diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h index 95944556d8b6..d0d76b30eb4c 100644 --- a/include/asm-sparc/oplib.h +++ b/include/asm-sparc/oplib.h @@ -164,6 +164,7 @@ enum prom_input_device { PROMDEV_IKBD, /* input from keyboard */ PROMDEV_ITTYA, /* input from ttya */ PROMDEV_ITTYB, /* input from ttyb */ + PROMDEV_IRSC, /* input from rsc */ PROMDEV_I_UNK, }; @@ -175,6 +176,7 @@ enum prom_output_device { PROMDEV_OSCREEN, /* to screen */ PROMDEV_OTTYA, /* to ttya */ PROMDEV_OTTYB, /* to ttyb */ + PROMDEV_ORSC, /* to rsc */ PROMDEV_O_UNK, }; diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h index 65f060b040ab..91b9f5888c85 100644 --- a/include/asm-sparc/thread_info.h +++ b/include/asm-sparc/thread_info.h @@ -128,9 +128,10 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) * thread information flag bit numbers */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +/* flag bit 1 is available */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */ #define TIF_USEDFPU 8 /* FPU was used by this task * this quantum (SMP) */ #define TIF_POLLING_NRFLAG 9 /* true if poll_idle() is polling @@ -139,9 +140,9 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) -#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index 58dba518239e..64ec640a40ee 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -300,11 +300,27 @@ #define __NR_add_key 281 #define __NR_request_key 282 #define __NR_keyctl 283 +#define __NR_openat 284 +#define __NR_mkdirat 285 +#define __NR_mknodat 286 +#define __NR_fchownat 287 +#define __NR_futimesat 288 +#define __NR_fstatat64 289 +#define __NR_unlinkat 290 +#define __NR_renameat 291 +#define __NR_linkat 292 +#define __NR_symlinkat 293 +#define __NR_readlinkat 294 +#define __NR_fchmodat 295 +#define __NR_faccessat 296 +#define __NR_pselect6 297 +#define __NR_ppoll 298 +#define __NR_unshare 299 -/* WARNING: You MAY NOT add syscall numbers larger than 283, since +/* WARNING: You MAY NOT add syscall numbers larger than 299, since * all of the syscall tables in the Sparc kernel are - * sized to have 283 entries (starting at zero). Therefore - * find a free slot in the 0-282 range. + * sized to have 299 entries (starting at zero). Therefore + * find a free slot in the 0-299 range. */ #define _syscall0(type,name) \ @@ -458,6 +474,7 @@ return -1; \ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #endif #ifdef __KERNEL_SYSCALLS__ diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h index d02f1e8ae1a6..3c59b2693fb9 100644 --- a/include/asm-sparc64/oplib.h +++ b/include/asm-sparc64/oplib.h @@ -163,6 +163,7 @@ enum prom_input_device { PROMDEV_IKBD, /* input from keyboard */ PROMDEV_ITTYA, /* input from ttya */ PROMDEV_ITTYB, /* input from ttyb */ + PROMDEV_IRSC, /* input from rsc */ PROMDEV_I_UNK, }; @@ -174,6 +175,7 @@ enum prom_output_device { PROMDEV_OSCREEN, /* to screen */ PROMDEV_OTTYA, /* to ttya */ PROMDEV_OTTYB, /* to ttyb */ + PROMDEV_ORSC, /* to rsc */ PROMDEV_O_UNK, }; diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h index ec85d12d73b9..508c416e9d6a 100644 --- a/include/asm-sparc64/spinlock.h +++ b/include/asm-sparc64/spinlock.h @@ -131,6 +131,28 @@ static void inline __read_lock(raw_rwlock_t *lock) : "memory"); } +static int inline __read_trylock(raw_rwlock_t *lock) +{ + int tmp1, tmp2; + + __asm__ __volatile__ ( +"1: ldsw [%2], %0\n" +" brlz,a,pn %0, 2f\n" +" mov 0, %0\n" +" add %0, 1, %1\n" +" cas [%2], %0, %1\n" +" cmp %0, %1\n" +" membar #StoreLoad | #StoreStore\n" +" bne,pn %%icc, 1b\n" +" mov 1, %0\n" +"2:" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (lock) + : "memory"); + + return tmp1; +} + static void inline __read_unlock(raw_rwlock_t *lock) { unsigned long tmp1, tmp2; @@ -211,12 +233,12 @@ static int inline __write_trylock(raw_rwlock_t *lock) } #define __raw_read_lock(p) __read_lock(p) +#define __raw_read_trylock(p) __read_trylock(p) #define __raw_read_unlock(p) __read_unlock(p) #define __raw_write_lock(p) __write_lock(p) #define __raw_write_unlock(p) __write_unlock(p) #define __raw_write_trylock(p) __write_trylock(p) -#define __raw_read_trylock(lock) generic__raw_read_trylock(lock) #define __raw_read_can_lock(rw) (!((rw)->lock & 0x80000000UL)) #define __raw_write_can_lock(rw) (!(rw)->lock) diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h index c94d8b3991bd..ac9d068aab4f 100644 --- a/include/asm-sparc64/thread_info.h +++ b/include/asm-sparc64/thread_info.h @@ -221,7 +221,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); * nop */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_RESTORE_SIGMASK 1 /* restore signal mask in do_signal() */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_PERFCTR 4 /* performance counters active */ @@ -241,7 +241,6 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define TIF_POLLING_NRFLAG 14 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) -#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_PERFCTR (1<<TIF_PERFCTR) @@ -250,11 +249,12 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_32BIT (1<<TIF_32BIT) #define _TIF_SECCOMP (1<<TIF_SECCOMP) #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \ - (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ + (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | \ _TIF_NEED_RESCHED | _TIF_PERFCTR)) #endif /* __KERNEL__ */ diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 51ec2879b881..a284986b1541 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -302,11 +302,27 @@ #define __NR_add_key 281 #define __NR_request_key 282 #define __NR_keyctl 283 +#define __NR_openat 284 +#define __NR_mkdirat 285 +#define __NR_mknodat 286 +#define __NR_fchownat 287 +#define __NR_futimesat 288 +#define __NR_fstatat64 289 +#define __NR_unlinkat 290 +#define __NR_renameat 291 +#define __NR_linkat 292 +#define __NR_symlinkat 293 +#define __NR_readlinkat 294 +#define __NR_fchmodat 295 +#define __NR_faccessat 296 +#define __NR_pselect6 297 +#define __NR_ppoll 298 +#define __NR_unshare 299 -/* WARNING: You MAY NOT add syscall numbers larger than 283, since +/* WARNING: You MAY NOT add syscall numbers larger than 299, since * all of the syscall tables in the Sparc kernel are - * sized to have 283 entries (starting at zero). Therefore - * find a free slot in the 0-282 range. + * sized to have 299 entries (starting at zero). Therefore + * find a free slot in the 0-299 range. */ #define _syscall0(type,name) \ @@ -501,6 +517,8 @@ asmlinkage long sys_rt_sigaction(int sig, #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #endif /* diff --git a/include/asm-um/io.h b/include/asm-um/io.h index 90674056dcef..1934d9340e2c 100644 --- a/include/asm-um/io.h +++ b/include/asm-um/io.h @@ -33,4 +33,20 @@ static inline void * phys_to_virt(unsigned long address) */ #define xlate_dev_kmem_ptr(p) p +static inline void writeb(unsigned char b, volatile void __iomem *addr) +{ + *(volatile unsigned char __force *) addr = b; +} +static inline void writew(unsigned short b, volatile void __iomem *addr) +{ + *(volatile unsigned short __force *) addr = b; +} +static inline void writel(unsigned int b, volatile void __iomem *addr) +{ + *(volatile unsigned int __force *) addr = b; +} +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel + #endif diff --git a/include/asm-um/ldt-x86_64.h b/include/asm-um/ldt-x86_64.h index 175722a91164..96b35aada79a 100644 --- a/include/asm-um/ldt-x86_64.h +++ b/include/asm-um/ldt-x86_64.h @@ -5,8 +5,8 @@ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com> */ -#ifndef __ASM_LDT_I386_H -#define __ASM_LDT_I386_H +#ifndef __ASM_LDT_X86_64_H +#define __ASM_LDT_X86_64_H #include "asm/semaphore.h" #include "asm/arch/ldt.h" @@ -39,11 +39,13 @@ typedef struct uml_ldt { } uml_ldt_t; /* - * macros stolen from include/asm-i386/desc.h + * macros stolen from include/asm-x86_64/desc.h */ #define LDT_entry_a(info) \ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) +/* Don't allow setting of the lm bit. It is useless anyways because + * 64bit system calls require __USER_CS. */ #define LDT_entry_b(info) \ (((info)->base_addr & 0xff000000) | \ (((info)->base_addr & 0x00ff0000) >> 16) | \ @@ -54,6 +56,7 @@ typedef struct uml_ldt { ((info)->seg_32bit << 22) | \ ((info)->limit_in_pages << 23) | \ ((info)->useable << 20) | \ + /* ((info)->lm << 21) | */ \ 0x7000) #define LDT_empty(info) (\ @@ -64,6 +67,7 @@ typedef struct uml_ldt { (info)->seg_32bit == 0 && \ (info)->limit_in_pages == 0 && \ (info)->seg_not_present == 1 && \ - (info)->useable == 0 ) + (info)->useable == 0 && \ + (info)->lm == 0) #endif diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h index d879eba2b52c..aeda6657f366 100644 --- a/include/asm-um/smp.h +++ b/include/asm-um/smp.h @@ -23,6 +23,8 @@ extern inline void smp_cpus_done(unsigned int maxcpus) { } +extern struct task_struct *idle_threads[NR_CPUS]; + #endif #endif diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index 705c71972c32..17b6b07c4332 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -69,6 +69,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTART_BLOCK 4 #define TIF_MEMDIE 5 #define TIF_SYSCALL_AUDIT 6 +#define TIF_RESTORE_SIGMASK 7 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) @@ -76,16 +77,6 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_MEMDIE (1 << TIF_MEMDIE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #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/include/asm-um/unistd.h b/include/asm-um/unistd.h index 6fdde45cc053..afccfcaa9ea9 100644 --- a/include/asm-um/unistd.h +++ b/include/asm-um/unistd.h @@ -34,6 +34,7 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]); #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #endif #ifdef __KERNEL_SYSCALLS__ diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h index 8955d2376ac8..609b9e87222a 100644 --- a/include/asm-v850/bitops.h +++ b/include/asm-v850/bitops.h @@ -188,7 +188,7 @@ static inline int find_next_zero_bit(const void *addr, int size, int offset) tmp = *p; found_first: - tmp |= ~0UL >> size; + tmp |= ~0UL << size; found_middle: return result + ffz (tmp); } diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h index 4f6a4dc455bb..bdbd8935612a 100644 --- a/include/asm-x86_64/apic.h +++ b/include/asm-x86_64/apic.h @@ -17,6 +17,7 @@ #define APIC_DEBUG 2 extern int apic_verbosity; +extern int apic_runs_main_timer; /* * Define the default level of output to be very little diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h index 41c0ac8559be..76bb6193ae91 100644 --- a/include/asm-x86_64/cpufeature.h +++ b/include/asm-x86_64/cpufeature.h @@ -61,7 +61,7 @@ #define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ #define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ #define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ -/* 4 free */ +#define X86_FEATURE_REP_GOOD (3*32+ 4) /* rep microcode works well on this CPU */ #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */ #define X86_FEATURE_SYNC_RDTSC (3*32+6) /* RDTSC syncs CPU core */ diff --git a/include/asm-x86_64/edac.h b/include/asm-x86_64/edac.h new file mode 100644 index 000000000000..cad1cd42b4ee --- /dev/null +++ b/include/asm-x86_64/edac.h @@ -0,0 +1,18 @@ +#ifndef ASM_EDAC_H +#define ASM_EDAC_H + +/* ECC atomic, DMA, SMP and interrupt safe scrub function */ + +static __inline__ void atomic_scrub(void *va, u32 size) +{ + unsigned int *virt_addr = va; + u32 i; + + for (i = 0; i < size / 4; i++, virt_addr++) + /* Very carefully read and write to memory atomically + * so we are interrupt, DMA and SMP safe. + */ + __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr)); +} + +#endif diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h index 8661b476fb40..8689951e3503 100644 --- a/include/asm-x86_64/hardirq.h +++ b/include/asm-x86_64/hardirq.h @@ -16,23 +16,6 @@ #define set_softirq_pending(x) write_pda(__softirq_pending, (x)) #define or_softirq_pending(x) or_pda(__softirq_pending, (x)) -/* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves. - */ -static inline void ack_bad_irq(unsigned int irq) -{ - printk("unexpected IRQ trap at vector %02x\n", irq); -#ifdef CONFIG_X86_LOCAL_APIC - /* - * Currently unexpected vectors happen only on SMP and APIC. - * We _must_ ack these because every local APIC has only N - * irq slots per priority level, and a 'hanging, unacked' IRQ - * holds up an irq slot - in excessive cases (when multiple - * unexpected vectors occur) that might lock up the APIC - * completely. - */ - ack_APIC_irq(); -#endif -} +extern void ack_bad_irq(unsigned int irq); + #endif /* __ASM_HARDIRQ_H */ diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h index c20c28f5c7a0..08b75c15269a 100644 --- a/include/asm-x86_64/hpet.h +++ b/include/asm-x86_64/hpet.h @@ -55,6 +55,8 @@ extern int is_hpet_enabled(void); extern int hpet_rtc_timer_init(void); extern int oem_force_hpet_timer(void); +extern int hpet_use_timer; + #ifdef CONFIG_HPET_EMULATE_RTC extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); extern int hpet_set_rtc_irq_bit(unsigned long bit_mask); diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h index e8843362a6cc..eeb2bcd635de 100644 --- a/include/asm-x86_64/ia32_unistd.h +++ b/include/asm-x86_64/ia32_unistd.h @@ -300,7 +300,23 @@ #define __NR_ia32_inotify_add_watch 292 #define __NR_ia32_inotify_rm_watch 293 #define __NR_ia32_migrate_pages 294 +#define __NR_ia32_openat 295 +#define __NR_ia32_mkdirat 296 +#define __NR_ia32_mknodat 297 +#define __NR_ia32_fchownat 298 +#define __NR_ia32_futimesat 299 +#define __NR_ia32_fstatat64 300 +#define __NR_ia32_unlinkat 301 +#define __NR_ia32_renameat 302 +#define __NR_ia32_linkat 303 +#define __NR_ia32_symlinkat 304 +#define __NR_ia32_readlinkat 305 +#define __NR_ia32_fchmodat 306 +#define __NR_ia32_faccessat 307 +#define __NR_ia32_pselect6 308 +#define __NR_ia32_ppoll 309 +#define __NR_ia32_unshare 310 -#define IA32_NR_syscalls 295 /* must be > than biggest syscall! */ +#define IA32_NR_syscalls 315 /* must be > than biggest syscall! */ #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h index ae28cd44bcd3..c564bae03433 100644 --- a/include/asm-x86_64/kexec.h +++ b/include/asm-x86_64/kexec.h @@ -1,8 +1,9 @@ #ifndef _X86_64_KEXEC_H #define _X86_64_KEXEC_H +#include <linux/string.h> + #include <asm/page.h> -#include <asm/proto.h> #include <asm/ptrace.h> /* diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h index 10248a9a0582..14fc3ddd9031 100644 --- a/include/asm-x86_64/mpspec.h +++ b/include/asm-x86_64/mpspec.h @@ -188,7 +188,7 @@ extern void mp_register_lapic_address (u64 address); extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base); extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi); extern void mp_config_acpi_legacy_irqs (void); -extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low); +extern int mp_register_gsi (u32 gsi, int triggering, int polarity); #endif /*CONFIG_X86_IO_APIC*/ #endif diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index 34e434ce3268..dffe276ca2df 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h @@ -22,8 +22,15 @@ extern void numa_set_node(int cpu, int node); extern unsigned char apicid_to_node[256]; #ifdef CONFIG_NUMA extern void __init init_cpu_to_node(void); + +static inline void clear_node_cpumask(int cpu) +{ + clear_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); +} + #else #define init_cpu_to_node() do {} while (0) +#define clear_node_cpumask(cpu) do {} while (0) #endif #define NUMA_NO_NODE 0xff diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index 115e496c6139..c99832e7bf3f 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -41,10 +41,18 @@ extern void iommu_hole_init(void); extern void time_init_gtod(void); extern int pmtimer_mark_offset(void); +extern void pmtimer_resume(void); +extern void pmtimer_wait(unsigned); extern unsigned int do_gettimeoffset_pm(void); +#ifdef CONFIG_X86_PM_TIMER extern u32 pmtmr_ioport; +#else +#define pmtmr_ioport 0 +#endif extern unsigned long long monotonic_base; extern int sysctl_vsyscall; +extern int nohpet; +extern unsigned long vxtime_hz; extern void do_softirq_thunk(void); @@ -65,6 +73,9 @@ extern void free_bootmem_generic(unsigned long phys, unsigned len); extern void load_gs_index(unsigned gs); +extern void stop_timer_interrupt(void); +extern void main_timer_handler(struct pt_regs *regs); + extern unsigned long end_pfn_map; extern void show_trace(unsigned long * rsp); diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index a73f0c789d8b..b7f66034ae7a 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h @@ -327,7 +327,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define wmb() asm volatile("" ::: "memory") #endif #define read_barrier_depends() do {} while(0) -#define set_mb(var, value) do { xchg(&var, value); } while (0) +#define set_mb(var, value) do { (void) xchg(&var, value); } while (0) #define set_wmb(var, value) do { var = value; wmb(); } while (0) #define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0) diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 2fa7f27381b4..c642f5d9882d 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -57,6 +57,15 @@ extern int __node_distance(int, int); #endif +#ifdef CONFIG_SMP +#define topology_physical_package_id(cpu) \ + (phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu]) +#define topology_core_id(cpu) \ + (cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu]) +#define topology_core_siblings(cpu) (cpu_core_map[cpu]) +#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) +#endif + #include <asm-generic/topology.h> #endif diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index e6f896161c11..da0341c57949 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -573,8 +573,41 @@ __SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch) __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) #define __NR_migrate_pages 256 __SYSCALL(__NR_migrate_pages, sys_migrate_pages) +#define __NR_openat 257 +__SYSCALL(__NR_openat, sys_openat) +#define __NR_mkdirat 258 +__SYSCALL(__NR_mkdirat, sys_mkdirat) +#define __NR_mknodat 259 +__SYSCALL(__NR_mknodat, sys_mknodat) +#define __NR_fchownat 260 +__SYSCALL(__NR_fchownat, sys_fchownat) +#define __NR_futimesat 261 +__SYSCALL(__NR_futimesat, sys_futimesat) +#define __NR_newfstatat 262 +__SYSCALL(__NR_newfstatat, sys_newfstatat) +#define __NR_unlinkat 263 +__SYSCALL(__NR_unlinkat, sys_unlinkat) +#define __NR_renameat 264 +__SYSCALL(__NR_renameat, sys_renameat) +#define __NR_linkat 265 +__SYSCALL(__NR_linkat, sys_linkat) +#define __NR_symlinkat 266 +__SYSCALL(__NR_symlinkat, sys_symlinkat) +#define __NR_readlinkat 267 +__SYSCALL(__NR_readlinkat, sys_readlinkat) +#define __NR_fchmodat 268 +__SYSCALL(__NR_fchmodat, sys_fchmodat) +#define __NR_faccessat 269 +__SYSCALL(__NR_faccessat, sys_faccessat) +#define __NR_pselect6 270 +__SYSCALL(__NR_pselect6, sys_ni_syscall) /* for now */ +#define __NR_ppoll 271 +__SYSCALL(__NR_ppoll, sys_ni_syscall) /* for now */ +#define __NR_unshare 272 +__SYSCALL(__NR_unshare, sys_unshare) + +#define __NR_syscall_max __NR_unshare -#define __NR_syscall_max __NR_migrate_pages #ifndef __NO_STUBS /* user-visible error numbers are in the range -1 - -4095 */ diff --git a/include/asm-xtensa/futex.h b/include/asm-xtensa/futex.h new file mode 100644 index 000000000000..0b745828f42b --- /dev/null +++ b/include/asm-xtensa/futex.h @@ -0,0 +1 @@ +#include <asm-generic/futex.h> diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 026c3c011dc0..84d3d9f034ce 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -435,7 +435,7 @@ extern int sbf_port ; #endif /* !CONFIG_ACPI */ -int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low); +int acpi_register_gsi (u32 gsi, int triggering, int polarity); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); /* diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h index 17a17c55a17f..6d59c8efe3be 100644 --- a/include/linux/agpgart.h +++ b/include/linux/agpgart.h @@ -111,6 +111,7 @@ typedef struct _agp_unbind { } agp_unbind; #else /* __KERNEL__ */ +#include <linux/mutex.h> #define AGPGART_MINOR 175 @@ -201,7 +202,7 @@ struct agp_file_private { }; struct agp_front_data { - struct semaphore agp_mutex; + struct mutex agp_mutex; struct agp_controller *current_controller; struct agp_controller *controllers; struct agp_file_private *file_priv_list; diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 6a2a19f14bb2..208650b1ad3a 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -81,7 +81,7 @@ static inline int generic_fls64(__u64 x) { __u32 h = x >> 32; if (h) - return fls(x) + 32; + return fls(h) + 32; return fls(x); } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 02a585faa62c..860e7a485a5f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -392,8 +392,8 @@ struct request_queue unsigned int nr_congestion_off; unsigned int nr_batching; - unsigned short max_sectors; - unsigned short max_hw_sectors; + unsigned int max_sectors; + unsigned int max_hw_sectors; unsigned short max_phys_segments; unsigned short max_hw_segments; unsigned short hardsect_size; @@ -697,7 +697,7 @@ extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *); extern void blk_cleanup_queue(request_queue_t *); extern void blk_queue_make_request(request_queue_t *, make_request_fn *); extern void blk_queue_bounce_limit(request_queue_t *, u64); -extern void blk_queue_max_sectors(request_queue_t *, unsigned short); +extern void blk_queue_max_sectors(request_queue_t *, unsigned int); extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short); extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short); extern void blk_queue_max_segment_size(request_queue_t *, unsigned int); diff --git a/include/linux/compat.h b/include/linux/compat.h index f9ca534787e2..c9ab2a26348c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -161,5 +161,25 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); +static inline int compat_timeval_compare(struct compat_timeval *lhs, + struct compat_timeval *rhs) +{ + if (lhs->tv_sec < rhs->tv_sec) + return -1; + if (lhs->tv_sec > rhs->tv_sec) + return 1; + return lhs->tv_usec - rhs->tv_usec; +} + +static inline int compat_timespec_compare(struct compat_timespec *lhs, + struct compat_timespec *rhs) +{ + if (lhs->tv_sec < rhs->tv_sec) + return -1; + if (lhs->tv_sec > rhs->tv_sec) + return 1; + return lhs->tv_nsec - rhs->tv_nsec; +} + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/include/linux/configfs.h b/include/linux/configfs.h index acffb8c9073a..a7f015027535 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h @@ -126,7 +126,7 @@ extern struct config_item *config_group_find_obj(struct config_group *, const ch struct configfs_attribute { - char *ca_name; + const char *ca_name; struct module *ca_owner; mode_t ca_mode; }; diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 13e9f4a3ab26..60e56c6e03dd 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -84,7 +84,6 @@ #include <linux/kernel.h> #include <linux/threads.h> #include <linux/bitmap.h> -#include <asm/bug.h> typedef struct { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; extern cpumask_t _unused_cpumask_arg_; @@ -329,7 +328,7 @@ static inline void __cpus_remap(cpumask_t *dstp, const cpumask_t *srcp, * bitmap of size NR_CPUS. * * #ifdef CONFIG_HOTPLUG_CPU - * cpu_possible_map - all NR_CPUS bits set + * cpu_possible_map - has bit 'cpu' set iff cpu is populatable * cpu_present_map - has bit 'cpu' set iff cpu is populated * cpu_online_map - has bit 'cpu' set iff cpu available to scheduler * #else diff --git a/include/linux/dcache.h b/include/linux/dcache.h index a3ed5e059d47..4361f3789975 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -8,7 +8,6 @@ #include <linux/spinlock.h> #include <linux/cache.h> #include <linux/rcupdate.h> -#include <asm/bug.h> struct nameidata; struct vfsmount; @@ -108,7 +107,9 @@ struct dentry { struct dentry_operations *d_op; struct super_block *d_sb; /* The root of the dentry tree */ void *d_fsdata; /* fs-specific data */ +#ifdef CONFIG_PROFILING struct dcookie_struct *d_cookie; /* cookie, if any */ +#endif int d_mounted; unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ }; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 83c7d207b80e..51e0e95a421a 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -91,7 +91,7 @@ struct target_type { }; struct io_restrictions { - unsigned short max_sectors; + unsigned int max_sectors; unsigned short max_phys_segments; unsigned short max_hw_segments; unsigned short hardsect_size; diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index b1999bfeaa56..b81e58b2ebf8 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -135,7 +135,7 @@ typedef struct video_spu { typedef struct video_spu_palette { /* SPU Palette information */ int length; - uint8_t *palette; + uint8_t __user *palette; } video_spu_palette_t; diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 23fe746a1d51..18cf1f3e1184 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -82,6 +82,7 @@ struct elevator_queue extern void elv_dispatch_sort(request_queue_t *, struct request *); extern void elv_add_request(request_queue_t *, struct request *, int, int); extern void __elv_add_request(request_queue_t *, struct request *, int, int); +extern void elv_insert(request_queue_t *, struct request *, int); extern int elv_merge(request_queue_t *, struct request **, struct bio *); extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index dbd7bb4a33b7..0cf0bea010fe 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -5,6 +5,7 @@ #include <linux/signal.h> #include <linux/time.h> #include <linux/user.h> +#include <linux/ptrace.h> struct elf_siginfo { diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h index 8a7c82151de9..c52a63755fdd 100644 --- a/include/linux/fcntl.h +++ b/include/linux/fcntl.h @@ -23,6 +23,13 @@ #define DN_ATTRIB 0x00000020 /* File changed attibutes */ #define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ +#define AT_FDCWD -100 /* Special value used to indicate + openat should use the current + working directory. */ +#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */ +#define AT_REMOVEDIR 0x200 /* Remove directory instead of + unlinking file. */ + #ifdef __KERNEL__ #ifndef force_o_largefile diff --git a/include/linux/fs.h b/include/linux/fs.h index b77f2608eef9..e059da947007 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -363,6 +363,8 @@ struct address_space_operations { loff_t offset, unsigned long nr_segs); struct page* (*get_xip_page)(struct address_space *, sector_t, int); + /* migrate the contents of a page to the specified target */ + int (*migratepage) (struct page *, struct page *); }; struct backing_dev_info; @@ -1340,7 +1342,8 @@ static inline int break_lease(struct inode *inode, unsigned int mode) extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, struct file *filp); -extern long do_sys_open(const char __user *filename, int flags, int mode); +extern long do_sys_open(int fdf, const char __user *filename, int flags, + int mode); extern struct file *filp_open(const char *, int, int); extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); extern int filp_close(struct file *, fl_owner_t id); @@ -1479,7 +1482,7 @@ static inline void allow_write_access(struct file *file) } extern int do_pipe(int *); -extern int open_namei(const char *, int, int, struct nameidata *); +extern int open_namei(int dfd, const char *, int, int, struct nameidata *); extern int may_open(struct nameidata *, int, int); extern int kernel_read(struct file *, unsigned long, char *, unsigned long); @@ -1677,6 +1680,8 @@ extern int vfs_readdir(struct file *, filldir_t, void *); extern int vfs_stat(char __user *, struct kstat *); extern int vfs_lstat(char __user *, struct kstat *); +extern int vfs_stat_fd(int dfd, char __user *, struct kstat *); +extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *); extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long); @@ -1716,6 +1721,12 @@ extern void simple_release_fs(struct vfsmount **mount, int *count); extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t); +#ifdef CONFIG_MIGRATION +extern int buffer_migrate_page(struct page *, struct page *); +#else +#define buffer_migrate_page NULL +#endif + extern int inode_change_ok(struct inode *, struct iattr *); extern int __must_check inode_setattr(struct inode *, struct iattr *); diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 528959c52f1b..5425b60021e3 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -14,7 +14,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 5 +#define FUSE_KERNEL_MINOR_VERSION 6 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -58,6 +58,9 @@ struct fuse_kstatfs { __u32 spare[6]; }; +/** + * Bitmasks for fuse_setattr_in.valid + */ #define FATTR_MODE (1 << 0) #define FATTR_UID (1 << 1) #define FATTR_GID (1 << 2) @@ -75,6 +78,11 @@ struct fuse_kstatfs { #define FOPEN_DIRECT_IO (1 << 0) #define FOPEN_KEEP_CACHE (1 << 1) +/** + * INIT request/reply flags + */ +#define FUSE_ASYNC_READ (1 << 0) + enum fuse_opcode { FUSE_LOOKUP = 1, FUSE_FORGET = 2, /* no reply */ @@ -247,12 +255,16 @@ struct fuse_access_in { struct fuse_init_in { __u32 major; __u32 minor; + __u32 max_readahead; + __u32 flags; }; struct fuse_init_out { __u32 major; __u32 minor; - __u32 unused[3]; + __u32 max_readahead; + __u32 flags; + __u32 unused; __u32 max_write; }; diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 089bfb1fa01a..6361544bb6ae 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -40,6 +40,7 @@ enum hrtimer_restart { enum hrtimer_state { HRTIMER_INACTIVE, /* Timer is inactive */ HRTIMER_EXPIRED, /* Timer is expired */ + HRTIMER_RUNNING, /* Timer is running the callback function */ HRTIMER_PENDING, /* Timer is pending */ }; @@ -100,9 +101,8 @@ struct hrtimer_base { /* Exported timer functions: */ /* Initialize timers: */ -extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock); -extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock); - +extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, + enum hrtimer_mode mode); /* Basic timer operations: */ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 7863a59bd598..63f1d63cc1d8 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -100,6 +100,9 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client, /* Returns the number of read bytes */ extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, u8 command, u8 *values); +extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, + u8 command, u8 length, + u8 *values); /* * A driver is capable of handling one or more physical devices present on diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 9ba806796667..5a9d8c599171 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -1115,9 +1115,11 @@ static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c) return ERR_PTR(-ENOMEM); mmsg->mfa = readl(c->in_port); - if (mmsg->mfa == I2O_QUEUE_EMPTY) { + if (unlikely(mmsg->mfa >= c->in_queue.len)) { mempool_free(mmsg, c->in_msg.mempool); - return ERR_PTR(-EBUSY); + if(mmsg->mfa == I2O_QUEUE_EMPTY) + return ERR_PTR(-EBUSY); + return ERR_PTR(-EFAULT); } return &mmsg->msg; diff --git a/include/linux/ide.h b/include/linux/ide.h index 110b3cfac021..a7fc4cc79b23 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -582,7 +582,6 @@ typedef struct ide_drive_s { unsigned noprobe : 1; /* from: hdx=noprobe */ unsigned removable : 1; /* 1 if need to do check_media_change */ unsigned attach : 1; /* needed for removable devices */ - unsigned is_flash : 1; /* 1 if probed as flash */ unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */ unsigned no_unmask : 1; /* disallow setting unmask bit */ unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ @@ -1006,7 +1005,6 @@ extern ide_hwif_t ide_hwifs[]; /* master data repository */ extern int noautodma; extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); -extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs); /* * This is used on exit from the driver to designate the next irq handler diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index fe26d431de87..7a92c1ce1457 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -72,6 +72,7 @@ * over Ethernet */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_TIPC 0x88CA /* TIPC */ /* * Non DIX types. Won't clash for 1500 types. diff --git a/include/linux/io.h b/include/linux/io.h new file mode 100644 index 000000000000..85533ec5aaa1 --- /dev/null +++ b/include/linux/io.h @@ -0,0 +1,25 @@ +/* + * Copyright 2006 PathScale, Inc. All Rights Reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _LINUX_IO_H +#define _LINUX_IO_H + +#include <asm/io.h> + +void __iowrite32_copy(void __iomem *to, const void *from, size_t count); + +#endif /* _LINUX_IO_H */ diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h index e7906a72a4f1..da7c09e4ede6 100644 --- a/include/linux/ioc3.h +++ b/include/linux/ioc3.h @@ -27,7 +27,7 @@ struct ioc3_driver_data { int id; /* IOC3 sequence number */ /* PCI mapping */ unsigned long pma; /* physical address */ - struct __iomem ioc3 *vma; /* pointer to registers */ + struct ioc3 __iomem *vma; /* pointer to registers */ struct pci_dev *pdev; /* PCI device */ /* IRQ stuff */ int dual_irq; /* set if separate IRQs are used */ diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 558cb4c26ec9..0fe4aa891ddc 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -23,6 +23,7 @@ #define jfs_debug jbd_debug #else +#include <linux/types.h> #include <linux/buffer_head.h> #include <linux/journal-head.h> #include <linux/stddef.h> @@ -238,7 +239,6 @@ typedef struct journal_superblock_s #include <linux/fs.h> #include <linux/sched.h> -#include <asm/bug.h> #define JBD_ASSERTIONS #ifdef JBD_ASSERTIONS @@ -618,6 +618,7 @@ struct transaction_s * @j_wbuf: array of buffer_heads for journal_commit_transaction * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the * number that will fit in j_blocksize + * @j_last_sync_writer: most recent pid which did a synchronous write * @j_private: An opaque pointer to fs-private information. */ @@ -807,6 +808,8 @@ struct journal_s struct buffer_head **j_wbuf; int j_wbufsize; + pid_t j_last_sync_writer; + /* * An opaque pointer to fs-private information. ext3 puts its * superblock pointer here diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index 45f625d7d0b2..e87c32a5c86a 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -151,6 +151,13 @@ extern unsigned int keymap_count; static inline void con_schedule_flip(struct tty_struct *t) { + unsigned long flags; + spin_lock_irqsave(&t->buf.lock, flags); + if (t->buf.tail != NULL) { + t->buf.tail->active = 0; + t->buf.tail->commit = t->buf.tail->used; + } + spin_unlock_irqrestore(&t->buf.lock, flags); schedule_work(&t->buf.work); } diff --git a/include/linux/kernel.h b/include/linux/kernel.h index a5363324cf95..b49affa0ac5a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -185,6 +185,7 @@ extern enum system_states { SYSTEM_HALT, SYSTEM_POWER_OFF, SYSTEM_RESTART, + SYSTEM_SUSPEND_DISK, } system_state; #define TAINT_PROPRIETARY_MODULE (1<<0) diff --git a/include/linux/kexec.h b/include/linux/kexec.h index a311f58c8a7c..cfb3410e32b1 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -6,6 +6,7 @@ #include <linux/list.h> #include <linux/linkage.h> #include <linux/compat.h> +#include <linux/ioport.h> #include <asm/kexec.h> /* Verify architecture specific macros are defined */ diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 1bd6552cc341..6aca67a569a2 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -10,6 +10,12 @@ * * Started by: Thomas Gleixner and Ingo Molnar * + * Credits: + * + * Roman Zippel provided the ideas and primary code snippets of + * the ktime_t union and further simplifications of the original + * code. + * * For licencing details see kernel-base/COPYING */ #ifndef _LINUX_KTIME_H diff --git a/include/linux/list.h b/include/linux/list.h index 945daa1f13dd..47208bd99f9e 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -34,9 +34,11 @@ struct list_head { #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} /* * Insert a new entry between two known consecutive entries. @@ -534,7 +536,11 @@ struct hlist_node { #define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} static inline int hlist_unhashed(const struct hlist_node *h) { diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 95c8fea293ba..920766cea79c 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -84,6 +84,7 @@ struct nlm_rqst { struct nlm_args a_args; /* arguments */ struct nlm_res a_res; /* result */ struct nlm_wait * a_block; + unsigned int a_retries; /* Retry count */ char a_owner[NLMCLNT_OHSIZE]; }; @@ -148,7 +149,6 @@ struct nlm_rqst * nlmclnt_alloc_call(void); int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl); void nlmclnt_finish_block(struct nlm_rqst *req); long nlmclnt_block(struct nlm_rqst *req, long timeout); -int nlmclnt_cancel(struct nlm_host *, struct file_lock *); u32 nlmclnt_grant(struct nlm_lock *); void nlmclnt_recovery(struct nlm_host *, u32); int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index d6a53ed6ab6c..bbd2221923c3 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -159,6 +159,7 @@ extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new); extern struct mempolicy default_policy; extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr); +extern unsigned slab_node(struct mempolicy *policy); extern int policy_zone; diff --git a/include/linux/mm.h b/include/linux/mm.h index 85854b867463..75e9f0724997 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -303,7 +303,7 @@ struct page { */ #define put_page_testzero(p) \ ({ \ - BUG_ON(page_count(p) == 0); \ + BUG_ON(atomic_read(&(p)->_count) == -1);\ atomic_add_negative(-1, &(p)->_count); \ }) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 49cc68af01f8..8ac854f7f190 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -39,24 +39,3 @@ del_page_from_lru(struct zone *zone, struct page *page) } } -/* - * Isolate one page from the LRU lists. - * - * - zone->lru_lock must be held - */ -static inline int __isolate_lru_page(struct page *page) -{ - if (unlikely(!TestClearPageLRU(page))) - return 0; - - if (get_page_testone(page)) { - /* - * It is being freed elsewhere - */ - __put_page(page); - SetPageLRU(page); - return -ENOENT; - } - - return 1; -} diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index ccd3e13de1e8..f38872abc126 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -21,24 +21,35 @@ struct mmc_command { u32 arg; u32 resp[4]; unsigned int flags; /* expected response type */ -#define MMC_RSP_NONE (0 << 0) -#define MMC_RSP_SHORT (1 << 0) -#define MMC_RSP_LONG (2 << 0) -#define MMC_RSP_MASK (3 << 0) -#define MMC_RSP_CRC (1 << 3) /* expect valid crc */ -#define MMC_RSP_BUSY (1 << 4) /* card may send busy */ -#define MMC_RSP_OPCODE (1 << 5) /* response contains opcode */ +#define MMC_RSP_PRESENT (1 << 0) +#define MMC_RSP_136 (1 << 1) /* 136 bit response */ +#define MMC_RSP_CRC (1 << 2) /* expect valid crc */ +#define MMC_RSP_BUSY (1 << 3) /* card may send busy */ +#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */ +#define MMC_CMD_MASK (3 << 5) /* command type */ +#define MMC_CMD_AC (0 << 5) +#define MMC_CMD_ADTC (1 << 5) +#define MMC_CMD_BC (2 << 5) +#define MMC_CMD_BCR (3 << 5) /* * These are the response types, and correspond to valid bit * patterns of the above flags. One additional valid pattern * is all zeros, which means we don't expect a response. */ -#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE) -#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) -#define MMC_RSP_R2 (MMC_RSP_LONG|MMC_RSP_CRC) -#define MMC_RSP_R3 (MMC_RSP_SHORT) -#define MMC_RSP_R6 (MMC_RSP_SHORT|MMC_RSP_CRC) +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) +#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC) + +#define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE)) + +/* + * These are the command types. + */ +#define mmc_cmd_type(cmd) ((cmd)->flags & MMC_CMD_TYPE) unsigned int retries; /* max number of retries */ unsigned int error; /* command error */ diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h index a14dc306545b..81c3f77f652c 100644 --- a/include/linux/mmc/protocol.h +++ b/include/linux/mmc/protocol.h @@ -79,7 +79,7 @@ /* SD commands type argument response */ /* class 8 */ /* This is basically the same command as for MMC with some quirks. */ -#define SD_SEND_RELATIVE_ADDR 3 /* ac R6 */ +#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ /* Application commands */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 34cbefd2ebde..ebfc238cc243 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -91,10 +91,21 @@ struct per_cpu_pageset { * be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible * combinations of zone modifiers in "zone modifier space". * + * As an optimisation any zone modifier bits which are only valid when + * no other zone modifier bits are set (loners) should be placed in + * the highest order bits of this field. This allows us to reduce the + * extent of the zonelists thus saving space. For example in the case + * of three zone modifier bits, we could require up to eight zonelists. + * If the left most zone modifier is a "loner" then the highest valid + * zonelist would be four allowing us to allocate only five zonelists. + * Use the first form for GFP_ZONETYPES when the left most bit is not + * a "loner", otherwise use the second. + * * NOTE! Make sure this matches the zones in <linux/gfp.h> */ #define GFP_ZONEMASK 0x07 -#define GFP_ZONETYPES 5 +/* #define GFP_ZONETYPES (GFP_ZONEMASK + 1) */ /* Non-loner */ +#define GFP_ZONETYPES ((GFP_ZONEMASK + 1) / 2 + 1) /* Loner */ /* * On machines where it is needed (eg PCs) we divide physical memory @@ -149,15 +160,17 @@ struct zone { unsigned long pages_scanned; /* since last reclaim */ int all_unreclaimable; /* All pages pinned */ - /* - * Does the allocator try to reclaim pages from the zone as soon - * as it fails a watermark_ok() in __alloc_pages? - */ - int reclaim_pages; /* A count of how many reclaimers are scanning this zone */ atomic_t reclaim_in_progress; /* + * timestamp (in jiffies) of the last zone reclaim that did not + * result in freeing of pages. This is used to avoid repeated scans + * if all memory in the zone is in use. + */ + unsigned long last_unsuccessful_zone_reclaim; + + /* * prev_priority holds the scanning priority for this zone. It is * defined as the scanning priority at which we achieved our reclaim * target at the previous try_to_free_pages() or balance_pgdat() diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index fedfbc8a287f..7dfd6e1fcde7 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -15,7 +15,6 @@ #include <asm/unaligned.h> #include <asm/system.h> #include <asm/io.h> -#include <asm/bug.h> #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 #define map_bankwidth(map) 1 diff --git a/include/linux/namei.h b/include/linux/namei.h index b699e427c00c..e6698013e4d0 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -56,10 +56,11 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_ACCESS (0x0400) extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *)); +extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *)); #define user_path_walk(name,nd) \ - __user_walk(name, LOOKUP_FOLLOW, nd) + __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd) #define user_path_walk_link(name,nd) \ - __user_walk(name, 0, nd) + __user_walk_fd(AT_FDCWD, name, 0, nd) extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); @@ -67,7 +68,7 @@ extern void path_release(struct nameidata *); extern void path_release_on_umount(struct nameidata *); extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags); -extern int path_lookup_open(const char *, unsigned lookup_flags, struct nameidata *, int open_flags); +extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags); extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, int (*open)(struct inode *, struct file *)); extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 6731977c4c13..3abc8e3b4879 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -15,6 +15,7 @@ struct namespace { extern int copy_namespace(int, struct task_struct *); extern void __put_namespace(struct namespace *namespace); +extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *); static inline void put_namespace(struct namespace *namespace) { diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 472f04834809..6500d4e59d46 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -19,7 +19,21 @@ struct xt_get_revision /* For standard target */ #define XT_RETURN (-NF_REPEAT - 1) -#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1)) +/* this is a dummy structure to find out the alignment requirement for a struct + * containing all the fundamental data types that are used in ipt_entry, + * ip6t_entry and arpt_entry. This sucks, and it is a hack. It will be my + * personal pleasure to remove it -HW + */ +struct _xt_align +{ + u_int8_t u8; + u_int16_t u16; + u_int32_t u32; + u_int64_t u64; +}; + +#define XT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) \ + & ~(__alignof__(struct _xt_align)-1)) /* Standard return verdict, or do jump. */ #define XT_STANDARD_TARGET "" diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h index b04dfa3083c9..f63e6ee91113 100644 --- a/include/linux/netfilter_ipv4/ipt_connbytes.h +++ b/include/linux/netfilter_ipv4/ipt_connbytes.h @@ -1,10 +1,10 @@ #ifndef _IPT_CONNBYTES_H #define _IPT_CONNBYTES_H -#include <net/netfilter/xt_connbytes.h> +#include <linux/netfilter/xt_connbytes.h> #define ipt_connbytes_what xt_connbytes_what -#define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS +#define IPT_CONNBYTES_PKTS XT_CONNBYTES_PKTS #define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES #define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h index 7fd1bec453f1..a3f6eff39d33 100644 --- a/include/linux/netfilter_ipv4/ipt_policy.h +++ b/include/linux/netfilter_ipv4/ipt_policy.h @@ -27,16 +27,22 @@ struct ipt_policy_spec reqid:1; }; +union ipt_policy_addr +{ + struct in_addr a4; + struct in6_addr a6; +}; + struct ipt_policy_elem { - u_int32_t saddr; - u_int32_t smask; - u_int32_t daddr; - u_int32_t dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; + union ipt_policy_addr saddr; + union ipt_policy_addr smask; + union ipt_policy_addr daddr; + union ipt_policy_addr dmask; + u_int32_t spi; + u_int32_t reqid; + u_int8_t proto; + u_int8_t mode; struct ipt_policy_spec match; struct ipt_policy_spec invert; diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h index 5a93afcd2ff1..671bd818300f 100644 --- a/include/linux/netfilter_ipv6/ip6t_policy.h +++ b/include/linux/netfilter_ipv6/ip6t_policy.h @@ -27,16 +27,22 @@ struct ip6t_policy_spec reqid:1; }; +union ip6t_policy_addr +{ + struct in_addr a4; + struct in6_addr a6; +}; + struct ip6t_policy_elem { - struct in6_addr saddr; - struct in6_addr smask; - struct in6_addr daddr; - struct in6_addr dmask; - u_int32_t spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; + union ip6t_policy_addr saddr; + union ip6t_policy_addr smask; + union ip6t_policy_addr daddr; + union ip6t_policy_addr dmask; + u_int32_t spi; + u_int32_t reqid; + u_int8_t proto; + u_int8_t mode; struct ip6t_policy_spec match; struct ip6t_policy_spec invert; diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 6a2ccf78a356..c256ebe2a7b4 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -160,7 +160,8 @@ extern int netlink_unregister_notifier(struct notifier_block *nb); /* finegrained unicast helpers: */ struct sock *netlink_getsockbyfilp(struct file *filp); -int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo); +int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, + long timeo, struct sock *ssk); void netlink_detachskb(struct sock *sk, struct sk_buff *skb); int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol); diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 51c231a1e5a6..ec7c2e872d72 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -124,7 +124,7 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *, int nfsd_notify_change(struct inode *, struct iattr *); int nfsd_permission(struct svc_export *, struct dentry *, int); -void nfsd_sync_dir(struct dentry *dp); +int nfsd_sync_dir(struct dentry *dp); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 8903688890ce..77adba7d2281 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -145,8 +145,9 @@ struct nfsd4_lock { } ok; struct nfsd4_lock_denied denied; } u; - - struct nfs4_stateowner *lk_stateowner; + /* The lk_replay_owner is the open owner in the open_to_lock_owner + * case and the lock owner otherwise: */ + struct nfs4_stateowner *lk_replay_owner; }; #define lk_new_open_seqid v.new.open_seqid #define lk_new_open_stateid v.new.open_stateid diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 4726ef7ba8e8..b959a4525cbd 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -84,7 +84,6 @@ #include <linux/threads.h> #include <linux/bitmap.h> #include <linux/numa.h> -#include <asm/bug.h> typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t; extern nodemask_t _unused_nodemask_arg_; diff --git a/include/linux/parport.h b/include/linux/parport.h index f67f838a3a1f..008d736a6c9a 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -128,6 +128,11 @@ struct amiga_parport_state { unsigned char statusdir;/* ciab.ddrb & 7 */ }; +struct ip32_parport_state { + unsigned int dcr; + unsigned int ecr; +}; + struct parport_state { union { struct pc_parport_state pc; @@ -135,6 +140,7 @@ struct parport_state { struct ax_parport_state ax; struct amiga_parport_state amiga; /* Atari has not state. */ + struct ip32_parport_state ip32; void *misc; } u; }; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0a44072383ec..fe1a2b02fc55 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -406,7 +406,6 @@ struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int devic struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); int pci_find_capability (struct pci_dev *dev, int cap); int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); -int pci_find_ext_capability (struct pci_dev *dev, int cap); struct pci_bus * pci_find_next_bus(const struct pci_bus *from); struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from); @@ -626,7 +625,6 @@ static inline int pci_register_driver(struct pci_driver *drv) { return 0;} static inline void pci_unregister_driver(struct pci_driver *drv) { } static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; } -static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; } static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } /* Power management related routines */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5403257ae3e7..82b83da25d77 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -394,14 +394,9 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE 0x0028 #define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE 0x002b -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d -#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e -#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f -#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030 #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 @@ -511,8 +506,6 @@ #define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 #define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A -#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A - #define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 #define PCI_DEVICE_ID_AMD_LX_AES 0x2082 @@ -1094,6 +1087,7 @@ #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000 0x0185 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO 0x0186 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO 0x0187 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL 0x0188 @@ -1677,6 +1671,9 @@ #define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060 #define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062 +#define PCI_DEVICE_ID_SIIG_8S_20x_550 0x2080 +#define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 +#define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 #define PCI_VENDOR_ID_RADISYS 0x1331 @@ -1836,6 +1833,7 @@ #define PCI_VENDOR_ID_AFAVLAB 0x14db #define PCI_DEVICE_ID_AFAVLAB_P028 0x2180 #define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 +#define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150 #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 @@ -1992,6 +1990,7 @@ #define PCI_VENDOR_ID_DCI 0x6666 #define PCI_DEVICE_ID_DCI_PCCOM4 0x0001 #define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 +#define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 #define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_EESSC 0x0008 @@ -2064,6 +2063,7 @@ #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db +#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 #define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 @@ -2084,6 +2084,8 @@ #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 #define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 #define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 +#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0 +#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 #define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 #define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 #define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 @@ -2103,6 +2105,13 @@ #define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd #define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de #define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df +#define PCI_DEVICE_ID_INTEL_ICH8_0 0x2810 +#define PCI_DEVICE_ID_INTEL_ICH8_1 0x2811 +#define PCI_DEVICE_ID_INTEL_ICH8_2 0x2812 +#define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814 +#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 +#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e +#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 @@ -2146,6 +2155,7 @@ #define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2 #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 +#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 #define PCI_DEVICE_ID_INTEL_82451NX 0x84ca #define PCI_DEVICE_ID_INTEL_82454NX 0x84cb #define PCI_DEVICE_ID_INTEL_84460GX 0x84ea diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h index 2c177e4c8f22..8a94c717c266 100644 --- a/include/linux/pktcdvd.h +++ b/include/linux/pktcdvd.h @@ -114,7 +114,7 @@ struct pkt_ctrl_command { struct packet_settings { - __u8 size; /* packet size in (512 byte) sectors */ + __u32 size; /* packet size in (512 byte) sectors */ __u8 fp; /* fixed packets */ __u8 link_loss; /* the rest is specified * as per Mt Fuji */ @@ -169,8 +169,8 @@ struct packet_iosched #if (PAGE_SIZE % CD_FRAMESIZE) != 0 #error "PAGE_SIZE must be a multiple of CD_FRAMESIZE" #endif -#define PACKET_MAX_SIZE 32 -#define PAGES_PER_PACKET (PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE) +#define PACKET_MAX_SIZE 128 +#define FRAMES_PER_PAGE (PAGE_SIZE / CD_FRAMESIZE) #define PACKET_MAX_SECTORS (PACKET_MAX_SIZE * CD_FRAMESIZE >> 9) enum packet_data_state { @@ -219,7 +219,7 @@ struct packet_data atomic_t io_errors; /* Number of read/write errors during IO */ struct bio *r_bios[PACKET_MAX_SIZE]; /* bios to use during data gathering */ - struct page *pages[PAGES_PER_PACKET]; + struct page *pages[PACKET_MAX_SIZE / FRAMES_PER_PAGE]; int cache_valid; /* If non-zero, the data for the zone defined */ /* by the sector variable is completely cached */ diff --git a/include/linux/poll.h b/include/linux/poll.h index f6da702088f4..8e8f6098508a 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -92,7 +92,11 @@ void zero_fd_set(unsigned long nr, unsigned long *fdset) memset(fdset, 0, FDS_BYTES(nr)); } -extern int do_select(int n, fd_set_bits *fds, long *timeout); +#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1) + +extern int do_select(int n, fd_set_bits *fds, s64 *timeout); +extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds, + s64 *timeout); #endif /* KERNEL */ diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 54faf5236da0..95572c434bc9 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -84,7 +84,6 @@ struct k_clock { void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock); /* error handlers for timer_create, nanosleep and settime */ -int do_posix_clock_notimer_create(struct k_itimer *timer); int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *, struct timespec __user *); int do_posix_clock_nosettime(const clockid_t, struct timespec *tp); diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 4f34d3d60f2e..21e5a9124856 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -190,7 +190,6 @@ static __inline__ int DQUOT_OFF(struct super_block *sb) */ #define sb_dquot_ops (NULL) #define sb_quotactl_ops (NULL) -#define sync_dquots_dev(dev,type) (NULL) #define DQUOT_INIT(inode) do { } while(0) #define DQUOT_DROP(inode) do { } while(0) #define DQUOT_ALLOC_INODE(inode) (0) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 981f9aa43353..b87aefa082e2 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -240,11 +240,14 @@ extern int rcu_pending(int cpu); * This means that all preempt_disable code sequences, including NMI and * hardware-interrupt handlers, in progress on entry will have completed * before this primitive returns. However, this does not guarantee that - * softirq handlers will have completed, since in some kernels + * softirq handlers will have completed, since in some kernels, these + * handlers can run in process context, and can block. * * This primitive provides the guarantees made by the (deprecated) * synchronize_kernel() API. In contrast, synchronize_rcu() only * guarantees that rcu_read_lock() sections will have completed. + * In "classic RCU", these two guarantees happen to be one and + * the same, but can differ in realtime RCU implementations. */ #define synchronize_sched() synchronize_rcu() diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 7ab2cdb83ef0..015297ff73fa 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -60,8 +60,7 @@ extern void machine_crash_shutdown(struct pt_regs *); */ extern void kernel_restart_prepare(char *cmd); -extern void kernel_halt_prepare(void); -extern void kernel_power_off_prepare(void); +extern void kernel_shutdown_prepare(enum system_states state); extern void kernel_restart(char *cmd); extern void kernel_halt(void); diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h index 0a3605099c44..806ec5b06707 100644 --- a/include/linux/reiserfs_acl.h +++ b/include/linux/reiserfs_acl.h @@ -58,9 +58,13 @@ extern struct reiserfs_xattr_handler posix_acl_default_handler; extern struct reiserfs_xattr_handler posix_acl_access_handler; #else -#define reiserfs_get_acl NULL #define reiserfs_cache_default_acl(inode) 0 +static inline struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) +{ + return NULL; +} + static inline int reiserfs_xattr_posix_acl_init(void) { return 0; diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index e276c5ba2bb7..7d51149bd793 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1971,22 +1971,6 @@ extern struct file_operations reiserfs_file_operations; extern struct address_space_operations reiserfs_address_space_operations; /* fix_nodes.c */ -#ifdef CONFIG_REISERFS_CHECK -void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s); -void reiserfs_kfree(const void *vp, size_t size, struct super_block *s); -#else -static inline void *reiserfs_kmalloc(size_t size, int flags, - struct super_block *s) -{ - return kmalloc(size, flags); -} - -static inline void reiserfs_kfree(const void *vp, size_t size, - struct super_block *s) -{ - kfree(vp); -} -#endif int fix_nodes(int n_op_mode, struct tree_balance *p_s_tb, struct item_head *p_s_ins_ih, const void *); diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 3e68592e52e9..31b4c0bd4fa0 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -382,7 +382,6 @@ struct reiserfs_sb_info { on-disk FS format */ /* session statistics */ - int s_kmallocs; int s_disk_reads; int s_disk_writes; int s_fix_nodes; diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index c84354e8374c..87280eb6083d 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h @@ -43,8 +43,6 @@ int reiserfs_delete_xattrs(struct inode *inode); int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); int reiserfs_xattr_init(struct super_block *sb, int mount_flags); int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd); -int reiserfs_permission_locked(struct inode *inode, int mask, - struct nameidata *nd); int reiserfs_xattr_del(struct inode *, const char *); int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t); diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 9d6fbeef2104..d6b9bcd1384c 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -91,7 +91,8 @@ static inline void page_dup_rmap(struct page *page) * Called from mm/vmscan.c to handle paging out */ int page_referenced(struct page *, int is_locked); -int try_to_unmap(struct page *); +int try_to_unmap(struct page *, int ignore_refs); +void remove_from_swap(struct page *page); /* * Called from mm/filemap_xip.c to unmap empty zero page @@ -111,7 +112,7 @@ unsigned long page_address_in_vma(struct page *, struct vm_area_struct *); #define anon_vma_link(vma) do {} while (0) #define page_referenced(page,l) TestClearPageReferenced(page) -#define try_to_unmap(page) SWAP_FAIL +#define try_to_unmap(page, refs) SWAP_FAIL #endif /* CONFIG_MMU */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 2df1a1a2fee5..9c1da0269a18 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -809,6 +809,7 @@ struct task_struct { struct sighand_struct *sighand; sigset_t blocked, real_blocked; + sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */ struct sigpending pending; unsigned long sas_ss_sp; @@ -1097,7 +1098,7 @@ extern struct sigqueue *sigqueue_alloc(void); extern void sigqueue_free(struct sigqueue *); extern int send_sigqueue(int, struct sigqueue *, struct task_struct *); extern int send_group_sigqueue(int, struct sigqueue *, struct task_struct *); -extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *); +extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long); /* These can be the second arg to send_sig_info/send_group_sig_info. */ diff --git a/include/linux/security.h b/include/linux/security.h index ef753654daa5..7cbef482e13a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1499,15 +1499,11 @@ static inline void security_sb_post_pivotroot (struct nameidata *old_nd, static inline int security_inode_alloc (struct inode *inode) { - if (unlikely (IS_PRIVATE (inode))) - return 0; return security_ops->inode_alloc_security (inode); } static inline void security_inode_free (struct inode *inode) { - if (unlikely (IS_PRIVATE (inode))) - return; security_ops->inode_free_security (inode); } @@ -2617,6 +2613,25 @@ static inline int security_netlink_recv (struct sk_buff *skb) return cap_netlink_recv (skb); } +static inline struct dentry *securityfs_create_dir(const char *name, + struct dentry *parent) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct dentry *securityfs_create_file(const char *name, + mode_t mode, + struct dentry *parent, + void *data, + struct file_operations *fops) +{ + return ERR_PTR(-ENODEV); +} + +static inline void securityfs_remove(struct dentry *dentry) +{ +} + #endif /* CONFIG_SECURITY */ #ifdef CONFIG_SECURITY_NETWORK diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index cee302aefdb7..73b464f0926a 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -26,7 +26,7 @@ struct plat_serial8250_port { unsigned char regshift; /* register shift */ unsigned char iotype; /* UPIO_* */ unsigned char hub6; - unsigned int flags; /* UPF_* flags */ + upf_t flags; /* UPF_* flags */ }; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index ec351005bf9d..4041122dabfc 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -203,6 +203,8 @@ struct uart_icount { __u32 buf_overrun; }; +typedef unsigned int __bitwise__ upf_t; + struct uart_port { spinlock_t lock; /* port lock */ unsigned int iobase; /* in/out[bwl] */ @@ -230,36 +232,34 @@ struct uart_port { unsigned long sysrq; /* sysrq timeout */ #endif - unsigned int flags; - -#define UPF_FOURPORT (1 << 1) -#define UPF_SAK (1 << 2) -#define UPF_SPD_MASK (0x1030) -#define UPF_SPD_HI (0x0010) -#define UPF_SPD_VHI (0x0020) -#define UPF_SPD_CUST (0x0030) -#define UPF_SPD_SHI (0x1000) -#define UPF_SPD_WARP (0x1010) -#define UPF_SKIP_TEST (1 << 6) -#define UPF_AUTO_IRQ (1 << 7) -#define UPF_HARDPPS_CD (1 << 11) -#define UPF_LOW_LATENCY (1 << 13) -#define UPF_BUGGY_UART (1 << 14) -#define UPF_AUTOPROBE (1 << 15) -#define UPF_MAGIC_MULTIPLIER (1 << 16) -#define UPF_BOOT_ONLYMCA (1 << 22) -#define UPF_CONS_FLOW (1 << 23) -#define UPF_SHARE_IRQ (1 << 24) -#define UPF_BOOT_AUTOCONF (1 << 28) -#define UPF_IOREMAP (1 << 31) - -#define UPF_CHANGE_MASK (0x17fff) -#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY) + upf_t flags; + +#define UPF_FOURPORT ((__force upf_t) (1 << 1)) +#define UPF_SAK ((__force upf_t) (1 << 2)) +#define UPF_SPD_MASK ((__force upf_t) (0x1030)) +#define UPF_SPD_HI ((__force upf_t) (0x0010)) +#define UPF_SPD_VHI ((__force upf_t) (0x0020)) +#define UPF_SPD_CUST ((__force upf_t) (0x0030)) +#define UPF_SPD_SHI ((__force upf_t) (0x1000)) +#define UPF_SPD_WARP ((__force upf_t) (0x1010)) +#define UPF_SKIP_TEST ((__force upf_t) (1 << 6)) +#define UPF_AUTO_IRQ ((__force upf_t) (1 << 7)) +#define UPF_HARDPPS_CD ((__force upf_t) (1 << 11)) +#define UPF_LOW_LATENCY ((__force upf_t) (1 << 13)) +#define UPF_BUGGY_UART ((__force upf_t) (1 << 14)) +#define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) +#define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) +#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) +#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) +#define UPF_IOREMAP ((__force upf_t) (1 << 31)) + +#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff)) +#define UPF_USR_MASK ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY)) unsigned int mctrl; /* current modem ctrl settings */ unsigned int timeout; /* character-based timeout */ unsigned int type; /* port type */ - struct uart_ops *ops; + const struct uart_ops *ops; unsigned int custom_divisor; unsigned int line; /* port index */ unsigned long mapbase; /* for ioremap */ @@ -289,6 +289,9 @@ struct uart_state { }; #define UART_XMIT_SIZE PAGE_SIZE + +typedef unsigned int __bitwise__ uif_t; + /* * This is the state information which is only valid when the port * is open; it may be freed by the core driver once the device has @@ -298,17 +301,16 @@ struct uart_state { struct uart_info { struct tty_struct *tty; struct circ_buf xmit; - unsigned int flags; + uif_t flags; /* - * These are the flags that specific to info->flags, and reflect our - * internal state. They can not be accessed via port->flags. Low - * level drivers must not change these, but may query them instead. + * Definitions for info->flags. These are _private_ to serial_core, and + * are specific to this structure. They may be queried by low level drivers. */ -#define UIF_CHECK_CD (1 << 25) -#define UIF_CTS_FLOW (1 << 26) -#define UIF_NORMAL_ACTIVE (1 << 29) -#define UIF_INITIALIZED (1 << 31) +#define UIF_CHECK_CD ((__force uif_t) (1 << 25)) +#define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) +#define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) +#define UIF_INITIALIZED ((__force uif_t) (1 << 31)) int blocked_open; @@ -430,7 +432,7 @@ static inline int uart_handle_break(struct uart_port *port) port->sysrq = 0; } #endif - if (info->flags & UPF_SAK) + if (port->flags & UPF_SAK) do_SAK(info->tty); return 0; } diff --git a/include/linux/slab.h b/include/linux/slab.h index 1fb77a9cc148..8cf52939d0ab 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -76,7 +76,14 @@ struct cache_sizes { kmem_cache_t *cs_dmacachep; }; extern struct cache_sizes malloc_sizes[]; + +#ifndef CONFIG_DEBUG_SLAB extern void *__kmalloc(size_t, gfp_t); +#else +extern void *__kmalloc_track_caller(size_t, gfp_t, void*); +#define __kmalloc(size, flags) \ + __kmalloc_track_caller(size, flags, __builtin_return_address(0)) +#endif static inline void *kmalloc(size_t size, gfp_t flags) { diff --git a/include/linux/smp.h b/include/linux/smp.h index 9dfa3ee769ae..44153fdf73fc 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -17,7 +17,6 @@ extern void cpu_idle(void); #include <linux/compiler.h> #include <linux/thread_info.h> #include <asm/smp.h> -#include <asm/bug.h> /* * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc. diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index b68c11a2d6dd..be4772ed43c0 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -48,7 +48,7 @@ struct rpc_cred { /* per-flavor data */ }; -#define RPCAUTH_CRED_LOCKED 0x0001 +#define RPCAUTH_CRED_NEW 0x0001 #define RPCAUTH_CRED_UPTODATE 0x0002 #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 @@ -83,9 +83,10 @@ struct rpc_auth { struct rpc_cred_cache * au_credcache; /* per-flavor data */ }; -#define RPC_AUTH_PROC_CREDS 0x0010 /* process creds (including - * uid/gid, fs[ug]id, gids) - */ + +/* Flags for rpcauth_lookupcred() */ +#define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ +#define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */ /* * Client authentication ops @@ -105,6 +106,7 @@ struct rpc_authops { struct rpc_credops { const char * cr_name; /* Name of the auth flavour */ + int (*cr_init)(struct rpc_auth *, struct rpc_cred *); void (*crdestroy)(struct rpc_cred *); int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index e4086ec8b952..50cab2a09f28 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -246,6 +246,7 @@ struct svc_deferred_req { u32 prot; /* protocol (UDP or TCP) */ struct sockaddr_in addr; struct svc_sock *svsk; /* where reply must go */ + u32 daddr; /* where reply must come from */ struct cache_deferred_req handle; int argslen; u32 args[0]; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5dc94e777fab..37c1c76fd547 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -43,16 +43,20 @@ extern void mark_free_pages(struct zone *zone); /* kernel/power/swsusp.c */ extern int software_suspend(void); +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) extern int pm_prepare_console(void); extern void pm_restore_console(void); - +#else +static inline int pm_prepare_console(void) { return 0; } +static inline void pm_restore_console(void) {} +#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */ #else static inline int software_suspend(void) { printk("Warning: fake suspend called\n"); return -EPERM; } -#endif +#endif /* CONFIG_PM */ #ifdef CONFIG_SUSPEND_SMP extern void disable_nonboot_cpus(void); diff --git a/include/linux/swap.h b/include/linux/swap.h index e92054d6530b..f3e17d5963c3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -167,6 +167,7 @@ extern void FASTCALL(lru_cache_add_active(struct page *)); extern void FASTCALL(activate_page(struct page *)); extern void FASTCALL(mark_page_accessed(struct page *)); extern void lru_add_drain(void); +extern int lru_add_drain_all(void); extern int rotate_reclaimable_page(struct page *page); extern void swap_setup(void); @@ -175,16 +176,35 @@ extern int try_to_free_pages(struct zone **, gfp_t); extern int shrink_all_memory(int); extern int vm_swappiness; +#ifdef CONFIG_NUMA +extern int zone_reclaim_mode; +extern int zone_reclaim_interval; +extern int zone_reclaim(struct zone *, gfp_t, unsigned int); +#else +#define zone_reclaim_mode 0 +static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order) +{ + return 0; +} +#endif + #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p); extern int putback_lru_pages(struct list_head *l); +extern int migrate_page(struct page *, struct page *); +extern void migrate_page_copy(struct page *, struct page *); +extern int migrate_page_remove_references(struct page *, struct page *, int); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); +extern int fail_migrate_page(struct page *, struct page *); #else static inline int isolate_lru_page(struct page *p) { return -ENOSYS; } static inline int putback_lru_pages(struct list_head *l) { return 0; } static inline int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed) { return -ENOSYS; } +/* Possible settings for the migrate_page() method in address_operations */ +#define migrate_page NULL +#define fail_migrate_page NULL #endif #ifdef CONFIG_MMU @@ -233,6 +253,7 @@ extern int remove_exclusive_swap_page(struct page *); struct backing_dev_info; extern spinlock_t swap_lock; +extern int remove_vma_swap(struct vm_area_struct *vma, struct page *page); /* linux/mm/thrash.c */ extern struct mm_struct * swap_token_mm; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 3eed47347013..d73501ba7e44 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -50,6 +50,8 @@ struct timezone; struct tms; struct utimbuf; struct mq_attr; +struct compat_stat; +struct compat_timeval; #include <linux/config.h> #include <linux/types.h> @@ -510,13 +512,61 @@ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, asmlinkage long sys_ioprio_set(int which, int who, int ioprio); asmlinkage long sys_ioprio_get(int which, int who); asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, - unsigned long maxnode); + unsigned long maxnode); asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, - const unsigned long __user *from, const unsigned long __user *to); + const unsigned long __user *from, + const unsigned long __user *to); +asmlinkage long sys_mbind(unsigned long start, unsigned long len, + unsigned long mode, + unsigned long __user *nmask, + unsigned long maxnode, + unsigned flags); +asmlinkage long sys_get_mempolicy(int __user *policy, + unsigned long __user *nmask, + unsigned long maxnode, + unsigned long addr, unsigned long flags); + +asmlinkage long sys_inotify_init(void); +asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, + u32 mask); +asmlinkage long sys_inotify_rm_watch(int fd, u32 wd); asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus); asmlinkage long sys_spu_create(const char __user *name, unsigned int flags, mode_t mode); +asmlinkage long sys_mknodat(int dfd, const char __user * filename, int mode, + unsigned dev); +asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, int mode); +asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag); +asmlinkage long sys_symlinkat(const char __user * oldname, + int newdfd, const char __user * newname); +asmlinkage long sys_linkat(int olddfd, const char __user *oldname, + int newdfd, const char __user *newname); +asmlinkage long sys_renameat(int olddfd, const char __user * oldname, + int newdfd, const char __user * newname); +asmlinkage long sys_futimesat(int dfd, char __user *filename, + struct timeval __user *utimes); +asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode); +asmlinkage long sys_fchmodat(int dfd, const char __user * filename, + mode_t mode); +asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, + gid_t group, int flag); +asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, + int mode); +asmlinkage long sys_newfstatat(int dfd, char __user *filename, + struct stat __user *statbuf, int flag); +asmlinkage long sys_fstatat64(int dfd, char __user *filename, + struct stat64 __user *statbuf, int flag); +asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, + int bufsiz); +asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, + struct compat_timeval __user *t); +asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename, + struct compat_stat __user *statbuf, + int flag); +asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, + int flags, int mode); + #endif diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 7f472127b7b5..32a4139c4ad8 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -182,6 +182,8 @@ enum VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */ VM_DROP_PAGECACHE=29, /* int: nuke lots of pagecache */ VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */ + VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */ + VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */ }; diff --git a/include/linux/time.h b/include/linux/time.h index f2aca7ec6325..d9cdba54b789 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -33,11 +33,34 @@ struct timezone { #define NSEC_PER_SEC 1000000000L #define NSEC_PER_USEC 1000L -static __inline__ int timespec_equal(struct timespec *a, struct timespec *b) +static inline int timespec_equal(struct timespec *a, struct timespec *b) { return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec); } +/* + * lhs < rhs: return <0 + * lhs == rhs: return 0 + * lhs > rhs: return >0 + */ +static inline int timespec_compare(struct timespec *lhs, struct timespec *rhs) +{ + if (lhs->tv_sec < rhs->tv_sec) + return -1; + if (lhs->tv_sec > rhs->tv_sec) + return 1; + return lhs->tv_nsec - rhs->tv_nsec; +} + +static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs) +{ + if (lhs->tv_sec < rhs->tv_sec) + return -1; + if (lhs->tv_sec > rhs->tv_sec) + return 1; + return lhs->tv_usec - rhs->tv_usec; +} + extern unsigned long mktime(const unsigned int year, const unsigned int mon, const unsigned int day, const unsigned int hour, const unsigned int min, const unsigned int sec); @@ -48,7 +71,7 @@ extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec); * Returns true if the timespec is norm, false if denorm: */ #define timespec_valid(ts) \ - (((ts)->tv_sec >= 0) && (((unsigned) (ts)->tv_nsec) < NSEC_PER_SEC)) + (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC)) /* * 64-bit nanosec type. Large enough to span 292+ years in nanosecond @@ -74,7 +97,7 @@ extern void do_gettimeofday(struct timeval *tv); extern int do_settimeofday(struct timespec *tv); extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz); #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) -extern long do_utimes(char __user *filename, struct timeval *times); +extern long do_utimes(int dfd, char __user *filename, struct timeval *times); struct itimerval; extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue); diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h index a52c8c64a5a3..33a653913d94 100644 --- a/include/linux/tipc_config.h +++ b/include/linux/tipc_config.h @@ -168,10 +168,13 @@ #define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ /* - * Link priority limits (range from 0 to # priorities - 1) + * Link priority limits (min, default, max, media default) */ -#define TIPC_NUM_LINK_PRI 32 +#define TIPC_MIN_LINK_PRI 0 +#define TIPC_DEF_LINK_PRI 10 +#define TIPC_MAX_LINK_PRI 31 +#define TIPC_MEDIA_LINK_PRI (TIPC_MAX_LINK_PRI + 1) /* * Link tolerance limits (min, default, max), in ms diff --git a/include/linux/topology.h b/include/linux/topology.h index 315a5163d6a0..e8eb0040ce3a 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -56,6 +56,14 @@ #define REMOTE_DISTANCE 20 #define node_distance(from,to) ((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE) #endif +#ifndef RECLAIM_DISTANCE +/* + * If the distance between nodes in a system is larger than RECLAIM_DISTANCE + * (in whatever arch specific measurement units returned by node_distance()) + * then switch on zone reclaim on boot. + */ +#define RECLAIM_DISTANCE 20 +#endif #ifndef PENALTY_FOR_NODE_WITH_CPUS #define PENALTY_FOR_NODE_WITH_CPUS (1) #endif diff --git a/include/linux/tty.h b/include/linux/tty.h index 3787102e4b12..f45cd74e6f24 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -57,6 +57,9 @@ struct tty_buffer { unsigned char *flag_buf_ptr; int used; int size; + int active; + int commit; + int read; /* Data points here */ unsigned long data[0]; }; @@ -64,6 +67,7 @@ struct tty_buffer { struct tty_bufhead { struct work_struct work; struct semaphore pty_sem; + spinlock_t lock; struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ struct tty_buffer *free; /* Free queue head */ diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index be1400e82482..222faf97d5f9 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -17,7 +17,7 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag) { struct tty_buffer *tb = tty->buf.tail; - if (tb && tb->used < tb->size) { + if (tb && tb->active && tb->used < tb->size) { tb->flag_buf_ptr[tb->used] = flag; tb->char_buf_ptr[tb->used++] = ch; return 1; @@ -27,6 +27,13 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty, _INLINE_ void tty_schedule_flip(struct tty_struct *tty) { + unsigned long flags; + spin_lock_irqsave(&tty->buf.lock, flags); + if (tty->buf.tail != NULL) { + tty->buf.tail->active = 0; + tty->buf.tail->commit = tty->buf.tail->used; + } + spin_unlock_irqrestore(&tty->buf.lock, flags); schedule_delayed_work(&tty->buf.work, 1); } diff --git a/include/linux/types.h b/include/linux/types.h index 21b9ce803644..54ae2d59e71b 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -8,6 +8,8 @@ (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] + +#define BITS_PER_BYTE 8 #endif #include <linux/posix_types.h> diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index 7a6babeca256..b0ffe4356e5a 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -148,11 +148,11 @@ typedef __u16 __bitwise __fs16; #define UFS_USEEFT ((__u16)65535) #define UFS_FSOK 0x7c269d38 -#define UFS_FSACTIVE ((char)0x00) -#define UFS_FSCLEAN ((char)0x01) -#define UFS_FSSTABLE ((char)0x02) -#define UFS_FSOSF1 ((char)0x03) /* is this correct for DEC OSF/1? */ -#define UFS_FSBAD ((char)0xff) +#define UFS_FSACTIVE ((__s8)0x00) +#define UFS_FSCLEAN ((__s8)0x01) +#define UFS_FSSTABLE ((__s8)0x02) +#define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ +#define UFS_FSBAD ((__s8)0xff) /* From here to next blank line, s_flags for ufs_sb_info */ /* directory entry encoding */ @@ -502,8 +502,7 @@ struct ufs_super_block { /* * Convert cylinder group to base address of its global summary info. */ -#define fs_cs(indx) \ - s_csp[(indx) >> uspi->s_csshift][(indx) & ~uspi->s_csmask] +#define fs_cs(indx) s_csp[(indx)] /* * Cylinder group block for a file system. @@ -913,6 +912,7 @@ extern int ufs_sync_inode (struct inode *); extern void ufs_delete_inode (struct inode *); extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *); extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); +extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); /* namei.c */ extern struct file_operations ufs_dir_operations; diff --git a/include/linux/ufs_fs_sb.h b/include/linux/ufs_fs_sb.h index c1be4c226486..8ff13c160f3d 100644 --- a/include/linux/ufs_fs_sb.h +++ b/include/linux/ufs_fs_sb.h @@ -25,7 +25,7 @@ struct ufs_csum; struct ufs_sb_info { struct ufs_sb_private_info * s_uspi; - struct ufs_csum * s_csp[UFS_MAXCSBUFS]; + struct ufs_csum * s_csp; unsigned s_bytesex; unsigned s_flags; struct buffer_head ** s_ucg; diff --git a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h index ee21e6bf3867..a2aacfc7af2f 100644 --- a/include/linux/usb_ch9.h +++ b/include/linux/usb_ch9.h @@ -535,9 +535,11 @@ enum usb_device_state { */ USB_STATE_NOTATTACHED = 0, - /* the chapter 9 device states */ + /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, - USB_STATE_POWERED, + USB_STATE_POWERED, /* wired */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_RECONNECTING, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ce40675324bd..5208b12d5550 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -315,6 +315,7 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */ #define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */ #define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */ /* * F O R M A T E N U M E R A T I O N @@ -548,7 +549,7 @@ struct v4l2_framebuffer struct v4l2_clip { struct v4l2_rect c; - struct v4l2_clip *next; + struct v4l2_clip __user *next; }; struct v4l2_window @@ -628,6 +629,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -660,7 +662,8 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_H |\ V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ - V4L2_STD_NTSC_M_JP) + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ V4L2_STD_SECAM_K |\ V4L2_STD_SECAM_K1) diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index bbfac86734ec..89d743cfdfdf 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -33,7 +33,7 @@ #define RFCOMM_DEFAULT_MTU 127 #define RFCOMM_DEFAULT_CREDITS 7 -#define RFCOMM_MAX_L2CAP_MTU 1024 +#define RFCOMM_MAX_L2CAP_MTU 1013 #define RFCOMM_MAX_CREDITS 40 #define RFCOMM_SKB_HEAD_RESERVE 8 diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index df05f468fa5c..9a92aef8b0b2 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -803,9 +803,9 @@ enum ieee80211_state { #define IEEE80211_24GHZ_MAX_CHANNEL 14 #define IEEE80211_24GHZ_CHANNELS 14 -#define IEEE80211_52GHZ_MIN_CHANNEL 36 +#define IEEE80211_52GHZ_MIN_CHANNEL 34 #define IEEE80211_52GHZ_MAX_CHANNEL 165 -#define IEEE80211_52GHZ_CHANNELS 32 +#define IEEE80211_52GHZ_CHANNELS 131 enum { IEEE80211_CH_PASSIVE_ONLY = (1 << 0), diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index 05a840837fe7..1880e46ecc9b 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -82,9 +82,9 @@ do { if(!(expr)) { \ #define IRDA_ASSERT_LABEL(label) #endif /* CONFIG_IRDA_DEBUG */ -#define IRDA_WARNING(args...) printk(KERN_WARNING args) -#define IRDA_MESSAGE(args...) printk(KERN_INFO args) -#define IRDA_ERROR(args...) printk(KERN_ERR args) +#define IRDA_WARNING(args...) do { if (net_ratelimit()) printk(KERN_WARNING args); } while (0) +#define IRDA_MESSAGE(args...) do { if (net_ratelimit()) printk(KERN_INFO args); } while (0) +#define IRDA_ERROR(args...) do { if (net_ratelimit()) printk(KERN_ERR args); } while (0) /* * Magic numbers used by Linux-IrDA. Random numbers which must be unique to diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index f55e86e75030..2127cae1e0a6 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -50,6 +50,9 @@ /* May be different when we get VFIR */ #define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) +/* Each IrDA device gets a random 32 bits IRLAP device address */ +#define LAP_ALEN 4 + #define BROADCAST 0xffffffff /* Broadcast device address */ #define CBROADCAST 0xfe /* Connection broadcast address */ #define XID_FORMAT 0x01 /* Discovery XID format */ diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 67856eb93b43..dac43b15a5b0 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -88,12 +88,6 @@ extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); -static inline struct nf_conntrack_l3proto * -__nf_ct_l3proto_find(u_int16_t l3proto) -{ - return nf_ct_l3protos[l3proto]; -} - extern struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto); @@ -103,4 +97,13 @@ extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto; + +static inline struct nf_conntrack_l3proto * +__nf_ct_l3proto_find(u_int16_t l3proto) +{ + if (unlikely(l3proto >= AF_MAX)) + return &nf_conntrack_generic_l3proto; + return nf_ct_l3protos[l3proto]; +} + #endif /*_NF_CONNTRACK_L3PROTO_H*/ diff --git a/include/net/route.h b/include/net/route.h index e3e5436f8017..9c04f15090d2 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -170,8 +170,8 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, return ip_route_output_flow(rp, &fl, sk, 0); } -static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, - struct sock *sk) +static inline int ip_route_newports(struct rtable **rp, u8 protocol, + u16 sport, u16 dport, struct sock *sk) { if (sport != (*rp)->fl.fl_ip_sport || dport != (*rp)->fl.fl_ip_dport) { @@ -180,6 +180,7 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, memcpy(&fl, &(*rp)->fl, sizeof(fl)); fl.fl_ip_sport = sport; fl.fl_ip_dport = dport; + fl.proto = protocol; ip_rt_put(*rp); *rp = NULL; return ip_route_output_flow(rp, &fl, sk, 0); diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index a553f39f6aee..e673b2c984e9 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -175,6 +175,8 @@ void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, void sctp_icmp_proto_unreachable(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t); +void sctp_backlog_migrate(struct sctp_association *assoc, + struct sock *oldsk, struct sock *newsk); /* * Section: Macros, externs, and inlines diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f5c22d77feab..072f407848a6 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -127,9 +127,9 @@ extern struct sctp_globals { * RTO.Alpha - 1/8 (3 when converted to right shifts.) * RTO.Beta - 1/4 (2 when converted to right shifts.) */ - __u32 rto_initial; - __u32 rto_min; - __u32 rto_max; + unsigned long rto_initial; + unsigned long rto_min; + unsigned long rto_max; /* Note: rto_alpha and rto_beta are really defined as inverse * powers of two to facilitate integer operations. @@ -140,12 +140,18 @@ extern struct sctp_globals { /* Max.Burst - 4 */ int max_burst; - /* Valid.Cookie.Life - 60 seconds */ - int valid_cookie_life; - /* Whether Cookie Preservative is enabled(1) or not(0) */ int cookie_preserve_enable; + /* Valid.Cookie.Life - 60 seconds */ + unsigned long valid_cookie_life; + + /* Delayed SACK timeout 200ms default*/ + unsigned long sack_timeout; + + /* HB.interval - 30 seconds */ + unsigned long hb_interval; + /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) * Max.Init.Retransmits - 8 attempts @@ -168,12 +174,6 @@ extern struct sctp_globals { */ int rcvbuf_policy; - /* Delayed SACK timeout 200ms default*/ - int sack_timeout; - - /* HB.interval - 30 seconds */ - int hb_interval; - /* The following variables are implementation specific. */ /* Default initialization values to be applied to new associations. */ @@ -405,8 +405,9 @@ struct sctp_cookie { /* The format of our cookie that we send to our peer. */ struct sctp_signed_cookie { __u8 signature[SCTP_SECRET_SIZE]; + __u32 __pad; /* force sctp_cookie alignment to 64 bits */ struct sctp_cookie c; -}; +} __attribute__((packed)); /* This is another convenience type to allocate memory for address * params for the maximum size and pass such structures around @@ -699,7 +700,7 @@ struct sctp_chunk { __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ __u8 pdiscard; /* Discard the whole packet now? */ __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ - __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ + __s8 fast_retransmit; /* Is this chunk fast retransmitted? */ __u8 tsn_missing_report; /* Data chunk missing counter. */ }; @@ -827,7 +828,7 @@ struct sctp_transport { __u32 rtt; /* This is the most recent RTT. */ /* RTO : The current retransmission timeout value. */ - __u32 rto; + unsigned long rto; /* RTTVAR : The current RTT variation. */ __u32 rttvar; @@ -877,22 +878,10 @@ struct sctp_transport { /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to * the destination address every heartbeat interval. */ - __u32 hbinterval; - - /* This is the max_retrans value for the transport and will - * be initialized from the assocs value. This can be changed - * using SCTP_SET_PEER_ADDR_PARAMS socket option. - */ - __u16 pathmaxrxt; - - /* PMTU : The current known path MTU. */ - __u32 pathmtu; + unsigned long hbinterval; /* SACK delay timeout */ - __u32 sackdelay; - - /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */ - __u32 param_flags; + unsigned long sackdelay; /* When was the last time (in jiffies) that we heard from this * transport? We use this to pick new active and retran paths. @@ -904,6 +893,18 @@ struct sctp_transport { */ unsigned long last_time_ecne_reduced; + /* This is the max_retrans value for the transport and will + * be initialized from the assocs value. This can be changed + * using SCTP_SET_PEER_ADDR_PARAMS socket option. + */ + __u16 pathmaxrxt; + + /* PMTU : The current known path MTU. */ + __u32 pathmtu; + + /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */ + __u32 param_flags; + /* The number of times INIT has been sent on this transport. */ int init_sent_count; @@ -1249,6 +1250,14 @@ struct sctp_endpoint { int last_key; int key_changed_at; + /* digest: This is a digest of the sctp cookie. This field is + * only used on the receive path when we try to validate + * that the cookie has not been tampered with. We put + * this here so we pre-allocate this once and can re-use + * on every receive. + */ + __u8 digest[SCTP_SIGNATURE_SIZE]; + /* sendbuf acct. policy. */ __u32 sndbuf_policy; @@ -1499,9 +1508,9 @@ struct sctp_association { * These values will be initialized by system defaults, but can * be modified via the SCTP_RTOINFO socket option. */ - __u32 rto_initial; - __u32 rto_max; - __u32 rto_min; + unsigned long rto_initial; + unsigned long rto_max; + unsigned long rto_min; /* Maximum number of new data packets that can be sent in a burst. */ int max_burst; @@ -1519,13 +1528,13 @@ struct sctp_association { __u16 init_retries; /* The largest timeout or RTO value to use in attempting an INIT */ - __u16 max_init_timeo; + unsigned long max_init_timeo; /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to * the destination address every heartbeat interval. This value * will be inherited by all new transports. */ - __u32 hbinterval; + unsigned long hbinterval; /* This is the max_retrans value for new transports in the * association. @@ -1537,13 +1546,14 @@ struct sctp_association { */ __u32 pathmtu; - /* SACK delay timeout */ - __u32 sackdelay; - /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */ __u32 param_flags; - int timeouts[SCTP_NUM_TIMEOUT_TYPES]; + /* SACK delay timeout */ + unsigned long sackdelay; + + + unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES]; struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES]; /* Transport to which SHUTDOWN chunk was last sent. */ @@ -1648,7 +1658,10 @@ struct sctp_association { /* How many duplicated TSNs have we seen? */ int numduptsns; - /* Number of seconds of idle time before an association is closed. */ + /* Number of seconds of idle time before an association is closed. + * In the association context, this is really used as a boolean + * since the real timeout is stored in the timeouts array + */ __u32 autoclose; /* These are to support diff --git a/include/net/sock.h b/include/net/sock.h index 1806e5b61419..30758035d616 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1354,12 +1354,12 @@ extern int sock_get_timestamp(struct sock *, struct timeval __user *); * Enable debug/info messages */ -#if 0 -#define NETDEBUG(fmt, args...) do { } while (0) -#define LIMIT_NETDEBUG(fmt, args...) do { } while(0) -#else +#ifdef CONFIG_NETDEBUG #define NETDEBUG(fmt, args...) printk(fmt,##args) #define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0) +#else +#define NETDEBUG(fmt, args...) do { } while (0) +#define LIMIT_NETDEBUG(fmt, args...) do { } while(0) #endif /* diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index e94ca4d36035..290e3b4d2aec 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -275,7 +275,7 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *, int timeout, int retries); extern int scsi_execute_async(struct scsi_device *sdev, - const unsigned char *cmd, int data_direction, + const unsigned char *cmd, int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, int timeout, int retries, void *privdata, void (*done)(void *, char *, int, int), diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 467274a764d1..827992949c4b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -554,7 +554,6 @@ struct Scsi_Host { /* * ordered write support */ - unsigned ordered_flush:1; unsigned ordered_tag:1; /* diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index 2b5930ba69ec..fb5a2ffae939 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -22,6 +22,7 @@ #include <linux/config.h> #include <linux/transport_class.h> +#include <linux/mutex.h> struct scsi_transport_template; struct scsi_target; diff --git a/init/Kconfig b/init/Kconfig index b9923b1434a2..38416a199def 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -31,19 +31,8 @@ config EXPERIMENTAL you say Y here, you will be offered the choice of using features or drivers that are currently considered to be in the alpha-test phase. -config CLEAN_COMPILE - bool "Select only drivers expected to compile cleanly" if EXPERIMENTAL - default y - help - Select this option if you don't even want to see the option - to configure known-broken drivers. - - If unsure, say Y - config BROKEN bool - depends on !CLEAN_COMPILE - default y config BROKEN_ON_SMP bool @@ -180,7 +169,6 @@ config SYSCTL config AUDIT bool "Auditing support" depends on NET - default y if SECURITY_SELINUX help Enable auditing infrastructure that can be used with another kernel subsystem, such as SELinux (which requires this for diff --git a/init/initramfs.c b/init/initramfs.c index 0c5d9a3f951b..637344b05981 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -466,10 +466,32 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) extern char __initramfs_start[], __initramfs_end[]; #ifdef CONFIG_BLK_DEV_INITRD #include <linux/initrd.h> +#include <linux/kexec.h> static void __init free_initrd(void) { - free_initrd_mem(initrd_start, initrd_end); +#ifdef CONFIG_KEXEC + unsigned long crashk_start = (unsigned long)__va(crashk_res.start); + unsigned long crashk_end = (unsigned long)__va(crashk_res.end); + + /* + * If the initrd region is overlapped with crashkernel reserved region, + * free only memory that is not part of crashkernel region. + */ + if (initrd_start < crashk_end && initrd_end > crashk_start) { + /* + * Initialize initrd memory region since the kexec boot does + * not do. + */ + memset((void *)initrd_start, 0, initrd_end - initrd_start); + if (initrd_start < crashk_start) + free_initrd_mem(initrd_start, crashk_start); + if (initrd_end > crashk_end) + free_initrd_mem(crashk_end, initrd_end); + } else +#endif + free_initrd_mem(initrd_start, initrd_end); + initrd_start = 0; initrd_end = 0; } diff --git a/init/main.c b/init/main.c index 7c79da57d3a2..4c194c47395f 100644 --- a/init/main.c +++ b/init/main.c @@ -668,7 +668,6 @@ static int init(void * unused) */ child_reaper = current; - /* Sets up cpus_possible() */ smp_prepare_cpus(max_cpus); do_pre_smp_initcalls(); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 59302fc3643b..fd2e26b6f966 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1018,7 +1018,8 @@ retry: goto out; } - ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT); + ret = netlink_attachskb(sock, nc, 0, + MAX_SCHEDULE_TIMEOUT, NULL); if (ret == 1) goto retry; if (ret) { diff --git a/ipc/shm.c b/ipc/shm.c index 4c28d2d8e305..9162123a7b23 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -870,6 +870,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr) * could possibly have landed at. Also cast things to loff_t to * prevent overflows and make comparisions vs. equal-width types. */ + size = PAGE_ALIGN(size); while (vma && (loff_t)(vma->vm_end - addr) <= size) { next = vma->vm_next; diff --git a/kernel/audit.c b/kernel/audit.c index d13ab7d2d899..0a813d2883e5 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -42,8 +42,8 @@ */ #include <linux/init.h> -#include <asm/atomic.h> #include <asm/types.h> +#include <asm/atomic.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/err.h> diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d8a68509e729..685c25175d96 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -30,8 +30,8 @@ */ #include <linux/init.h> -#include <asm/atomic.h> #include <asm/types.h> +#include <asm/atomic.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/mount.h> diff --git a/kernel/compat.c b/kernel/compat.c index 256e5d9f0647..8c9cd88b6785 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -23,7 +23,6 @@ #include <linux/security.h> #include <asm/uaccess.h> -#include <asm/bug.h> int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) { @@ -871,3 +870,31 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr) } #endif /* __ARCH_WANT_COMPAT_SYS_TIME */ + +#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND +asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize) +{ + sigset_t newset; + compat_sigset_t newset32; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) + return -EFAULT; + sigset_from_compat(&newset, &newset32); + sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); + + spin_lock_irq(¤t->sighand->siglock); + current->saved_sigmask = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; +} +#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ diff --git a/kernel/cpuset.c b/kernel/cpuset.c index fe2f71f92ae0..ba42b0a76961 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -641,7 +641,7 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask) * task has been modifying its cpuset. */ -void cpuset_update_task_memory_state() +void cpuset_update_task_memory_state(void) { int my_cpusets_mem_gen; struct task_struct *tsk = current; diff --git a/kernel/fork.c b/kernel/fork.c index 4ae8cfc1c89c..8e88b374cee9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -446,6 +446,55 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) } } +/* + * Allocate a new mm structure and copy contents from the + * mm structure of the passed in task structure. + */ +static struct mm_struct *dup_mm(struct task_struct *tsk) +{ + struct mm_struct *mm, *oldmm = current->mm; + int err; + + if (!oldmm) + return NULL; + + mm = allocate_mm(); + if (!mm) + goto fail_nomem; + + memcpy(mm, oldmm, sizeof(*mm)); + + if (!mm_init(mm)) + goto fail_nomem; + + if (init_new_context(tsk, mm)) + goto fail_nocontext; + + err = dup_mmap(mm, oldmm); + if (err) + goto free_pt; + + mm->hiwater_rss = get_mm_rss(mm); + mm->hiwater_vm = mm->total_vm; + + return mm; + +free_pt: + mmput(mm); + +fail_nomem: + return NULL; + +fail_nocontext: + /* + * If init_new_context() failed, we cannot use mmput() to free the mm + * because it calls destroy_context() + */ + mm_free_pgd(mm); + free_mm(mm); + return NULL; +} + static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) { struct mm_struct * mm, *oldmm; @@ -473,43 +522,17 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) } retval = -ENOMEM; - mm = allocate_mm(); + mm = dup_mm(tsk); if (!mm) goto fail_nomem; - /* Copy the current MM stuff.. */ - memcpy(mm, oldmm, sizeof(*mm)); - if (!mm_init(mm)) - goto fail_nomem; - - if (init_new_context(tsk,mm)) - goto fail_nocontext; - - retval = dup_mmap(mm, oldmm); - if (retval) - goto free_pt; - - mm->hiwater_rss = get_mm_rss(mm); - mm->hiwater_vm = mm->total_vm; - good_mm: tsk->mm = mm; tsk->active_mm = mm; return 0; -free_pt: - mmput(mm); fail_nomem: return retval; - -fail_nocontext: - /* - * If init_new_context() failed, we cannot use mmput() to free the mm - * because it calls destroy_context() - */ - mm_free_pgd(mm); - free_mm(mm); - return retval; } static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old) @@ -597,32 +620,17 @@ out: return newf; } -static int copy_files(unsigned long clone_flags, struct task_struct * tsk) +/* + * Allocate a new files structure and copy contents from the + * passed in files structure. + */ +static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) { - struct files_struct *oldf, *newf; + struct files_struct *newf; struct file **old_fds, **new_fds; - int open_files, size, i, error = 0, expand; + int open_files, size, i, expand; struct fdtable *old_fdt, *new_fdt; - /* - * A background process may not have any files ... - */ - oldf = current->files; - if (!oldf) - goto out; - - if (clone_flags & CLONE_FILES) { - atomic_inc(&oldf->count); - goto out; - } - - /* - * Note: we may be using current for both targets (See exec.c) - * This works because we cache current->files (old) as oldf. Don't - * break this. - */ - tsk->files = NULL; - error = -ENOMEM; newf = alloc_files(); if (!newf) goto out; @@ -651,9 +659,9 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) if (expand) { spin_unlock(&oldf->file_lock); spin_lock(&newf->file_lock); - error = expand_files(newf, open_files-1); + *errorp = expand_files(newf, open_files-1); spin_unlock(&newf->file_lock); - if (error < 0) + if (*errorp < 0) goto out_release; new_fdt = files_fdtable(newf); /* @@ -702,10 +710,8 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) memset(&new_fdt->close_on_exec->fds_bits[start], 0, left); } - tsk->files = newf; - error = 0; out: - return error; + return newf; out_release: free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset); @@ -715,6 +721,40 @@ out_release: goto out; } +static int copy_files(unsigned long clone_flags, struct task_struct * tsk) +{ + struct files_struct *oldf, *newf; + int error = 0; + + /* + * A background process may not have any files ... + */ + oldf = current->files; + if (!oldf) + goto out; + + if (clone_flags & CLONE_FILES) { + atomic_inc(&oldf->count); + goto out; + } + + /* + * Note: we may be using current for both targets (See exec.c) + * This works because we cache current->files (old) as oldf. Don't + * break this. + */ + tsk->files = NULL; + error = -ENOMEM; + newf = dup_fd(oldf, &error); + if (!newf) + goto out; + + tsk->files = newf; + error = 0; +out: + return error; +} + /* * Helper to unshare the files of the current task. * We don't want to expose copy_files internals to @@ -802,7 +842,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts init_sigpending(&sig->shared_pending); INIT_LIST_HEAD(&sig->posix_timers); - hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC); + hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL); sig->it_real_incr.tv64 = 0; sig->real_timer.function = it_real_fn; sig->real_timer.data = tsk; @@ -1323,3 +1363,249 @@ void __init proc_caches_init(void) sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); } + + +/* + * Check constraints on flags passed to the unshare system call and + * force unsharing of additional process context as appropriate. + */ +static inline void check_unshare_flags(unsigned long *flags_ptr) +{ + /* + * If unsharing a thread from a thread group, must also + * unshare vm. + */ + if (*flags_ptr & CLONE_THREAD) + *flags_ptr |= CLONE_VM; + + /* + * If unsharing vm, must also unshare signal handlers. + */ + if (*flags_ptr & CLONE_VM) + *flags_ptr |= CLONE_SIGHAND; + + /* + * If unsharing signal handlers and the task was created + * using CLONE_THREAD, then must unshare the thread + */ + if ((*flags_ptr & CLONE_SIGHAND) && + (atomic_read(¤t->signal->count) > 1)) + *flags_ptr |= CLONE_THREAD; + + /* + * If unsharing namespace, must also unshare filesystem information. + */ + if (*flags_ptr & CLONE_NEWNS) + *flags_ptr |= CLONE_FS; +} + +/* + * Unsharing of tasks created with CLONE_THREAD is not supported yet + */ +static int unshare_thread(unsigned long unshare_flags) +{ + if (unshare_flags & CLONE_THREAD) + return -EINVAL; + + return 0; +} + +/* + * Unshare the filesystem structure if it is being shared + */ +static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) +{ + struct fs_struct *fs = current->fs; + + if ((unshare_flags & CLONE_FS) && + (fs && atomic_read(&fs->count) > 1)) { + *new_fsp = __copy_fs_struct(current->fs); + if (!*new_fsp) + return -ENOMEM; + } + + return 0; +} + +/* + * Unshare the namespace structure if it is being shared + */ +static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs) +{ + struct namespace *ns = current->namespace; + + if ((unshare_flags & CLONE_NEWNS) && + (ns && atomic_read(&ns->count) > 1)) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + *new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs); + if (!*new_nsp) + return -ENOMEM; + } + + return 0; +} + +/* + * Unsharing of sighand for tasks created with CLONE_SIGHAND is not + * supported yet + */ +static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp) +{ + struct sighand_struct *sigh = current->sighand; + + if ((unshare_flags & CLONE_SIGHAND) && + (sigh && atomic_read(&sigh->count) > 1)) + return -EINVAL; + else + return 0; +} + +/* + * Unshare vm if it is being shared + */ +static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp) +{ + struct mm_struct *mm = current->mm; + + if ((unshare_flags & CLONE_VM) && + (mm && atomic_read(&mm->mm_users) > 1)) { + *new_mmp = dup_mm(current); + if (!*new_mmp) + return -ENOMEM; + } + + return 0; +} + +/* + * Unshare file descriptor table if it is being shared + */ +static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp) +{ + struct files_struct *fd = current->files; + int error = 0; + + if ((unshare_flags & CLONE_FILES) && + (fd && atomic_read(&fd->count) > 1)) { + *new_fdp = dup_fd(fd, &error); + if (!*new_fdp) + return error; + } + + return 0; +} + +/* + * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not + * supported yet + */ +static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp) +{ + if (unshare_flags & CLONE_SYSVSEM) + return -EINVAL; + + return 0; +} + +/* + * unshare allows a process to 'unshare' part of the process + * context which was originally shared using clone. copy_* + * functions used by do_fork() cannot be used here directly + * because they modify an inactive task_struct that is being + * constructed. Here we are modifying the current, active, + * task_struct. + */ +asmlinkage long sys_unshare(unsigned long unshare_flags) +{ + int err = 0; + struct fs_struct *fs, *new_fs = NULL; + struct namespace *ns, *new_ns = NULL; + struct sighand_struct *sigh, *new_sigh = NULL; + struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; + struct files_struct *fd, *new_fd = NULL; + struct sem_undo_list *new_ulist = NULL; + + check_unshare_flags(&unshare_flags); + + if ((err = unshare_thread(unshare_flags))) + goto bad_unshare_out; + if ((err = unshare_fs(unshare_flags, &new_fs))) + goto bad_unshare_cleanup_thread; + if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs))) + goto bad_unshare_cleanup_fs; + if ((err = unshare_sighand(unshare_flags, &new_sigh))) + goto bad_unshare_cleanup_ns; + if ((err = unshare_vm(unshare_flags, &new_mm))) + goto bad_unshare_cleanup_sigh; + if ((err = unshare_fd(unshare_flags, &new_fd))) + goto bad_unshare_cleanup_vm; + if ((err = unshare_semundo(unshare_flags, &new_ulist))) + goto bad_unshare_cleanup_fd; + + if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist) { + + task_lock(current); + + if (new_fs) { + fs = current->fs; + current->fs = new_fs; + new_fs = fs; + } + + if (new_ns) { + ns = current->namespace; + current->namespace = new_ns; + new_ns = ns; + } + + if (new_sigh) { + sigh = current->sighand; + current->sighand = new_sigh; + new_sigh = sigh; + } + + if (new_mm) { + mm = current->mm; + active_mm = current->active_mm; + current->mm = new_mm; + current->active_mm = new_mm; + activate_mm(active_mm, new_mm); + new_mm = mm; + } + + if (new_fd) { + fd = current->files; + current->files = new_fd; + new_fd = fd; + } + + task_unlock(current); + } + +bad_unshare_cleanup_fd: + if (new_fd) + put_files_struct(new_fd); + +bad_unshare_cleanup_vm: + if (new_mm) + mmput(new_mm); + +bad_unshare_cleanup_sigh: + if (new_sigh) + if (atomic_dec_and_test(&new_sigh->count)) + kmem_cache_free(sighand_cachep, new_sigh); + +bad_unshare_cleanup_ns: + if (new_ns) + put_namespace(new_ns); + +bad_unshare_cleanup_fs: + if (new_fs) + put_fs_struct(new_fs); + +bad_unshare_cleanup_thread: +bad_unshare_out: + return err; +} diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f1c4155b49ac..2b6e1757aedd 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -21,6 +21,12 @@ * Credits: * based on kernel/timer.c * + * Help, testing, suggestions, bugfixes, improvements were + * provided by: + * + * George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel + * et. al. + * * For licencing details see kernel-base/COPYING */ @@ -66,6 +72,12 @@ EXPORT_SYMBOL_GPL(ktime_get_real); /* * The timer bases: + * + * Note: If we want to add new timer bases, we have to skip the two + * clock ids captured by the cpu-timers. We do this by holding empty + * entries rather than doing math adjustment of the clock ids. + * This ensures that we capture erroneous accesses to these clock ids + * rather than moving them into the range of valid clock id's. */ #define MAX_HRTIMER_BASES 2 @@ -483,29 +495,25 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer) } /** - * hrtimer_rebase - rebase an initialized hrtimer to a different base + * hrtimer_init - initialize a timer to the given clock * - * @timer: the timer to be rebased + * @timer: the timer to be initialized * @clock_id: the clock to be used + * @mode: timer mode abs/rel */ -void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id) +void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, + enum hrtimer_mode mode) { struct hrtimer_base *bases; + memset(timer, 0, sizeof(struct hrtimer)); + bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); - timer->base = &bases[clock_id]; -} -/** - * hrtimer_init - initialize a timer to the given clock - * - * @timer: the timer to be initialized - * @clock_id: the clock to be used - */ -void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id) -{ - memset(timer, 0, sizeof(struct hrtimer)); - hrtimer_rebase(timer, clock_id); + if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS) + clock_id = CLOCK_MONOTONIC; + + timer->base = &bases[clock_id]; } /** @@ -550,6 +558,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) fn = timer->function; data = timer->data; set_curr_timer(base, timer); + timer->state = HRTIMER_RUNNING; __remove_hrtimer(timer, base); spin_unlock_irq(&base->lock); @@ -565,6 +574,10 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) spin_lock_irq(&base->lock); + /* Another CPU has added back the timer */ + if (timer->state != HRTIMER_RUNNING) + continue; + if (restart == HRTIMER_RESTART) enqueue_hrtimer(timer, base); else @@ -638,8 +651,7 @@ schedule_hrtimer_interruptible(struct hrtimer *timer, return schedule_hrtimer(timer, mode); } -static long __sched -nanosleep_restart(struct restart_block *restart, clockid_t clockid) +static long __sched nanosleep_restart(struct restart_block *restart) { struct timespec __user *rmtp; struct timespec tu; @@ -649,7 +661,7 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) restart->fn = do_no_restart_syscall; - hrtimer_init(&timer, clockid); + hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS); timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; @@ -669,16 +681,6 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid) return -ERESTART_RESTARTBLOCK; } -static long __sched nanosleep_restart_mono(struct restart_block *restart) -{ - return nanosleep_restart(restart, CLOCK_MONOTONIC); -} - -static long __sched nanosleep_restart_real(struct restart_block *restart) -{ - return nanosleep_restart(restart, CLOCK_REALTIME); -} - long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, const enum hrtimer_mode mode, const clockid_t clockid) { @@ -687,7 +689,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, struct timespec tu; ktime_t rem; - hrtimer_init(&timer, clockid); + hrtimer_init(&timer, clockid, mode); timer.expires = timespec_to_ktime(*rqtp); @@ -695,7 +697,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, if (rem.tv64 <= 0) return 0; - /* Absolute timers do not update the rmtp value: */ + /* Absolute timers do not update the rmtp value and restart: */ if (mode == HRTIMER_ABS) return -ERESTARTNOHAND; @@ -705,11 +707,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, return -EFAULT; restart = ¤t_thread_info()->restart_block; - restart->fn = (clockid == CLOCK_MONOTONIC) ? - nanosleep_restart_mono : nanosleep_restart_real; + restart->fn = nanosleep_restart; restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; restart->arg1 = timer.expires.tv64 >> 32; restart->arg2 = (unsigned long) rmtp; + restart->arg3 = (unsigned long) timer.base->index; return -ERESTART_RESTARTBLOCK; } @@ -736,10 +738,8 @@ static void __devinit init_hrtimers_cpu(int cpu) struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); int i; - for (i = 0; i < MAX_HRTIMER_BASES; i++) { + for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) spin_lock_init(&base->lock); - base++; - } } #ifdef CONFIG_HOTPLUG_CPU diff --git a/kernel/intermodule.c b/kernel/intermodule.c index 0cbe633420fb..55b1e5b85db9 100644 --- a/kernel/intermodule.c +++ b/kernel/intermodule.c @@ -179,3 +179,6 @@ EXPORT_SYMBOL(inter_module_register); EXPORT_SYMBOL(inter_module_unregister); EXPORT_SYMBOL(inter_module_get_request); EXPORT_SYMBOL(inter_module_put); + +MODULE_LICENSE("GPL"); + diff --git a/kernel/itimer.c b/kernel/itimer.c index c2c05c4ff28d..379be2f8c84c 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -49,9 +49,11 @@ int do_getitimer(int which, struct itimerval *value) switch (which) { case ITIMER_REAL: + spin_lock_irq(&tsk->sighand->siglock); value->it_value = itimer_get_remtime(&tsk->signal->real_timer); value->it_interval = ktime_to_timeval(tsk->signal->it_real_incr); + spin_unlock_irq(&tsk->sighand->siglock); break; case ITIMER_VIRTUAL: read_lock(&tasklist_lock); @@ -150,18 +152,25 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) switch (which) { case ITIMER_REAL: +again: + spin_lock_irq(&tsk->sighand->siglock); timer = &tsk->signal->real_timer; - hrtimer_cancel(timer); if (ovalue) { ovalue->it_value = itimer_get_remtime(timer); ovalue->it_interval = ktime_to_timeval(tsk->signal->it_real_incr); } + /* We are sharing ->siglock with it_real_fn() */ + if (hrtimer_try_to_cancel(timer) < 0) { + spin_unlock_irq(&tsk->sighand->siglock); + goto again; + } tsk->signal->it_real_incr = timeval_to_ktime(value->it_interval); expires = timeval_to_ktime(value->it_value); if (expires.tv64 != 0) hrtimer_start(timer, expires, HRTIMER_REL); + spin_unlock_irq(&tsk->sighand->siglock); break; case ITIMER_VIRTUAL: nval = timeval_to_cputime(&value->it_value); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 3ea6325228da..fef1af8a73ce 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -344,23 +344,6 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) spin_unlock_irqrestore(&kretprobe_lock, flags); } -/* - * This kprobe pre_handler is registered with every kretprobe. When probe - * hits it will set up the return probe. - */ -static int __kprobes pre_handler_kretprobe(struct kprobe *p, - struct pt_regs *regs) -{ - struct kretprobe *rp = container_of(p, struct kretprobe, kp); - unsigned long flags = 0; - - /*TODO: consider to only swap the RA after the last pre_handler fired */ - spin_lock_irqsave(&kretprobe_lock, flags); - arch_prepare_kretprobe(rp, regs); - spin_unlock_irqrestore(&kretprobe_lock, flags); - return 0; -} - static inline void free_rp_inst(struct kretprobe *rp) { struct kretprobe_instance *ri; @@ -578,6 +561,23 @@ void __kprobes unregister_jprobe(struct jprobe *jp) #ifdef ARCH_SUPPORTS_KRETPROBES +/* + * This kprobe pre_handler is registered with every kretprobe. When probe + * hits it will set up the return probe. + */ +static int __kprobes pre_handler_kretprobe(struct kprobe *p, + struct pt_regs *regs) +{ + struct kretprobe *rp = container_of(p, struct kretprobe, kp); + unsigned long flags = 0; + + /*TODO: consider to only swap the RA after the last pre_handler fired */ + spin_lock_irqsave(&kretprobe_lock, flags); + arch_prepare_kretprobe(rp, regs); + spin_unlock_irqrestore(&kretprobe_lock, flags); + return 0; +} + int __kprobes register_kretprobe(struct kretprobe *rp) { int ret = 0; @@ -631,12 +631,12 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp) unregister_kprobe(&rp->kp); /* No race here */ spin_lock_irqsave(&kretprobe_lock, flags); - free_rp_inst(rp); while ((ri = get_used_rp_inst(rp)) != NULL) { ri->rp = NULL; hlist_del(&ri->uflist); } spin_unlock_irqrestore(&kretprobe_lock, flags); + free_rp_inst(rp); } static int __init init_kprobes(void) diff --git a/kernel/module.c b/kernel/module.c index 618ed6e23ecc..5aad477ddc79 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1670,6 +1670,9 @@ static struct module *load_module(void __user *umod, goto free_mod; } + /* Userspace could have altered the string after the strlen_user() */ + args[arglen - 1] = '\0'; + if (find_module(mod->name)) { err = -EEXIST; goto free_mod; @@ -2092,7 +2095,8 @@ static unsigned long mod_find_symname(struct module *mod, const char *name) unsigned int i; for (i = 0; i < mod->num_symtab; i++) - if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0) + if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 && + mod->symtab[i].st_info != 'U') return mod->symtab[i].st_value; return 0; } diff --git a/kernel/panic.c b/kernel/panic.c index c5c4ab255834..126dc43f1c74 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -130,6 +130,7 @@ NORET_TYPE void panic(const char * fmt, ...) #endif local_irq_enable(); for (i = 0;;) { + touch_softlockup_watchdog(); i += panic_blink(i); mdelay(1); i++; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 197208b3aa2a..216f574b5ffb 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -194,9 +194,7 @@ static inline int common_clock_set(const clockid_t which_clock, static int common_timer_create(struct k_itimer *new_timer) { - hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock); - new_timer->it.real.timer.data = new_timer; - new_timer->it.real.timer.function = posix_timer_fn; + hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0); return 0; } @@ -290,7 +288,8 @@ void do_schedule_next_timer(struct siginfo *info) info->si_overrun = timr->it_overrun_last; } - unlock_timer(timr, flags); + if (timr) + unlock_timer(timr, flags); } int posix_timer_event(struct k_itimer *timr,int si_private) @@ -692,6 +691,7 @@ common_timer_set(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting) { struct hrtimer *timer = &timr->it.real.timer; + enum hrtimer_mode mode; if (old_setting) common_timer_get(timr, old_setting); @@ -713,14 +713,10 @@ common_timer_set(struct k_itimer *timr, int flags, if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) return 0; - /* Posix madness. Only absolute CLOCK_REALTIME timers - * are affected by clock sets. So we must reiniatilize - * the timer. - */ - if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME)) - hrtimer_rebase(timer, CLOCK_REALTIME); - else - hrtimer_rebase(timer, CLOCK_MONOTONIC); + mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL; + hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); + timr->it.real.timer.data = timr; + timr->it.real.timer.function = posix_timer_fn; timer->expires = timespec_to_ktime(new_setting->it_value); @@ -728,11 +724,15 @@ common_timer_set(struct k_itimer *timr, int flags, timr->it.real.interval = timespec_to_ktime(new_setting->it_interval); /* SIGEV_NONE timers are not queued ! See common_timer_get */ - if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) + if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { + /* Setup correct expiry time for relative timers */ + if (mode == HRTIMER_REL) + timer->expires = ktime_add(timer->expires, + timer->base->get_time()); return 0; + } - hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ? - HRTIMER_ABS : HRTIMER_REL); + hrtimer_start(timer, timer->expires, mode); return 0; } @@ -875,12 +875,6 @@ int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp) } EXPORT_SYMBOL_GPL(do_posix_clock_nosettime); -int do_posix_clock_notimer_create(struct k_itimer *timer) -{ - return -EINVAL; -} -EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create); - int do_posix_clock_nonanosleep(const clockid_t clock, int flags, struct timespec *t, struct timespec __user *r) { @@ -947,21 +941,8 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp) static int common_nsleep(const clockid_t which_clock, int flags, struct timespec *tsave, struct timespec __user *rmtp) { - int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL; - int clockid = which_clock; - - switch (which_clock) { - case CLOCK_REALTIME: - /* Posix madness. Only absolute timers on clock realtime - are affected by clock set. */ - if (mode != HRTIMER_ABS) - clockid = CLOCK_MONOTONIC; - case CLOCK_MONOTONIC: - break; - default: - return -EINVAL; - } - return hrtimer_nanosleep(tsave, rmtp, mode, clockid); + return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? + HRTIMER_ABS : HRTIMER_REL, which_clock); } asmlinkage long diff --git a/kernel/power/console.c b/kernel/power/console.c index 7ff375e7c95f..623786d44159 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -9,18 +9,13 @@ #include <linux/console.h> #include "power.h" -static int new_loglevel = 10; -static int orig_loglevel; -#ifdef SUSPEND_CONSOLE +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) +#define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) + static int orig_fgconsole, orig_kmsg; -#endif int pm_prepare_console(void) { - orig_loglevel = console_loglevel; - console_loglevel = new_loglevel; - -#ifdef SUSPEND_CONSOLE acquire_console_sem(); orig_fgconsole = fg_console; @@ -41,18 +36,15 @@ int pm_prepare_console(void) } orig_kmsg = kmsg_redirect; kmsg_redirect = SUSPEND_CONSOLE; -#endif return 0; } void pm_restore_console(void) { - console_loglevel = orig_loglevel; -#ifdef SUSPEND_CONSOLE acquire_console_sem(); set_console(orig_fgconsole); release_console_sem(); kmsg_redirect = orig_kmsg; -#endif return; } +#endif diff --git a/kernel/power/disk.c b/kernel/power/disk.c index e24446f8d8cd..0b43847dc980 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -53,7 +53,7 @@ static void power_down(suspend_disk_method_t mode) switch(mode) { case PM_DISK_PLATFORM: - kernel_power_off_prepare(); + kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK); error = pm_ops->enter(PM_SUSPEND_DISK); break; case PM_DISK_SHUTDOWN: @@ -95,13 +95,6 @@ static int prepare_processes(void) goto thaw; } - if (pm_disk_mode == PM_DISK_PLATFORM) { - if (pm_ops && pm_ops->prepare) { - if ((error = pm_ops->prepare(PM_SUSPEND_DISK))) - goto thaw; - } - } - /* Free memory before shutting down devices. */ if (!(error = swsusp_shrink_memory())) return 0; @@ -367,14 +360,14 @@ power_attr(resume); static ssize_t image_size_show(struct subsystem * subsys, char *buf) { - return sprintf(buf, "%u\n", image_size); + return sprintf(buf, "%lu\n", image_size); } static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n) { - unsigned int size; + unsigned long size; - if (sscanf(buf, "%u", &size) == 1) { + if (sscanf(buf, "%lu", &size) == 1) { image_size = size; return n; } diff --git a/kernel/power/main.c b/kernel/power/main.c index d253f3ae2fa5..9cb235cba4a9 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -133,10 +133,10 @@ static int suspend_enter(suspend_state_t state) static void suspend_finish(suspend_state_t state) { device_resume(); - if (pm_ops && pm_ops->finish) - pm_ops->finish(state); thaw_processes(); enable_nonboot_cpus(); + if (pm_ops && pm_ops->finish) + pm_ops->finish(state); pm_restore_console(); } diff --git a/kernel/power/power.h b/kernel/power/power.h index 7e8492fd1423..388dba680841 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -1,14 +1,6 @@ #include <linux/suspend.h> #include <linux/utsname.h> -/* With SUSPEND_CONSOLE defined suspend looks *really* cool, but - we probably do not take enough locks for switching consoles, etc, - so bad things might happen. -*/ -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) -#define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) -#endif - struct swsusp_info { struct new_utsname uts; u32 version_code; @@ -42,17 +34,14 @@ static struct subsys_attribute _name##_attr = { \ extern struct subsystem power_subsys; -extern int pm_prepare_console(void); -extern void pm_restore_console(void); - /* References to section boundaries */ extern const void __nosave_begin, __nosave_end; extern unsigned int nr_copy_pages; extern struct pbe *pagedir_nosave; -/* Preferred image size in MB (default 500) */ -extern unsigned int image_size; +/* Preferred image size in bytes (default 500 MB) */ +extern unsigned long image_size; extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 55a18d26abed..4e90905f0e87 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -70,12 +70,12 @@ #include "power.h" /* - * Preferred image size in MB (tunable via /sys/power/image_size). + * Preferred image size in bytes (tunable via /sys/power/image_size). * When it is set to N, swsusp will do its best to ensure the image - * size will not exceed N MB, but if that is impossible, it will + * size will not exceed N bytes, but if that is impossible, it will * try to create the smallest image possible. */ -unsigned int image_size = 500; +unsigned long image_size = 500 * 1024 * 1024; #ifdef CONFIG_HIGHMEM unsigned int count_highmem_pages(void); @@ -590,7 +590,7 @@ int swsusp_shrink_memory(void) if (!tmp) return -ENOMEM; pages += tmp; - } else if (size > (image_size * 1024 * 1024) / PAGE_SIZE) { + } else if (size > image_size / PAGE_SIZE) { tmp = shrink_all_memory(SHRINK_BITE); pages += tmp; } @@ -743,7 +743,6 @@ static int submit(int rw, pgoff_t page_off, void *page) if (!bio) return -ENOMEM; bio->bi_sector = page_off * (PAGE_SIZE >> 9); - bio_get(bio); bio->bi_bdev = resume_bdev; bio->bi_end_io = end_io; @@ -753,14 +752,13 @@ static int submit(int rw, pgoff_t page_off, void *page) goto Done; } - if (rw == WRITE) - bio_set_pages_dirty(bio); atomic_set(&io_done, 1); submit_bio(rw | (1 << BIO_RW_SYNC), bio); while (atomic_read(&io_done)) yield(); - + if (rw == READ) + bio_set_pages_dirty(bio); Done: bio_put(bio); return error; diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 773219907dd8..7712912dbc84 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -114,16 +114,16 @@ rcu_torture_alloc(void) { struct list_head *p; - spin_lock(&rcu_torture_lock); + spin_lock_bh(&rcu_torture_lock); if (list_empty(&rcu_torture_freelist)) { atomic_inc(&n_rcu_torture_alloc_fail); - spin_unlock(&rcu_torture_lock); + spin_unlock_bh(&rcu_torture_lock); return NULL; } atomic_inc(&n_rcu_torture_alloc); p = rcu_torture_freelist.next; list_del_init(p); - spin_unlock(&rcu_torture_lock); + spin_unlock_bh(&rcu_torture_lock); return container_of(p, struct rcu_torture, rtort_free); } @@ -134,9 +134,9 @@ static void rcu_torture_free(struct rcu_torture *p) { atomic_inc(&n_rcu_torture_free); - spin_lock(&rcu_torture_lock); + spin_lock_bh(&rcu_torture_lock); list_add_tail(&p->rtort_free, &rcu_torture_freelist); - spin_unlock(&rcu_torture_lock); + spin_unlock_bh(&rcu_torture_lock); } static void diff --git a/kernel/sched.c b/kernel/sched.c index 788ecce1e0e4..87d93be336a1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -215,7 +215,6 @@ struct runqueue { */ unsigned long nr_running; #ifdef CONFIG_SMP - unsigned long prio_bias; unsigned long cpu_load[3]; #endif unsigned long long nr_switches; @@ -669,68 +668,13 @@ static int effective_prio(task_t *p) return prio; } -#ifdef CONFIG_SMP -static inline void inc_prio_bias(runqueue_t *rq, int prio) -{ - rq->prio_bias += MAX_PRIO - prio; -} - -static inline void dec_prio_bias(runqueue_t *rq, int prio) -{ - rq->prio_bias -= MAX_PRIO - prio; -} - -static inline void inc_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running++; - if (rt_task(p)) { - if (p != rq->migration_thread) - /* - * The migration thread does the actual balancing. Do - * not bias by its priority as the ultra high priority - * will skew balancing adversely. - */ - inc_prio_bias(rq, p->prio); - } else - inc_prio_bias(rq, p->static_prio); -} - -static inline void dec_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running--; - if (rt_task(p)) { - if (p != rq->migration_thread) - dec_prio_bias(rq, p->prio); - } else - dec_prio_bias(rq, p->static_prio); -} -#else -static inline void inc_prio_bias(runqueue_t *rq, int prio) -{ -} - -static inline void dec_prio_bias(runqueue_t *rq, int prio) -{ -} - -static inline void inc_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running++; -} - -static inline void dec_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running--; -} -#endif - /* * __activate_task - move a task to the runqueue. */ static inline void __activate_task(task_t *p, runqueue_t *rq) { enqueue_task(p, rq->active); - inc_nr_running(p, rq); + rq->nr_running++; } /* @@ -739,7 +683,7 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) static inline void __activate_idle_task(task_t *p, runqueue_t *rq) { enqueue_task_head(p, rq->active); - inc_nr_running(p, rq); + rq->nr_running++; } static int recalc_task_prio(task_t *p, unsigned long long now) @@ -863,7 +807,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local) */ static void deactivate_task(struct task_struct *p, runqueue_t *rq) { - dec_nr_running(p, rq); + rq->nr_running--; dequeue_task(p, p->array); p->array = NULL; } @@ -1007,61 +951,27 @@ void kick_process(task_t *p) * We want to under-estimate the load of migration sources, to * balance conservatively. */ -static unsigned long __source_load(int cpu, int type, enum idle_type idle) +static inline unsigned long source_load(int cpu, int type) { runqueue_t *rq = cpu_rq(cpu); - unsigned long running = rq->nr_running; - unsigned long source_load, cpu_load = rq->cpu_load[type-1], - load_now = running * SCHED_LOAD_SCALE; - + unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; if (type == 0) - source_load = load_now; - else - source_load = min(cpu_load, load_now); + return load_now; - if (running > 1 || (idle == NOT_IDLE && running)) - /* - * If we are busy rebalancing the load is biased by - * priority to create 'nice' support across cpus. When - * idle rebalancing we should only bias the source_load if - * there is more than one task running on that queue to - * prevent idle rebalance from trying to pull tasks from a - * queue with only one running task. - */ - source_load = source_load * rq->prio_bias / running; - - return source_load; -} - -static inline unsigned long source_load(int cpu, int type) -{ - return __source_load(cpu, type, NOT_IDLE); + return min(rq->cpu_load[type-1], load_now); } /* * Return a high guess at the load of a migration-target cpu */ -static inline unsigned long __target_load(int cpu, int type, enum idle_type idle) +static inline unsigned long target_load(int cpu, int type) { runqueue_t *rq = cpu_rq(cpu); - unsigned long running = rq->nr_running; - unsigned long target_load, cpu_load = rq->cpu_load[type-1], - load_now = running * SCHED_LOAD_SCALE; - + unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; if (type == 0) - target_load = load_now; - else - target_load = max(cpu_load, load_now); - - if (running > 1 || (idle == NOT_IDLE && running)) - target_load = target_load * rq->prio_bias / running; + return load_now; - return target_load; -} - -static inline unsigned long target_load(int cpu, int type) -{ - return __target_load(cpu, type, NOT_IDLE); + return max(rq->cpu_load[type-1], load_now); } /* @@ -1530,7 +1440,7 @@ void fastcall wake_up_new_task(task_t *p, unsigned long clone_flags) list_add_tail(&p->run_list, ¤t->run_list); p->array = current->array; p->array->nr_active++; - inc_nr_running(p, rq); + rq->nr_running++; } set_need_resched(); } else @@ -1875,9 +1785,9 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) { dequeue_task(p, src_array); - dec_nr_running(p, src_rq); + src_rq->nr_running--; set_task_cpu(p, this_cpu); - inc_nr_running(p, this_rq); + this_rq->nr_running++; enqueue_task(p, this_array); p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) + this_rq->timestamp_last_tick; @@ -2056,9 +1966,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, /* Bias balancing toward cpus of our domain */ if (local_group) - load = __target_load(i, load_idx, idle); + load = target_load(i, load_idx); else - load = __source_load(i, load_idx, idle); + load = source_load(i, load_idx); avg_load += load; } @@ -2171,7 +2081,7 @@ static runqueue_t *find_busiest_queue(struct sched_group *group, int i; for_each_cpu_mask(i, group->cpumask) { - load = __source_load(i, 0, idle); + load = source_load(i, 0); if (load > max_load) { max_load = load; @@ -3571,10 +3481,8 @@ void set_user_nice(task_t *p, long nice) goto out_unlock; } array = p->array; - if (array) { + if (array) dequeue_task(p, array); - dec_prio_bias(rq, p->static_prio); - } old_prio = p->prio; new_prio = NICE_TO_PRIO(nice); @@ -3584,7 +3492,6 @@ void set_user_nice(task_t *p, long nice) if (array) { enqueue_task(p, array); - inc_prio_bias(rq, p->static_prio); /* * If the task increased its priority or is running and * lowered its priority, then reschedule its CPU: @@ -3850,6 +3757,10 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) { + /* negative values for policy are not valid */ + if (policy < 0) + return -EINVAL; + return do_sched_setscheduler(pid, policy, param); } @@ -4027,7 +3938,7 @@ long sched_getaffinity(pid_t pid, cpumask_t *mask) goto out_unlock; retval = 0; - cpus_and(*mask, p->cpus_allowed, cpu_possible_map); + cpus_and(*mask, p->cpus_allowed, cpu_online_map); out_unlock: read_unlock(&tasklist_lock); @@ -5137,7 +5048,7 @@ static void init_sched_build_groups(struct sched_group groups[], cpumask_t span, #define SEARCH_SCOPE 2 #define MIN_CACHE_SIZE (64*1024U) #define DEFAULT_CACHE_SIZE (5*1024*1024U) -#define ITERATIONS 2 +#define ITERATIONS 1 #define SIZE_THRESH 130 #define COST_THRESH 130 @@ -5476,9 +5387,9 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2) break; } /* - * Increase the cachesize in 5% steps: + * Increase the cachesize in 10% steps: */ - size = size * 20 / 19; + size = size * 10 / 9; } if (migration_debug) @@ -5547,13 +5458,15 @@ static void calibrate_migration_costs(const cpumask_t *cpu_map) -1 #endif ); - printk("migration_cost="); - for (distance = 0; distance <= max_distance; distance++) { - if (distance) - printk(","); - printk("%ld", (long)migration_cost[distance] / 1000); + if (system_state == SYSTEM_BOOTING) { + printk("migration_cost="); + for (distance = 0; distance <= max_distance; distance++) { + if (distance) + printk(","); + printk("%ld", (long)migration_cost[distance] / 1000); + } + printk("\n"); } - printk("\n"); j1 = jiffies; if (migration_debug) printk("migration: %ld seconds\n", (j1-j0)/HZ); @@ -6105,7 +6018,7 @@ void __init sched_init(void) runqueue_t *rq; int i, j, k; - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { prio_array_t *array; rq = cpu_rq(i); diff --git a/kernel/signal.c b/kernel/signal.c index 5dafbd36d62e..ea154104a00b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -283,7 +283,7 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, return(q); } -static inline void __sigqueue_free(struct sigqueue *q) +static void __sigqueue_free(struct sigqueue *q) { if (q->flags & SIGQUEUE_PREALLOC) return; @@ -2430,7 +2430,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo) } int -do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) +do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) { struct k_sigaction *k; sigset_t mask; @@ -2454,6 +2454,8 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) *oact = *k; if (act) { + sigdelsetmask(&act->sa.sa_mask, + sigmask(SIGKILL) | sigmask(SIGSTOP)); /* * POSIX 3.3.1.3: * "Setting a signal action to SIG_IGN for a signal that is @@ -2479,8 +2481,6 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) read_lock(&tasklist_lock); spin_lock_irq(&t->sighand->siglock); *k = *act; - sigdelsetmask(&k->sa.sa_mask, - sigmask(SIGKILL) | sigmask(SIGSTOP)); sigemptyset(&mask); sigaddset(&mask, sig); rm_from_queue_full(&mask, &t->signal->shared_pending); @@ -2495,8 +2495,6 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) } *k = *act; - sigdelsetmask(&k->sa.sa_mask, - sigmask(SIGKILL) | sigmask(SIGSTOP)); } spin_unlock_irq(¤t->sighand->siglock); @@ -2702,6 +2700,7 @@ sys_signal(int sig, __sighandler_t handler) new_sa.sa.sa_handler = handler; new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; + sigemptyset(&new_sa.sa.sa_mask); ret = do_sigaction(sig, &new_sa, &old_sa); @@ -2721,6 +2720,32 @@ sys_pause(void) #endif +#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND +asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) +{ + sigset_t newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); + + spin_lock_irq(¤t->sighand->siglock); + current->saved_sigmask = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; +} +#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ + void __init signals_init(void) { sigqueue_cachep = diff --git a/kernel/sys.c b/kernel/sys.c index d09cac23fdfd..f91218a5463e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -428,7 +428,7 @@ void kernel_kexec(void) { #ifdef CONFIG_KEXEC struct kimage *image; - image = xchg(&kexec_image, 0); + image = xchg(&kexec_image, NULL); if (!image) { return; } @@ -440,23 +440,25 @@ void kernel_kexec(void) } EXPORT_SYMBOL_GPL(kernel_kexec); +void kernel_shutdown_prepare(enum system_states state) +{ + notifier_call_chain(&reboot_notifier_list, + (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL); + system_state = state; + device_shutdown(); +} /** * kernel_halt - halt the system * * Shutdown everything and perform a clean system halt. */ -void kernel_halt_prepare(void) -{ - notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); - system_state = SYSTEM_HALT; - device_shutdown(); -} void kernel_halt(void) { - kernel_halt_prepare(); + kernel_shutdown_prepare(SYSTEM_HALT); printk(KERN_EMERG "System halted.\n"); machine_halt(); } + EXPORT_SYMBOL_GPL(kernel_halt); /** @@ -464,20 +466,13 @@ EXPORT_SYMBOL_GPL(kernel_halt); * * Shutdown everything and perform a clean system power_off. */ -void kernel_power_off_prepare(void) -{ - notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); - system_state = SYSTEM_POWER_OFF; - device_shutdown(); -} void kernel_power_off(void) { - kernel_power_off_prepare(); + kernel_shutdown_prepare(SYSTEM_POWER_OFF); printk(KERN_EMERG "Power down.\n"); machine_power_off(); } EXPORT_SYMBOL_GPL(kernel_power_off); - /* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers diff --git a/kernel/sysctl.c b/kernel/sysctl.c index f5d69b6e29f5..71dd6f62efec 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -870,6 +870,27 @@ static ctl_table vm_table[] = { .strategy = &sysctl_jiffies, }, #endif +#ifdef CONFIG_NUMA + { + .ctl_name = VM_ZONE_RECLAIM_MODE, + .procname = "zone_reclaim_mode", + .data = &zone_reclaim_mode, + .maxlen = sizeof(zone_reclaim_mode), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = VM_ZONE_RECLAIM_INTERVAL, + .procname = "zone_reclaim_interval", + .data = &zone_reclaim_interval, + .maxlen = sizeof(zone_reclaim_interval), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, +#endif { .ctl_name = 0 } }; diff --git a/kernel/time.c b/kernel/time.c index 7477b1d2079e..804539165d8b 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -155,7 +155,7 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) static int firsttime = 1; int error = 0; - if (!timespec_valid(tv)) + if (tv && !timespec_valid(tv)) return -EINVAL; error = security_settime(tv, tz); @@ -637,15 +637,16 @@ void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec) * * Returns the timespec representation of the nsec parameter. */ -inline struct timespec ns_to_timespec(const nsec_t nsec) +struct timespec ns_to_timespec(const nsec_t nsec) { struct timespec ts; - if (nsec) - ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC, - &ts.tv_nsec); - else - ts.tv_sec = ts.tv_nsec = 0; + if (!nsec) + return (struct timespec) {0, 0}; + + ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC, &ts.tv_nsec); + if (unlikely(nsec < 0)) + set_normalized_timespec(&ts, ts.tv_sec, ts.tv_nsec); return ts; } diff --git a/kernel/timer.c b/kernel/timer.c index 4f1cb0ab5251..b9dad3994676 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -495,7 +495,7 @@ unsigned long next_timer_interrupt(void) base = &__get_cpu_var(tvec_bases); spin_lock(&base->t_base.lock); expires = base->timer_jiffies + (LONG_MAX >> 1); - list = 0; + list = NULL; /* Look for timer events in tv1. */ j = base->timer_jiffies & TVR_MASK; diff --git a/kernel/user.c b/kernel/user.c index 89e562feb1b1..d9deae43a9ab 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/bitops.h> #include <linux/key.h> +#include <linux/interrupt.h> /* * UID task count cache, to get fast user lookup in "alloc_uid" @@ -27,6 +28,16 @@ static kmem_cache_t *uid_cachep; static struct list_head uidhash_table[UIDHASH_SZ]; + +/* + * The uidhash_lock is mostly taken from process context, but it is + * occasionally also taken from softirq/tasklet context, when + * task-structs get RCU-freed. Hence all locking must be softirq-safe. + * But free_uid() is also called with local interrupts disabled, and running + * local_bh_enable() with local interrupts disabled is an error - we'll run + * softirq callbacks, and they can unconditionally enable interrupts, and + * the caller of free_uid() didn't expect that.. + */ static DEFINE_SPINLOCK(uidhash_lock); struct user_struct root_user = { @@ -82,15 +93,19 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *has struct user_struct *find_user(uid_t uid) { struct user_struct *ret; + unsigned long flags; - spin_lock(&uidhash_lock); + spin_lock_irqsave(&uidhash_lock, flags); ret = uid_hash_find(uid, uidhashentry(uid)); - spin_unlock(&uidhash_lock); + spin_unlock_irqrestore(&uidhash_lock, flags); return ret; } void free_uid(struct user_struct *up) { + unsigned long flags; + + local_irq_save(flags); if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) { uid_hash_remove(up); key_put(up->uid_keyring); @@ -98,6 +113,7 @@ void free_uid(struct user_struct *up) kmem_cache_free(uid_cachep, up); spin_unlock(&uidhash_lock); } + local_irq_restore(flags); } struct user_struct * alloc_uid(uid_t uid) @@ -105,9 +121,9 @@ struct user_struct * alloc_uid(uid_t uid) struct list_head *hashent = uidhashentry(uid); struct user_struct *up; - spin_lock(&uidhash_lock); + spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); - spin_unlock(&uidhash_lock); + spin_unlock_irq(&uidhash_lock); if (!up) { struct user_struct *new; @@ -137,7 +153,7 @@ struct user_struct * alloc_uid(uid_t uid) * Before adding this, check whether we raced * on adding the same user already.. */ - spin_lock(&uidhash_lock); + spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { key_put(new->uid_keyring); @@ -147,7 +163,7 @@ struct user_struct * alloc_uid(uid_t uid) uid_hash_insert(new, hashent); up = new; } - spin_unlock(&uidhash_lock); + spin_unlock_irq(&uidhash_lock); } return up; @@ -183,9 +199,9 @@ static int __init uid_cache_init(void) INIT_LIST_HEAD(uidhash_table + n); /* Insert the root user immediately (init already runs as root) */ - spin_lock(&uidhash_lock); + spin_lock_irq(&uidhash_lock); uid_hash_insert(&root_user, uidhashentry(0)); - spin_unlock(&uidhash_lock); + spin_unlock_irq(&uidhash_lock); return 0; } diff --git a/lib/Makefile b/lib/Makefile index 8535f4d7d1c3..648b2c1242fd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ lib-y += kobject.o kref.o kobject_uevent.o klist.o -obj-y += sort.o parser.o halfmd4.o +obj-y += sort.o parser.o halfmd4.o iomap_copy.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index a5d2cdc5684c..fd355a99327c 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c @@ -15,7 +15,7 @@ unsigned long int_sqrt(unsigned long x) op = x; res = 0; - one = 1 << 30; + one = 1UL << (BITS_PER_LONG - 2); while (one > op) one >>= 2; diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c new file mode 100644 index 000000000000..a6b1e271d53c --- /dev/null +++ b/lib/iomap_copy.c @@ -0,0 +1,42 @@ +/* + * Copyright 2006 PathScale, Inc. All Rights Reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/io.h> +#include <linux/module.h> + +/** + * __iowrite32_copy - copy data to MMIO space, in 32-bit units + * @to: destination, in MMIO space (must be 32-bit aligned) + * @from: source (must be 32-bit aligned) + * @count: number of 32-bit quantities to copy + * + * Copy data from kernel space to MMIO space, in units of 32 bits at a + * time. Order of access is not guaranteed, nor is a memory barrier + * performed afterwards. + */ +void __attribute__((weak)) __iowrite32_copy(void __iomem *to, + const void *from, + size_t count) +{ + u32 __iomem *dst = to; + const u32 *src = from; + const u32 *end = src + count; + + while (src < end) + __raw_writel(*src++, dst++); +} +EXPORT_SYMBOL_GPL(__iowrite32_copy); diff --git a/lib/kobject.c b/lib/kobject.c index 7a0e6809490d..efe67fa96a71 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -72,6 +72,8 @@ static int get_kobj_path_length(struct kobject *kobj) * Add 1 to strlen for leading '/' of each level. */ do { + if (kobject_name(parent) == NULL) + return 0; length += strlen(kobject_name(parent)) + 1; parent = parent->parent; } while (parent); @@ -107,6 +109,8 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) int len; len = get_kobj_path_length(kobj); + if (len == 0) + return NULL; path = kmalloc(len, gfp_mask); if (!path) return NULL; @@ -162,6 +166,11 @@ int kobject_add(struct kobject * kobj) return -ENOENT; if (!kobj->k_name) kobj->k_name = kobj->name; + if (!kobj->k_name) { + pr_debug("kobject attempted to be registered with no name!\n"); + WARN_ON(1); + return -EINVAL; + } parent = kobject_get(kobj->parent); pr_debug("kobject %s: registering. parent: %s, set: %s\n", diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index f56e27ae9d52..1b1985c136ec 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -22,7 +22,7 @@ #include <linux/kobject.h> #include <net/sock.h> -#define BUFFER_SIZE 1024 /* buffer for the variables */ +#define BUFFER_SIZE 2048 /* buffer for the variables */ #define NUM_ENVP 32 /* number of env pointers */ #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index c8bb8cc899d7..d8b6bb419d49 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -72,9 +72,9 @@ static void __spin_lock_debug(spinlock_t *lock) for (;;) { for (i = 0; i < loops_per_jiffy * HZ; i++) { - cpu_relax(); if (__raw_spin_trylock(&lock->raw_lock)) return; + __delay(1); } /* lockup suspected: */ if (print_once) { @@ -144,9 +144,9 @@ static void __read_lock_debug(rwlock_t *lock) for (;;) { for (i = 0; i < loops_per_jiffy * HZ; i++) { - cpu_relax(); if (__raw_read_trylock(&lock->raw_lock)) return; + __delay(1); } /* lockup suspected: */ if (print_once) { @@ -217,9 +217,9 @@ static void __write_lock_debug(rwlock_t *lock) for (;;) { for (i = 0; i < loops_per_jiffy * HZ; i++) { - cpu_relax(); if (__raw_write_trylock(&lock->raw_lock)) return; + __delay(1); } /* lockup suspected: */ if (print_once) { diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 8a8b3a16133e..c4c1ac5fbd1a 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -94,10 +94,28 @@ next: bs = bm->bad_shift[text[shift-i]]; return UINT_MAX; } +static int subpattern(u8 *pattern, int i, int j, int g) +{ + int x = i+g-1, y = j+g-1, ret = 0; + + while(pattern[x--] == pattern[y--]) { + if (y < 0) { + ret = 1; + break; + } + if (--g == 0) { + ret = pattern[i-1] != pattern[j-1]; + break; + } + } + + return ret; +} + static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, unsigned int len) { - int i, j, ended, l[ASIZE]; + int i, j, g; for (i = 0; i < ASIZE; i++) bm->bad_shift[i] = len; @@ -106,23 +124,15 @@ static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, /* Compute the good shift array, used to match reocurrences * of a subpattern */ - for (i = 1; i < bm->patlen; i++) { - for (j = 0; j < bm->patlen && bm->pattern[bm->patlen - 1 - j] - == bm->pattern[bm->patlen - 1 - i - j]; j++); - l[i] = j; - } - bm->good_shift[0] = 1; for (i = 1; i < bm->patlen; i++) bm->good_shift[i] = bm->patlen; - for (i = bm->patlen - 1; i > 0; i--) - bm->good_shift[l[i]] = i; - ended = 0; - for (i = 0; i < bm->patlen; i++) { - if (l[i] == bm->patlen - 1 - i) - ended = i; - if (ended) - bm->good_shift[i] = ended; + for (i = bm->patlen-1, g = 1; i > 0; g++, i--) { + for (j = i-1; j >= 1-g ; j--) + if (subpattern(bm->pattern, i, j, g)) { + bm->good_shift[g] = bm->patlen-j-g; + break; + } } } diff --git a/mm/filemap.c b/mm/filemap.c index a965b6b35f26..44da3d476994 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -94,6 +94,7 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, * ->private_lock (try_to_unmap_one) * ->tree_lock (try_to_unmap_one) * ->zone.lru_lock (follow_page->mark_page_accessed) + * ->zone.lru_lock (check_pte_range->isolate_lru_page) * ->private_lock (page_remove_rmap->set_page_dirty) * ->tree_lock (page_remove_rmap->set_page_dirty) * ->inode_lock (page_remove_rmap->set_page_dirty) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b21d78c941b5..67f29516662a 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -107,7 +107,7 @@ struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) set_page_count(page, 1); page[1].mapping = (void *)free_huge_page; for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) - clear_highpage(&page[i]); + clear_user_highpage(&page[i], addr); return page; } @@ -391,12 +391,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, if (!new_page) { page_cache_release(old_page); - - /* Logically this is OOM, not a SIGBUS, but an OOM - * could cause the kernel to go killing other - * processes which won't help the hugepage situation - * at all (?) */ - return VM_FAULT_SIGBUS; + return VM_FAULT_OOM; } spin_unlock(&mm->page_table_lock); @@ -444,6 +439,7 @@ retry: page = alloc_huge_page(vma, address); if (!page) { hugetlb_put_quota(mapping); + ret = VM_FAULT_OOM; goto out; } diff --git a/mm/memory.c b/mm/memory.c index 7a11ddd5060f..2bee1f21aa8a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1871,6 +1871,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out; entry = pte_to_swp_entry(orig_pte); +again: page = lookup_swap_cache(entry); if (!page) { swapin_readahead(entry, address, vma); @@ -1894,6 +1895,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, mark_page_accessed(page); lock_page(page); + if (!PageSwapCache(page)) { + /* Page migration has occured */ + unlock_page(page); + page_cache_release(page); + goto again; + } /* * Back out if somebody else already faulted in this pte. diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 3171f884d245..3bd7fb7e4b75 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -95,6 +95,9 @@ #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1) /* Invert check for nodemask */ #define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2) /* Gather statistics */ +/* The number of pages to migrate per call to migrate_pages() */ +#define MIGRATE_CHUNK_SIZE 256 + static kmem_cache_t *policy_cache; static kmem_cache_t *sn_cache; @@ -185,8 +188,8 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) } static void gather_stats(struct page *, void *); -static void migrate_page_add(struct vm_area_struct *vma, - struct page *page, struct list_head *pagelist, unsigned long flags); +static void migrate_page_add(struct page *page, struct list_head *pagelist, + unsigned long flags); /* Scan through pages checking if pages follow certain conditions. */ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, @@ -208,6 +211,17 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, page = vm_normal_page(vma, addr, *pte); if (!page) continue; + /* + * The check for PageReserved here is important to avoid + * handling zero pages and other pages that may have been + * marked special by the system. + * + * If the PageReserved would not be checked here then f.e. + * the location of the zero page could have an influence + * on MPOL_MF_STRICT, zero pages would be counted for + * the per node stats, and there would be useless attempts + * to put zero pages on the migration list. + */ if (PageReserved(page)) continue; nid = page_to_nid(page); @@ -216,11 +230,8 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, if (flags & MPOL_MF_STATS) gather_stats(page, private); - else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { - spin_unlock(ptl); - migrate_page_add(vma, page, private, flags); - spin_lock(ptl); - } + else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) + migrate_page_add(page, private, flags); else break; } while (pte++, addr += PAGE_SIZE, addr != end); @@ -309,6 +320,10 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, int err; struct vm_area_struct *first, *vma, *prev; + /* Clear the LRU lists so pages can be isolated */ + if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) + lru_add_drain_all(); + first = find_vma(mm, start); if (!first) return ERR_PTR(-EFAULT); @@ -519,72 +534,103 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, * page migration */ -/* Check if we are the only process mapping the page in question */ -static inline int single_mm_mapping(struct mm_struct *mm, - struct address_space *mapping) +static void migrate_page_add(struct page *page, struct list_head *pagelist, + unsigned long flags) { - struct vm_area_struct *vma; - struct prio_tree_iter iter; - int rc = 1; - - spin_lock(&mapping->i_mmap_lock); - vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX) - if (mm != vma->vm_mm) { - rc = 0; - goto out; - } - list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) - if (mm != vma->vm_mm) { - rc = 0; - goto out; - } -out: - spin_unlock(&mapping->i_mmap_lock); - return rc; + /* + * Avoid migrating a page that is shared with others. + */ + if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { + if (isolate_lru_page(page)) + list_add(&page->lru, pagelist); + } } /* - * Add a page to be migrated to the pagelist + * Migrate the list 'pagelist' of pages to a certain destination. + * + * Specify destination with either non-NULL vma or dest_node >= 0 + * Return the number of pages not migrated or error code */ -static void migrate_page_add(struct vm_area_struct *vma, - struct page *page, struct list_head *pagelist, unsigned long flags) +static int migrate_pages_to(struct list_head *pagelist, + struct vm_area_struct *vma, int dest) { - /* - * Avoid migrating a page that is shared by others and not writable. - */ - if ((flags & MPOL_MF_MOVE_ALL) || !page->mapping || PageAnon(page) || - mapping_writably_mapped(page->mapping) || - single_mm_mapping(vma->vm_mm, page->mapping)) { - int rc = isolate_lru_page(page); + LIST_HEAD(newlist); + LIST_HEAD(moved); + LIST_HEAD(failed); + int err = 0; + int nr_pages; + struct page *page; + struct list_head *p; - if (rc == 1) - list_add(&page->lru, pagelist); - /* - * If the isolate attempt was not successful then we just - * encountered an unswappable page. Something must be wrong. - */ - WARN_ON(rc == 0); +redo: + nr_pages = 0; + list_for_each(p, pagelist) { + if (vma) + page = alloc_page_vma(GFP_HIGHUSER, vma, vma->vm_start); + else + page = alloc_pages_node(dest, GFP_HIGHUSER, 0); + + if (!page) { + err = -ENOMEM; + goto out; + } + list_add(&page->lru, &newlist); + nr_pages++; + if (nr_pages > MIGRATE_CHUNK_SIZE); + break; + } + err = migrate_pages(pagelist, &newlist, &moved, &failed); + + putback_lru_pages(&moved); /* Call release pages instead ?? */ + + if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist)) + goto redo; +out: + /* Return leftover allocated pages */ + while (!list_empty(&newlist)) { + page = list_entry(newlist.next, struct page, lru); + list_del(&page->lru); + __free_page(page); } + list_splice(&failed, pagelist); + if (err < 0) + return err; + + /* Calculate number of leftover pages */ + nr_pages = 0; + list_for_each(p, pagelist) + nr_pages++; + return nr_pages; } -static int swap_pages(struct list_head *pagelist) +/* + * Migrate pages from one node to a target node. + * Returns error or the number of pages not migrated. + */ +int migrate_to_node(struct mm_struct *mm, int source, int dest, int flags) { - LIST_HEAD(moved); - LIST_HEAD(failed); - int n; + nodemask_t nmask; + LIST_HEAD(pagelist); + int err = 0; - n = migrate_pages(pagelist, NULL, &moved, &failed); - putback_lru_pages(&failed); - putback_lru_pages(&moved); + nodes_clear(nmask); + node_set(source, nmask); - return n; + check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask, + flags | MPOL_MF_DISCONTIG_OK, &pagelist); + + if (!list_empty(&pagelist)) { + err = migrate_pages_to(&pagelist, NULL, dest); + if (!list_empty(&pagelist)) + putback_lru_pages(&pagelist); + } + return err; } /* - * For now migrate_pages simply swaps out the pages from nodes that are in - * the source set but not in the target set. In the future, we would - * want a function that moves pages between the two nodesets in such - * a way as to preserve the physical layout as much as possible. + * Move pages between the two nodesets so as to preserve the physical + * layout as much as possible. * * Returns the number of page that could not be moved. */ @@ -592,22 +638,76 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) { LIST_HEAD(pagelist); - int count = 0; - nodemask_t nodes; + int busy = 0; + int err = 0; + nodemask_t tmp; - nodes_andnot(nodes, *from_nodes, *to_nodes); + down_read(&mm->mmap_sem); - down_read(&mm->mmap_sem); - check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes, - flags | MPOL_MF_DISCONTIG_OK, &pagelist); +/* + * Find a 'source' bit set in 'tmp' whose corresponding 'dest' + * bit in 'to' is not also set in 'tmp'. Clear the found 'source' + * bit in 'tmp', and return that <source, dest> pair for migration. + * The pair of nodemasks 'to' and 'from' define the map. + * + * If no pair of bits is found that way, fallback to picking some + * pair of 'source' and 'dest' bits that are not the same. If the + * 'source' and 'dest' bits are the same, this represents a node + * that will be migrating to itself, so no pages need move. + * + * If no bits are left in 'tmp', or if all remaining bits left + * in 'tmp' correspond to the same bit in 'to', return false + * (nothing left to migrate). + * + * This lets us pick a pair of nodes to migrate between, such that + * if possible the dest node is not already occupied by some other + * source node, minimizing the risk of overloading the memory on a + * node that would happen if we migrated incoming memory to a node + * before migrating outgoing memory source that same node. + * + * A single scan of tmp is sufficient. As we go, we remember the + * most recent <s, d> pair that moved (s != d). If we find a pair + * that not only moved, but what's better, moved to an empty slot + * (d is not set in tmp), then we break out then, with that pair. + * Otherwise when we finish scannng from_tmp, we at least have the + * most recent <s, d> pair that moved. If we get all the way through + * the scan of tmp without finding any node that moved, much less + * moved to an empty node, then there is nothing left worth migrating. + */ - if (!list_empty(&pagelist)) { - count = swap_pages(&pagelist); - putback_lru_pages(&pagelist); + tmp = *from_nodes; + while (!nodes_empty(tmp)) { + int s,d; + int source = -1; + int dest = 0; + + for_each_node_mask(s, tmp) { + d = node_remap(s, *from_nodes, *to_nodes); + if (s == d) + continue; + + source = s; /* Node moved. Memorize */ + dest = d; + + /* dest not in remaining from nodes? */ + if (!node_isset(dest, tmp)) + break; + } + if (source == -1) + break; + + node_clear(source, tmp); + err = migrate_to_node(mm, source, dest, flags); + if (err > 0) + busy += err; + if (err < 0) + break; } up_read(&mm->mmap_sem); - return count; + if (err < 0) + return err; + return busy; } long do_mbind(unsigned long start, unsigned long len, @@ -667,8 +767,9 @@ long do_mbind(unsigned long start, unsigned long len, int nr_failed = 0; err = mbind_range(vma, start, end, new); + if (!list_empty(&pagelist)) - nr_failed = swap_pages(&pagelist); + nr_failed = migrate_pages_to(&pagelist, vma, -1); if (!err && nr_failed && (flags & MPOL_MF_STRICT)) err = -EIO; @@ -1000,6 +1101,33 @@ static unsigned interleave_nodes(struct mempolicy *policy) return nid; } +/* + * Depending on the memory policy provide a node from which to allocate the + * next slab entry. + */ +unsigned slab_node(struct mempolicy *policy) +{ + switch (policy->policy) { + case MPOL_INTERLEAVE: + return interleave_nodes(policy); + + case MPOL_BIND: + /* + * Follow bind policy behavior and start allocation at the + * first node. + */ + return policy->v.zonelist->zones[0]->zone_pgdat->node_id; + + case MPOL_PREFERRED: + if (policy->v.preferred_node >= 0) + return policy->v.preferred_node; + /* Fall through */ + + default: + return numa_node_id(); + } +} + /* Do static interleaving for a VMA with known offset. */ static unsigned offset_il_node(struct mempolicy *pol, struct vm_area_struct *vma, unsigned long off) @@ -1031,6 +1159,7 @@ static inline unsigned interleave_nid(struct mempolicy *pol, return interleave_nodes(pol); } +#ifdef CONFIG_HUGETLBFS /* Return a zonelist suitable for a huge page allocation. */ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr) { @@ -1044,6 +1173,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr) } return zonelist_policy(GFP_HIGHUSER, pol); } +#endif /* Allocate a page in interleaved policy. Own path because it needs to do special accounting. */ diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 14bd4ec79597..b05ab8f2a562 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -271,6 +271,7 @@ void out_of_memory(gfp_t gfp_mask, int order) if (printk_ratelimit()) { printk("oom-killer: gfp_mask=0x%x, order=%d\n", gfp_mask, order); + dump_stack(); show_mem(); } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 5240e426c1f7..945559fb63d2 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -46,7 +46,7 @@ static long ratelimit_pages = 32; static long total_pages; /* The total number of pages in the machine. */ -static int dirty_exceeded; /* Dirty mem may be over limit */ +static int dirty_exceeded __cacheline_aligned_in_smp; /* Dirty mem may be over limit */ /* * When balance_dirty_pages decides that the caller needs to perform some @@ -212,7 +212,8 @@ static void balance_dirty_pages(struct address_space *mapping) if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) break; - dirty_exceeded = 1; + if (!dirty_exceeded) + dirty_exceeded = 1; /* Note: nr_reclaimable denotes nr_dirty + nr_unstable. * Unstable writes are a feature of certain networked @@ -234,7 +235,7 @@ static void balance_dirty_pages(struct address_space *mapping) blk_congestion_wait(WRITE, HZ/10); } - if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) + if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh && dirty_exceeded) dirty_exceeded = 0; if (writeback_in_progress(bdi)) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c2e29743a8d1..dde04ff4be31 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -878,7 +878,9 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, mark = (*z)->pages_high; if (!zone_watermark_ok(*z, order, mark, classzone_idx, alloc_flags)) - continue; + if (!zone_reclaim_mode || + !zone_reclaim(*z, gfp_mask, order)) + continue; } page = buffered_rmqueue(zonelist, *z, order, gfp_mask); @@ -1211,18 +1213,21 @@ static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) { int cpu = 0; - memset(ret, 0, sizeof(*ret)); + memset(ret, 0, nr * sizeof(unsigned long)); cpus_and(*cpumask, *cpumask, cpu_online_map); cpu = first_cpu(*cpumask); while (cpu < NR_CPUS) { unsigned long *in, *out, off; + if (!cpu_isset(cpu, *cpumask)) + continue; + in = (unsigned long *)&per_cpu(page_states, cpu); cpu = next_cpu(cpu, *cpumask); - if (cpu < NR_CPUS) + if (likely(cpu < NR_CPUS)) prefetch(&per_cpu(page_states, cpu)); out = (unsigned long *)ret; @@ -1595,13 +1600,22 @@ static void __init build_zonelists(pg_data_t *pgdat) prev_node = local_node; nodes_clear(used_mask); while ((node = find_next_best_node(local_node, &used_mask)) >= 0) { + int distance = node_distance(local_node, node); + + /* + * If another node is sufficiently far away then it is better + * to reclaim pages in a zone before going off node. + */ + if (distance > RECLAIM_DISTANCE) + zone_reclaim_mode = 1; + /* * We don't want to pressure a particular node. * So adding penalty to the first node in same * distance group to make it round-robin. */ - if (node_distance(local_node, node) != - node_distance(local_node, prev_node)) + + if (distance != node_distance(local_node, prev_node)) node_load[node] += load; prev_node = node; load--; @@ -1788,7 +1802,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, memmap_init_zone((size), (nid), (zone), (start_pfn)) #endif -static int __meminit zone_batchsize(struct zone *zone) +static int __cpuinit zone_batchsize(struct zone *zone) { int batch; @@ -1875,14 +1889,13 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p, * not check if the processor is online before following the pageset pointer. * Other parts of the kernel may not check if the zone is available. */ -static struct per_cpu_pageset - boot_pageset[NR_CPUS]; +static struct per_cpu_pageset boot_pageset[NR_CPUS]; /* * Dynamically allocate memory for the * per cpu pageset array in struct zone. */ -static int __meminit process_zones(int cpu) +static int __cpuinit process_zones(int cpu) { struct zone *zone, *dzone; @@ -1923,7 +1936,7 @@ static inline void free_zone_pagesets(int cpu) } } -static int __meminit pageset_cpuup_callback(struct notifier_block *nfb, +static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/mm/rmap.c b/mm/rmap.c index dfbb89f99a15..df2c41c2a9a2 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -33,7 +33,7 @@ * mapping->i_mmap_lock * anon_vma->lock * mm->page_table_lock or pte_lock - * zone->lru_lock (in mark_page_accessed) + * zone->lru_lock (in mark_page_accessed, isolate_lru_page) * swap_lock (in swap_duplicate, swap_info_get) * mmlist_lock (in mmput, drain_mmlist and others) * mapping->private_lock (in __set_page_dirty_buffers) @@ -52,6 +52,7 @@ #include <linux/init.h> #include <linux/rmap.h> #include <linux/rcupdate.h> +#include <linux/module.h> #include <asm/tlbflush.h> @@ -205,6 +206,36 @@ out: return anon_vma; } +#ifdef CONFIG_MIGRATION +/* + * Remove an anonymous page from swap replacing the swap pte's + * through real pte's pointing to valid pages and then releasing + * the page from the swap cache. + * + * Must hold page lock on page. + */ +void remove_from_swap(struct page *page) +{ + struct anon_vma *anon_vma; + struct vm_area_struct *vma; + + if (!PageAnon(page) || !PageSwapCache(page)) + return; + + anon_vma = page_lock_anon_vma(page); + if (!anon_vma) + return; + + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) + remove_vma_swap(vma, page); + + spin_unlock(&anon_vma->lock); + + delete_from_swap_cache(page); +} +EXPORT_SYMBOL(remove_from_swap); +#endif + /* * At what user virtual address is page expected in vma? */ @@ -541,7 +572,8 @@ void page_remove_rmap(struct page *page) * Subfunctions of try_to_unmap: try_to_unmap_one called * repeatedly from either try_to_unmap_anon or try_to_unmap_file. */ -static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) +static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, + int ignore_refs) { struct mm_struct *mm = vma->vm_mm; unsigned long address; @@ -564,7 +596,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) * skipped over this mm) then we should reactivate it. */ if ((vma->vm_flags & VM_LOCKED) || - ptep_clear_flush_young(vma, address, pte)) { + (ptep_clear_flush_young(vma, address, pte) + && !ignore_refs)) { ret = SWAP_FAIL; goto out_unmap; } @@ -698,7 +731,7 @@ static void try_to_unmap_cluster(unsigned long cursor, pte_unmap_unlock(pte - 1, ptl); } -static int try_to_unmap_anon(struct page *page) +static int try_to_unmap_anon(struct page *page, int ignore_refs) { struct anon_vma *anon_vma; struct vm_area_struct *vma; @@ -709,7 +742,7 @@ static int try_to_unmap_anon(struct page *page) return ret; list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { - ret = try_to_unmap_one(page, vma); + ret = try_to_unmap_one(page, vma, ignore_refs); if (ret == SWAP_FAIL || !page_mapped(page)) break; } @@ -726,7 +759,7 @@ static int try_to_unmap_anon(struct page *page) * * This function is only called from try_to_unmap for object-based pages. */ -static int try_to_unmap_file(struct page *page) +static int try_to_unmap_file(struct page *page, int ignore_refs) { struct address_space *mapping = page->mapping; pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); @@ -740,7 +773,7 @@ static int try_to_unmap_file(struct page *page) spin_lock(&mapping->i_mmap_lock); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { - ret = try_to_unmap_one(page, vma); + ret = try_to_unmap_one(page, vma, ignore_refs); if (ret == SWAP_FAIL || !page_mapped(page)) goto out; } @@ -825,16 +858,16 @@ out: * SWAP_AGAIN - we missed a mapping, try again later * SWAP_FAIL - the page is unswappable */ -int try_to_unmap(struct page *page) +int try_to_unmap(struct page *page, int ignore_refs) { int ret; BUG_ON(!PageLocked(page)); if (PageAnon(page)) - ret = try_to_unmap_anon(page); + ret = try_to_unmap_anon(page, ignore_refs); else - ret = try_to_unmap_file(page); + ret = try_to_unmap_file(page, ignore_refs); if (!page_mapped(page)) ret = SWAP_SUCCESS; diff --git a/mm/shmem.c b/mm/shmem.c index ce501bce1c2e..f7ac7b812f92 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1028,6 +1028,14 @@ repeat: page_cache_release(swappage); goto repeat; } + if (!PageSwapCache(swappage)) { + /* Page migration has occured */ + shmem_swp_unmap(entry); + spin_unlock(&info->lock); + unlock_page(swappage); + page_cache_release(swappage); + goto repeat; + } if (PageWriteback(swappage)) { shmem_swp_unmap(entry); spin_unlock(&info->lock); diff --git a/mm/slab.c b/mm/slab.c index 9374293a3012..add05d808a4a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -55,7 +55,7 @@ * * SMP synchronization: * constructors and destructors are called without any locking. - * Several members in kmem_cache_t and struct slab never change, they + * Several members in struct kmem_cache and struct slab never change, they * are accessed without any locking. * The per-cpu arrays are never accessed from the wrong cpu, no locking, * and local interrupts are disabled so slab code is preempt-safe. @@ -68,7 +68,7 @@ * Further notes from the original documentation: * * 11 April '97. Started multi-threading - markhe - * The global cache-chain is protected by the semaphore 'cache_chain_sem'. + * The global cache-chain is protected by the mutex 'cache_chain_mutex'. * The sem is only needed when accessing/extending the cache-chain, which * can never happen inside an interrupt (kmem_cache_create(), * kmem_cache_shrink() and kmem_cache_reap()). @@ -103,6 +103,8 @@ #include <linux/rcupdate.h> #include <linux/string.h> #include <linux/nodemask.h> +#include <linux/mempolicy.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/cacheflush.h> @@ -242,7 +244,7 @@ struct slab { */ struct slab_rcu { struct rcu_head head; - kmem_cache_t *cachep; + struct kmem_cache *cachep; void *addr; }; @@ -292,6 +294,7 @@ struct kmem_list3 { unsigned long next_reap; int free_touched; unsigned int free_limit; + unsigned int colour_next; /* Per-node cache coloring */ spinlock_t list_lock; struct array_cache *shared; /* shared per node */ struct array_cache **alien; /* on other nodes */ @@ -314,6 +317,8 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS]; */ static __always_inline int index_of(const size_t size) { + extern void __bad_size(void); + if (__builtin_constant_p(size)) { int i = 0; @@ -324,25 +329,23 @@ static __always_inline int index_of(const size_t size) i++; #include "linux/kmalloc_sizes.h" #undef CACHE - { - extern void __bad_size(void); - __bad_size(); - } + __bad_size(); } else - BUG(); + __bad_size(); return 0; } #define INDEX_AC index_of(sizeof(struct arraycache_init)) #define INDEX_L3 index_of(sizeof(struct kmem_list3)) -static inline void kmem_list3_init(struct kmem_list3 *parent) +static void kmem_list3_init(struct kmem_list3 *parent) { INIT_LIST_HEAD(&parent->slabs_full); INIT_LIST_HEAD(&parent->slabs_partial); INIT_LIST_HEAD(&parent->slabs_free); parent->shared = NULL; parent->alien = NULL; + parent->colour_next = 0; spin_lock_init(&parent->list_lock); parent->free_objects = 0; parent->free_touched = 0; @@ -362,7 +365,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent) } while (0) /* - * kmem_cache_t + * struct kmem_cache * * manages a cache. */ @@ -373,7 +376,7 @@ struct kmem_cache { unsigned int batchcount; unsigned int limit; unsigned int shared; - unsigned int objsize; + unsigned int buffer_size; /* 2) touched by every alloc & free from the backend */ struct kmem_list3 *nodelists[MAX_NUMNODES]; unsigned int flags; /* constant flags */ @@ -389,16 +392,15 @@ struct kmem_cache { size_t colour; /* cache colouring range */ unsigned int colour_off; /* colour offset */ - unsigned int colour_next; /* cache colouring */ - kmem_cache_t *slabp_cache; + struct kmem_cache *slabp_cache; unsigned int slab_size; unsigned int dflags; /* dynamic flags */ /* constructor func */ - void (*ctor) (void *, kmem_cache_t *, unsigned long); + void (*ctor) (void *, struct kmem_cache *, unsigned long); /* de-constructor func */ - void (*dtor) (void *, kmem_cache_t *, unsigned long); + void (*dtor) (void *, struct kmem_cache *, unsigned long); /* 4) cache creation/removal */ const char *name; @@ -421,8 +423,14 @@ struct kmem_cache { atomic_t freemiss; #endif #if DEBUG - int dbghead; - int reallen; + /* + * If debugging is enabled, then the allocator can add additional + * fields and/or padding to every object. buffer_size contains the total + * object size including these internal fields, the following two + * variables contain the offset to the user object and its size. + */ + int obj_offset; + int obj_size; #endif }; @@ -493,50 +501,50 @@ struct kmem_cache { /* memory layout of objects: * 0 : objp - * 0 .. cachep->dbghead - BYTES_PER_WORD - 1: padding. This ensures that + * 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that * the end of an object is aligned with the end of the real * allocation. Catches writes behind the end of the allocation. - * cachep->dbghead - BYTES_PER_WORD .. cachep->dbghead - 1: + * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1: * redzone word. - * cachep->dbghead: The real object. - * cachep->objsize - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] - * cachep->objsize - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long] + * cachep->obj_offset: The real object. + * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long] */ -static int obj_dbghead(kmem_cache_t *cachep) +static int obj_offset(struct kmem_cache *cachep) { - return cachep->dbghead; + return cachep->obj_offset; } -static int obj_reallen(kmem_cache_t *cachep) +static int obj_size(struct kmem_cache *cachep) { - return cachep->reallen; + return cachep->obj_size; } -static unsigned long *dbg_redzone1(kmem_cache_t *cachep, void *objp) +static unsigned long *dbg_redzone1(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); - return (unsigned long*) (objp+obj_dbghead(cachep)-BYTES_PER_WORD); + return (unsigned long*) (objp+obj_offset(cachep)-BYTES_PER_WORD); } -static unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp) +static unsigned long *dbg_redzone2(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long *)(objp + cachep->objsize - + return (unsigned long *)(objp + cachep->buffer_size - 2 * BYTES_PER_WORD); - return (unsigned long *)(objp + cachep->objsize - BYTES_PER_WORD); + return (unsigned long *)(objp + cachep->buffer_size - BYTES_PER_WORD); } -static void **dbg_userword(kmem_cache_t *cachep, void *objp) +static void **dbg_userword(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void **)(objp + cachep->objsize - BYTES_PER_WORD); + return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD); } #else -#define obj_dbghead(x) 0 -#define obj_reallen(cachep) (cachep->objsize) +#define obj_offset(x) 0 +#define obj_size(cachep) (cachep->buffer_size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) @@ -589,6 +597,18 @@ static inline struct slab *page_get_slab(struct page *page) return (struct slab *)page->lru.prev; } +static inline struct kmem_cache *virt_to_cache(const void *obj) +{ + struct page *page = virt_to_page(obj); + return page_get_cache(page); +} + +static inline struct slab *virt_to_slab(const void *obj) +{ + struct page *page = virt_to_page(obj); + return page_get_slab(page); +} + /* These are the default caches for kmalloc. Custom caches can have other sizes. */ struct cache_sizes malloc_sizes[] = { #define CACHE(x) { .cs_size = (x) }, @@ -617,21 +637,21 @@ static struct arraycache_init initarray_generic = { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; /* internal cache of cache description objs */ -static kmem_cache_t cache_cache = { +static struct kmem_cache cache_cache = { .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, - .objsize = sizeof(kmem_cache_t), + .buffer_size = sizeof(struct kmem_cache), .flags = SLAB_NO_REAP, .spinlock = SPIN_LOCK_UNLOCKED, .name = "kmem_cache", #if DEBUG - .reallen = sizeof(kmem_cache_t), + .obj_size = sizeof(struct kmem_cache), #endif }; /* Guard access to the cache-chain. */ -static struct semaphore cache_chain_sem; +static DEFINE_MUTEX(cache_chain_mutex); static struct list_head cache_chain; /* @@ -655,17 +675,17 @@ static enum { static DEFINE_PER_CPU(struct work_struct, reap_work); -static void free_block(kmem_cache_t *cachep, void **objpp, int len, int node); -static void enable_cpucache(kmem_cache_t *cachep); +static void free_block(struct kmem_cache *cachep, void **objpp, int len, int node); +static void enable_cpucache(struct kmem_cache *cachep); static void cache_reap(void *unused); -static int __node_shrink(kmem_cache_t *cachep, int node); +static int __node_shrink(struct kmem_cache *cachep, int node); -static inline struct array_cache *ac_data(kmem_cache_t *cachep) +static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) { return cachep->array[smp_processor_id()]; } -static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags) +static inline struct kmem_cache *__find_general_cachep(size_t size, gfp_t gfpflags) { struct cache_sizes *csizep = malloc_sizes; @@ -689,43 +709,80 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags) return csizep->cs_cachep; } -kmem_cache_t *kmem_find_general_cachep(size_t size, gfp_t gfpflags) +struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags) { return __find_general_cachep(size, gfpflags); } EXPORT_SYMBOL(kmem_find_general_cachep); -/* Cal the num objs, wastage, and bytes left over for a given slab size. */ -static void cache_estimate(unsigned long gfporder, size_t size, size_t align, - int flags, size_t *left_over, unsigned int *num) +static size_t slab_mgmt_size(size_t nr_objs, size_t align) { - int i; - size_t wastage = PAGE_SIZE << gfporder; - size_t extra = 0; - size_t base = 0; + return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align); +} - if (!(flags & CFLGS_OFF_SLAB)) { - base = sizeof(struct slab); - extra = sizeof(kmem_bufctl_t); - } - i = 0; - while (i * size + ALIGN(base + i * extra, align) <= wastage) - i++; - if (i > 0) - i--; +/* Calculate the number of objects and left-over bytes for a given + buffer size. */ +static void cache_estimate(unsigned long gfporder, size_t buffer_size, + size_t align, int flags, size_t *left_over, + unsigned int *num) +{ + int nr_objs; + size_t mgmt_size; + size_t slab_size = PAGE_SIZE << gfporder; + + /* + * The slab management structure can be either off the slab or + * on it. For the latter case, the memory allocated for a + * slab is used for: + * + * - The struct slab + * - One kmem_bufctl_t for each object + * - Padding to respect alignment of @align + * - @buffer_size bytes for each object + * + * If the slab management structure is off the slab, then the + * alignment will already be calculated into the size. Because + * the slabs are all pages aligned, the objects will be at the + * correct alignment when allocated. + */ + if (flags & CFLGS_OFF_SLAB) { + mgmt_size = 0; + nr_objs = slab_size / buffer_size; + + if (nr_objs > SLAB_LIMIT) + nr_objs = SLAB_LIMIT; + } else { + /* + * Ignore padding for the initial guess. The padding + * is at most @align-1 bytes, and @buffer_size is at + * least @align. In the worst case, this result will + * be one greater than the number of objects that fit + * into the memory allocation when taking the padding + * into account. + */ + nr_objs = (slab_size - sizeof(struct slab)) / + (buffer_size + sizeof(kmem_bufctl_t)); + + /* + * This calculated number will be either the right + * amount, or one greater than what we want. + */ + if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size + > slab_size) + nr_objs--; - if (i > SLAB_LIMIT) - i = SLAB_LIMIT; + if (nr_objs > SLAB_LIMIT) + nr_objs = SLAB_LIMIT; - *num = i; - wastage -= i * size; - wastage -= ALIGN(base + i * extra, align); - *left_over = wastage; + mgmt_size = slab_mgmt_size(nr_objs, align); + } + *num = nr_objs; + *left_over = slab_size - nr_objs*buffer_size - mgmt_size; } #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg) -static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg) +static void __slab_error(const char *function, struct kmem_cache *cachep, char *msg) { printk(KERN_ERR "slab error in %s(): cache `%s': %s\n", function, cachep->name, msg); @@ -772,7 +829,9 @@ static struct array_cache *alloc_arraycache(int node, int entries, } #ifdef CONFIG_NUMA -static inline struct array_cache **alloc_alien_cache(int node, int limit) +static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int); + +static struct array_cache **alloc_alien_cache(int node, int limit) { struct array_cache **ac_ptr; int memsize = sizeof(void *) * MAX_NUMNODES; @@ -799,7 +858,7 @@ static inline struct array_cache **alloc_alien_cache(int node, int limit) return ac_ptr; } -static inline void free_alien_cache(struct array_cache **ac_ptr) +static void free_alien_cache(struct array_cache **ac_ptr) { int i; @@ -812,8 +871,8 @@ static inline void free_alien_cache(struct array_cache **ac_ptr) kfree(ac_ptr); } -static inline void __drain_alien_cache(kmem_cache_t *cachep, - struct array_cache *ac, int node) +static void __drain_alien_cache(struct kmem_cache *cachep, + struct array_cache *ac, int node) { struct kmem_list3 *rl3 = cachep->nodelists[node]; @@ -825,14 +884,14 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep, } } -static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3) +static void drain_alien_cache(struct kmem_cache *cachep, struct array_cache **alien) { int i = 0; struct array_cache *ac; unsigned long flags; for_each_online_node(i) { - ac = l3->alien[i]; + ac = alien[i]; if (ac) { spin_lock_irqsave(&ac->lock, flags); __drain_alien_cache(cachep, ac, i); @@ -841,23 +900,32 @@ static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3) } } #else -#define alloc_alien_cache(node, limit) do { } while (0) -#define free_alien_cache(ac_ptr) do { } while (0) -#define drain_alien_cache(cachep, l3) do { } while (0) + +#define drain_alien_cache(cachep, alien) do { } while (0) + +static inline struct array_cache **alloc_alien_cache(int node, int limit) +{ + return (struct array_cache **) 0x01020304ul; +} + +static inline void free_alien_cache(struct array_cache **ac_ptr) +{ +} + #endif static int __devinit cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; - kmem_cache_t *cachep; + struct kmem_cache *cachep; struct kmem_list3 *l3 = NULL; int node = cpu_to_node(cpu); int memsize = sizeof(struct kmem_list3); switch (action) { case CPU_UP_PREPARE: - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); /* we need to do this right in the beginning since * alloc_arraycache's are going to use this list. * kmalloc_node allows us to add the slab to the right @@ -877,6 +945,11 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, l3->next_reap = jiffies + REAPTIMEOUT_LIST3 + ((unsigned long)cachep) % REAPTIMEOUT_LIST3; + /* + * The l3s don't come and go as CPUs come and + * go. cache_chain_mutex is sufficient + * protection here. + */ cachep->nodelists[node] = l3; } @@ -891,53 +964,82 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, & array cache's */ list_for_each_entry(cachep, &cache_chain, next) { struct array_cache *nc; + struct array_cache *shared; + struct array_cache **alien; nc = alloc_arraycache(node, cachep->limit, - cachep->batchcount); + cachep->batchcount); if (!nc) goto bad; + shared = alloc_arraycache(node, + cachep->shared * cachep->batchcount, + 0xbaadf00d); + if (!shared) + goto bad; + + alien = alloc_alien_cache(node, cachep->limit); + if (!alien) + goto bad; cachep->array[cpu] = nc; l3 = cachep->nodelists[node]; BUG_ON(!l3); - if (!l3->shared) { - if (!(nc = alloc_arraycache(node, - cachep->shared * - cachep->batchcount, - 0xbaadf00d))) - goto bad; - /* we are serialised from CPU_DEAD or - CPU_UP_CANCELLED by the cpucontrol lock */ - l3->shared = nc; + spin_lock_irq(&l3->list_lock); + if (!l3->shared) { + /* + * We are serialised from CPU_DEAD or + * CPU_UP_CANCELLED by the cpucontrol lock + */ + l3->shared = shared; + shared = NULL; + } +#ifdef CONFIG_NUMA + if (!l3->alien) { + l3->alien = alien; + alien = NULL; } +#endif + spin_unlock_irq(&l3->list_lock); + + kfree(shared); + free_alien_cache(alien); } - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); break; case CPU_ONLINE: start_cpu_timer(cpu); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: + /* + * Even if all the cpus of a node are down, we don't free the + * kmem_list3 of any cache. This to avoid a race between + * cpu_down, and a kmalloc allocation from another cpu for + * memory from the node of the cpu going down. The list3 + * structure is usually allocated from kmem_cache_create() and + * gets destroyed at kmem_cache_destroy(). + */ /* fall thru */ case CPU_UP_CANCELED: - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); list_for_each_entry(cachep, &cache_chain, next) { struct array_cache *nc; + struct array_cache *shared; + struct array_cache **alien; cpumask_t mask; mask = node_to_cpumask(node); - spin_lock_irq(&cachep->spinlock); /* cpu is dead; no one can alloc from it. */ nc = cachep->array[cpu]; cachep->array[cpu] = NULL; l3 = cachep->nodelists[node]; if (!l3) - goto unlock_cache; + goto free_array_cache; - spin_lock(&l3->list_lock); + spin_lock_irq(&l3->list_lock); /* Free limit for this kmem_list3 */ l3->free_limit -= cachep->batchcount; @@ -945,41 +1047,51 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, free_block(cachep, nc->entry, nc->avail, node); if (!cpus_empty(mask)) { - spin_unlock(&l3->list_lock); - goto unlock_cache; + spin_unlock_irq(&l3->list_lock); + goto free_array_cache; } - if (l3->shared) { + shared = l3->shared; + if (shared) { free_block(cachep, l3->shared->entry, l3->shared->avail, node); - kfree(l3->shared); l3->shared = NULL; } - if (l3->alien) { - drain_alien_cache(cachep, l3); - free_alien_cache(l3->alien); - l3->alien = NULL; - } - /* free slabs belonging to this node */ - if (__node_shrink(cachep, node)) { - cachep->nodelists[node] = NULL; - spin_unlock(&l3->list_lock); - kfree(l3); - } else { - spin_unlock(&l3->list_lock); + alien = l3->alien; + l3->alien = NULL; + + spin_unlock_irq(&l3->list_lock); + + kfree(shared); + if (alien) { + drain_alien_cache(cachep, alien); + free_alien_cache(alien); } - unlock_cache: - spin_unlock_irq(&cachep->spinlock); +free_array_cache: kfree(nc); } - up(&cache_chain_sem); + /* + * In the previous loop, all the objects were freed to + * the respective cache's slabs, now we can go ahead and + * shrink each nodelist to its limit. + */ + list_for_each_entry(cachep, &cache_chain, next) { + l3 = cachep->nodelists[node]; + if (!l3) + continue; + spin_lock_irq(&l3->list_lock); + /* free slabs belonging to this node */ + __node_shrink(cachep, node); + spin_unlock_irq(&l3->list_lock); + } + mutex_unlock(&cache_chain_mutex); break; #endif } return NOTIFY_OK; bad: - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); return NOTIFY_BAD; } @@ -988,7 +1100,7 @@ static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 }; /* * swap the static kmem_list3 with kmalloced memory */ -static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list, int nodeid) +static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list, int nodeid) { struct kmem_list3 *ptr; @@ -1028,14 +1140,14 @@ void __init kmem_cache_init(void) /* Bootstrap is tricky, because several objects are allocated * from caches that do not exist yet: - * 1) initialize the cache_cache cache: it contains the kmem_cache_t + * 1) initialize the cache_cache cache: it contains the struct kmem_cache * structures of all caches, except cache_cache itself: cache_cache * is statically allocated. * Initially an __init data area is used for the head array and the * kmem_list3 structures, it's replaced with a kmalloc allocated * array at the end of the bootstrap. * 2) Create the first kmalloc cache. - * The kmem_cache_t for the new cache is allocated normally. + * The struct kmem_cache for the new cache is allocated normally. * An __init data area is used for the head array. * 3) Create the remaining kmalloc caches, with minimally sized * head arrays. @@ -1047,22 +1159,20 @@ void __init kmem_cache_init(void) */ /* 1) create the cache_cache */ - init_MUTEX(&cache_chain_sem); INIT_LIST_HEAD(&cache_chain); list_add(&cache_cache.next, &cache_chain); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE]; - cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size()); + cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, cache_line_size()); - cache_estimate(0, cache_cache.objsize, cache_line_size(), 0, + cache_estimate(0, cache_cache.buffer_size, cache_line_size(), 0, &left_over, &cache_cache.num); if (!cache_cache.num) BUG(); cache_cache.colour = left_over / cache_cache.colour_off; - cache_cache.colour_next = 0; cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + sizeof(struct slab), cache_line_size()); @@ -1129,8 +1239,8 @@ void __init kmem_cache_init(void) ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL); local_irq_disable(); - BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache); - memcpy(ptr, ac_data(&cache_cache), + BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache); + memcpy(ptr, cpu_cache_get(&cache_cache), sizeof(struct arraycache_init)); cache_cache.array[smp_processor_id()] = ptr; local_irq_enable(); @@ -1138,9 +1248,9 @@ void __init kmem_cache_init(void) ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL); local_irq_disable(); - BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep) + BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep) != &initarray_generic.cache); - memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep), + memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep), sizeof(struct arraycache_init)); malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] = ptr; @@ -1167,18 +1277,18 @@ void __init kmem_cache_init(void) /* 6) resize the head arrays to their final sizes */ { - kmem_cache_t *cachep; - down(&cache_chain_sem); + struct kmem_cache *cachep; + mutex_lock(&cache_chain_mutex); list_for_each_entry(cachep, &cache_chain, next) enable_cpucache(cachep); - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); } /* Done! */ g_cpucache_up = FULL; /* Register a cpu startup notifier callback - * that initializes ac_data for all new cpus + * that initializes cpu_cache_get for all new cpus */ register_cpu_notifier(&cpucache_notifier); @@ -1210,7 +1320,7 @@ __initcall(cpucache_init); * did not request dmaable memory, we might get it, but that * would be relatively rare and ignorable. */ -static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid) +static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) { struct page *page; void *addr; @@ -1236,7 +1346,7 @@ static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid) /* * Interface to system's page release. */ -static void kmem_freepages(kmem_cache_t *cachep, void *addr) +static void kmem_freepages(struct kmem_cache *cachep, void *addr) { unsigned long i = (1 << cachep->gfporder); struct page *page = virt_to_page(addr); @@ -1258,7 +1368,7 @@ static void kmem_freepages(kmem_cache_t *cachep, void *addr) static void kmem_rcu_free(struct rcu_head *head) { struct slab_rcu *slab_rcu = (struct slab_rcu *)head; - kmem_cache_t *cachep = slab_rcu->cachep; + struct kmem_cache *cachep = slab_rcu->cachep; kmem_freepages(cachep, slab_rcu->addr); if (OFF_SLAB(cachep)) @@ -1268,12 +1378,12 @@ static void kmem_rcu_free(struct rcu_head *head) #if DEBUG #ifdef CONFIG_DEBUG_PAGEALLOC -static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, +static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, unsigned long caller) { - int size = obj_reallen(cachep); + int size = obj_size(cachep); - addr = (unsigned long *)&((char *)addr)[obj_dbghead(cachep)]; + addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)]; if (size < 5 * sizeof(unsigned long)) return; @@ -1301,10 +1411,10 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, } #endif -static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val) +static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) { - int size = obj_reallen(cachep); - addr = &((char *)addr)[obj_dbghead(cachep)]; + int size = obj_size(cachep); + addr = &((char *)addr)[obj_offset(cachep)]; memset(addr, val, size); *(unsigned char *)(addr + size - 1) = POISON_END; @@ -1323,7 +1433,7 @@ static void dump_line(char *data, int offset, int limit) #if DEBUG -static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines) +static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines) { int i, size; char *realobj; @@ -1341,8 +1451,8 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines) (unsigned long)*dbg_userword(cachep, objp)); printk("\n"); } - realobj = (char *)objp + obj_dbghead(cachep); - size = obj_reallen(cachep); + realobj = (char *)objp + obj_offset(cachep); + size = obj_size(cachep); for (i = 0; i < size && lines; i += 16, lines--) { int limit; limit = 16; @@ -1352,14 +1462,14 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines) } } -static void check_poison_obj(kmem_cache_t *cachep, void *objp) +static void check_poison_obj(struct kmem_cache *cachep, void *objp) { char *realobj; int size, i; int lines = 0; - realobj = (char *)objp + obj_dbghead(cachep); - size = obj_reallen(cachep); + realobj = (char *)objp + obj_offset(cachep); + size = obj_size(cachep); for (i = 0; i < size; i++) { char exp = POISON_FREE; @@ -1392,20 +1502,20 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp) /* Print some data about the neighboring objects, if they * exist: */ - struct slab *slabp = page_get_slab(virt_to_page(objp)); + struct slab *slabp = virt_to_slab(objp); int objnr; - objnr = (objp - slabp->s_mem) / cachep->objsize; + objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; if (objnr) { - objp = slabp->s_mem + (objnr - 1) * cachep->objsize; - realobj = (char *)objp + obj_dbghead(cachep); + objp = slabp->s_mem + (objnr - 1) * cachep->buffer_size; + realobj = (char *)objp + obj_offset(cachep); printk(KERN_ERR "Prev obj: start=%p, len=%d\n", realobj, size); print_objinfo(cachep, objp, 2); } if (objnr + 1 < cachep->num) { - objp = slabp->s_mem + (objnr + 1) * cachep->objsize; - realobj = (char *)objp + obj_dbghead(cachep); + objp = slabp->s_mem + (objnr + 1) * cachep->buffer_size; + realobj = (char *)objp + obj_offset(cachep); printk(KERN_ERR "Next obj: start=%p, len=%d\n", realobj, size); print_objinfo(cachep, objp, 2); @@ -1414,25 +1524,23 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp) } #endif -/* Destroy all the objs in a slab, and release the mem back to the system. - * Before calling the slab must have been unlinked from the cache. - * The cache-lock is not held/needed. +#if DEBUG +/** + * slab_destroy_objs - call the registered destructor for each object in + * a slab that is to be destroyed. */ -static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp) +static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp) { - void *addr = slabp->s_mem - slabp->colouroff; - -#if DEBUG int i; for (i = 0; i < cachep->num; i++) { - void *objp = slabp->s_mem + cachep->objsize * i; + void *objp = slabp->s_mem + cachep->buffer_size * i; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->objsize % PAGE_SIZE) == 0 + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->objsize / PAGE_SIZE, + cachep->buffer_size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); @@ -1449,18 +1557,32 @@ static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp) "was overwritten"); } if (cachep->dtor && !(cachep->flags & SLAB_POISON)) - (cachep->dtor) (objp + obj_dbghead(cachep), cachep, 0); + (cachep->dtor) (objp + obj_offset(cachep), cachep, 0); } +} #else +static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp) +{ if (cachep->dtor) { int i; for (i = 0; i < cachep->num; i++) { - void *objp = slabp->s_mem + cachep->objsize * i; + void *objp = slabp->s_mem + cachep->buffer_size * i; (cachep->dtor) (objp, cachep, 0); } } +} #endif +/** + * Destroy all the objs in a slab, and release the mem back to the system. + * Before calling the slab must have been unlinked from the cache. + * The cache-lock is not held/needed. + */ +static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp) +{ + void *addr = slabp->s_mem - slabp->colouroff; + + slab_destroy_objs(cachep, slabp); if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) { struct slab_rcu *slab_rcu; @@ -1475,9 +1597,9 @@ static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp) } } -/* For setting up all the kmem_list3s for cache whose objsize is same +/* For setting up all the kmem_list3s for cache whose buffer_size is same as size of kmem_list3. */ -static inline void set_up_list3s(kmem_cache_t *cachep, int index) +static void set_up_list3s(struct kmem_cache *cachep, int index) { int node; @@ -1490,15 +1612,20 @@ static inline void set_up_list3s(kmem_cache_t *cachep, int index) } /** - * calculate_slab_order - calculate size (page order) of slabs and the number - * of objects per slab. + * calculate_slab_order - calculate size (page order) of slabs + * @cachep: pointer to the cache that is being created + * @size: size of objects to be created in this cache. + * @align: required alignment for the objects. + * @flags: slab allocation flags + * + * Also calculates the number of objects per slab. * * This could be made much more intelligent. For now, try to avoid using * high order pages for slabs. When the gfp() functions are more friendly * towards high-order requests, this should be changed. */ -static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size, - size_t align, gfp_t flags) +static inline size_t calculate_slab_order(struct kmem_cache *cachep, + size_t size, size_t align, unsigned long flags) { size_t left_over = 0; @@ -1569,13 +1696,13 @@ static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size, * cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -kmem_cache_t * +struct kmem_cache * kmem_cache_create (const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long), - void (*dtor)(void*, kmem_cache_t *, unsigned long)) + unsigned long flags, void (*ctor)(void*, struct kmem_cache *, unsigned long), + void (*dtor)(void*, struct kmem_cache *, unsigned long)) { size_t left_over, slab_size, ralign; - kmem_cache_t *cachep = NULL; + struct kmem_cache *cachep = NULL; struct list_head *p; /* @@ -1590,10 +1717,16 @@ kmem_cache_create (const char *name, size_t size, size_t align, BUG(); } - down(&cache_chain_sem); + /* + * Prevent CPUs from coming and going. + * lock_cpu_hotplug() nests outside cache_chain_mutex + */ + lock_cpu_hotplug(); + + mutex_lock(&cache_chain_mutex); list_for_each(p, &cache_chain) { - kmem_cache_t *pc = list_entry(p, kmem_cache_t, next); + struct kmem_cache *pc = list_entry(p, struct kmem_cache, next); mm_segment_t old_fs = get_fs(); char tmp; int res; @@ -1608,7 +1741,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, set_fs(old_fs); if (res) { printk("SLAB: cache with size %d has lost its name\n", - pc->objsize); + pc->buffer_size); continue; } @@ -1693,20 +1826,20 @@ kmem_cache_create (const char *name, size_t size, size_t align, align = ralign; /* Get cache's description obj. */ - cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL); + cachep = kmem_cache_alloc(&cache_cache, SLAB_KERNEL); if (!cachep) goto oops; - memset(cachep, 0, sizeof(kmem_cache_t)); + memset(cachep, 0, sizeof(struct kmem_cache)); #if DEBUG - cachep->reallen = size; + cachep->obj_size = size; if (flags & SLAB_RED_ZONE) { /* redzoning only works with word aligned caches */ align = BYTES_PER_WORD; /* add space for red zone words */ - cachep->dbghead += BYTES_PER_WORD; + cachep->obj_offset += BYTES_PER_WORD; size += 2 * BYTES_PER_WORD; } if (flags & SLAB_STORE_USER) { @@ -1719,8 +1852,8 @@ kmem_cache_create (const char *name, size_t size, size_t align, } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->reallen > cache_line_size() && size < PAGE_SIZE) { - cachep->dbghead += PAGE_SIZE - size; + && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) { + cachep->obj_offset += PAGE_SIZE - size; size = PAGE_SIZE; } #endif @@ -1783,7 +1916,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (flags & SLAB_CACHE_DMA) cachep->gfpflags |= GFP_DMA; spin_lock_init(&cachep->spinlock); - cachep->objsize = size; + cachep->buffer_size = size; if (flags & CFLGS_OFF_SLAB) cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u); @@ -1791,8 +1924,6 @@ kmem_cache_create (const char *name, size_t size, size_t align, cachep->dtor = dtor; cachep->name = name; - /* Don't let CPUs to come and go */ - lock_cpu_hotplug(); if (g_cpucache_up == FULL) { enable_cpucache(cachep); @@ -1840,23 +1971,23 @@ kmem_cache_create (const char *name, size_t size, size_t align, jiffies + REAPTIMEOUT_LIST3 + ((unsigned long)cachep) % REAPTIMEOUT_LIST3; - BUG_ON(!ac_data(cachep)); - ac_data(cachep)->avail = 0; - ac_data(cachep)->limit = BOOT_CPUCACHE_ENTRIES; - ac_data(cachep)->batchcount = 1; - ac_data(cachep)->touched = 0; + BUG_ON(!cpu_cache_get(cachep)); + cpu_cache_get(cachep)->avail = 0; + cpu_cache_get(cachep)->limit = BOOT_CPUCACHE_ENTRIES; + cpu_cache_get(cachep)->batchcount = 1; + cpu_cache_get(cachep)->touched = 0; cachep->batchcount = 1; cachep->limit = BOOT_CPUCACHE_ENTRIES; } /* cache setup completed, link it into the list */ list_add(&cachep->next, &cache_chain); - unlock_cpu_hotplug(); oops: if (!cachep && (flags & SLAB_PANIC)) panic("kmem_cache_create(): failed to create slab `%s'\n", name); - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); + unlock_cpu_hotplug(); return cachep; } EXPORT_SYMBOL(kmem_cache_create); @@ -1872,7 +2003,7 @@ static void check_irq_on(void) BUG_ON(irqs_disabled()); } -static void check_spinlock_acquired(kmem_cache_t *cachep) +static void check_spinlock_acquired(struct kmem_cache *cachep) { #ifdef CONFIG_SMP check_irq_off(); @@ -1880,7 +2011,7 @@ static void check_spinlock_acquired(kmem_cache_t *cachep) #endif } -static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node) +static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node) { #ifdef CONFIG_SMP check_irq_off(); @@ -1913,45 +2044,43 @@ static void smp_call_function_all_cpus(void (*func)(void *arg), void *arg) preempt_enable(); } -static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac, +static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac, int force, int node); static void do_drain(void *arg) { - kmem_cache_t *cachep = (kmem_cache_t *) arg; + struct kmem_cache *cachep = (struct kmem_cache *) arg; struct array_cache *ac; int node = numa_node_id(); check_irq_off(); - ac = ac_data(cachep); + ac = cpu_cache_get(cachep); spin_lock(&cachep->nodelists[node]->list_lock); free_block(cachep, ac->entry, ac->avail, node); spin_unlock(&cachep->nodelists[node]->list_lock); ac->avail = 0; } -static void drain_cpu_caches(kmem_cache_t *cachep) +static void drain_cpu_caches(struct kmem_cache *cachep) { struct kmem_list3 *l3; int node; smp_call_function_all_cpus(do_drain, cachep); check_irq_on(); - spin_lock_irq(&cachep->spinlock); for_each_online_node(node) { l3 = cachep->nodelists[node]; if (l3) { - spin_lock(&l3->list_lock); + spin_lock_irq(&l3->list_lock); drain_array_locked(cachep, l3->shared, 1, node); - spin_unlock(&l3->list_lock); + spin_unlock_irq(&l3->list_lock); if (l3->alien) - drain_alien_cache(cachep, l3); + drain_alien_cache(cachep, l3->alien); } } - spin_unlock_irq(&cachep->spinlock); } -static int __node_shrink(kmem_cache_t *cachep, int node) +static int __node_shrink(struct kmem_cache *cachep, int node) { struct slab *slabp; struct kmem_list3 *l3 = cachep->nodelists[node]; @@ -1980,7 +2109,7 @@ static int __node_shrink(kmem_cache_t *cachep, int node) return ret; } -static int __cache_shrink(kmem_cache_t *cachep) +static int __cache_shrink(struct kmem_cache *cachep) { int ret = 0, i = 0; struct kmem_list3 *l3; @@ -2006,7 +2135,7 @@ static int __cache_shrink(kmem_cache_t *cachep) * Releases as many slabs as possible for a cache. * To help debugging, a zero exit status indicates all slabs were released. */ -int kmem_cache_shrink(kmem_cache_t *cachep) +int kmem_cache_shrink(struct kmem_cache *cachep) { if (!cachep || in_interrupt()) BUG(); @@ -2019,7 +2148,7 @@ EXPORT_SYMBOL(kmem_cache_shrink); * kmem_cache_destroy - delete a cache * @cachep: the cache to destroy * - * Remove a kmem_cache_t object from the slab cache. + * Remove a struct kmem_cache object from the slab cache. * Returns 0 on success. * * It is expected this function will be called by a module when it is @@ -2032,7 +2161,7 @@ EXPORT_SYMBOL(kmem_cache_shrink); * The caller must guarantee that noone will allocate memory from the cache * during the kmem_cache_destroy(). */ -int kmem_cache_destroy(kmem_cache_t *cachep) +int kmem_cache_destroy(struct kmem_cache *cachep) { int i; struct kmem_list3 *l3; @@ -2044,18 +2173,18 @@ int kmem_cache_destroy(kmem_cache_t *cachep) lock_cpu_hotplug(); /* Find the cache in the chain of caches. */ - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); /* * the chain is never empty, cache_cache is never destroyed */ list_del(&cachep->next); - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); if (__cache_shrink(cachep)) { slab_error(cachep, "Can't free all objects"); - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); list_add(&cachep->next, &cache_chain); - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); unlock_cpu_hotplug(); return 1; } @@ -2083,7 +2212,7 @@ int kmem_cache_destroy(kmem_cache_t *cachep) EXPORT_SYMBOL(kmem_cache_destroy); /* Get the memory for a slab management obj. */ -static struct slab *alloc_slabmgmt(kmem_cache_t *cachep, void *objp, +static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp, int colour_off, gfp_t local_flags) { struct slab *slabp; @@ -2109,13 +2238,13 @@ static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp) return (kmem_bufctl_t *) (slabp + 1); } -static void cache_init_objs(kmem_cache_t *cachep, +static void cache_init_objs(struct kmem_cache *cachep, struct slab *slabp, unsigned long ctor_flags) { int i; for (i = 0; i < cachep->num; i++) { - void *objp = slabp->s_mem + cachep->objsize * i; + void *objp = slabp->s_mem + cachep->buffer_size * i; #if DEBUG /* need to poison the objs? */ if (cachep->flags & SLAB_POISON) @@ -2133,7 +2262,7 @@ static void cache_init_objs(kmem_cache_t *cachep, * Otherwise, deadlock. They must also be threaded. */ if (cachep->ctor && !(cachep->flags & SLAB_POISON)) - cachep->ctor(objp + obj_dbghead(cachep), cachep, + cachep->ctor(objp + obj_offset(cachep), cachep, ctor_flags); if (cachep->flags & SLAB_RED_ZONE) { @@ -2144,10 +2273,10 @@ static void cache_init_objs(kmem_cache_t *cachep, slab_error(cachep, "constructor overwrote the" " start of an object"); } - if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) kernel_map_pages(virt_to_page(objp), - cachep->objsize / PAGE_SIZE, 0); + cachep->buffer_size / PAGE_SIZE, 0); #else if (cachep->ctor) cachep->ctor(objp, cachep, ctor_flags); @@ -2158,7 +2287,7 @@ static void cache_init_objs(kmem_cache_t *cachep, slabp->free = 0; } -static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags) +static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) { if (flags & SLAB_DMA) { if (!(cachep->gfpflags & GFP_DMA)) @@ -2169,7 +2298,43 @@ static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags) } } -static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) +static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp, int nodeid) +{ + void *objp = slabp->s_mem + (slabp->free * cachep->buffer_size); + kmem_bufctl_t next; + + slabp->inuse++; + next = slab_bufctl(slabp)[slabp->free]; +#if DEBUG + slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE; + WARN_ON(slabp->nodeid != nodeid); +#endif + slabp->free = next; + + return objp; +} + +static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp, void *objp, + int nodeid) +{ + unsigned int objnr = (unsigned)(objp-slabp->s_mem) / cachep->buffer_size; + +#if DEBUG + /* Verify that the slab belongs to the intended node */ + WARN_ON(slabp->nodeid != nodeid); + + if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) { + printk(KERN_ERR "slab: double free detected in cache " + "'%s', objp %p\n", cachep->name, objp); + BUG(); + } +#endif + slab_bufctl(slabp)[objnr] = slabp->free; + slabp->free = objnr; + slabp->inuse--; +} + +static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp, void *objp) { int i; struct page *page; @@ -2188,7 +2353,7 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid) +static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) { struct slab *slabp; void *objp; @@ -2214,20 +2379,20 @@ static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid) */ ctor_flags |= SLAB_CTOR_ATOMIC; - /* About to mess with non-constant members - lock. */ + /* Take the l3 list lock to change the colour_next on this node */ check_irq_off(); - spin_lock(&cachep->spinlock); + l3 = cachep->nodelists[nodeid]; + spin_lock(&l3->list_lock); /* Get colour for the slab, and cal the next value. */ - offset = cachep->colour_next; - cachep->colour_next++; - if (cachep->colour_next >= cachep->colour) - cachep->colour_next = 0; - offset *= cachep->colour_off; + offset = l3->colour_next; + l3->colour_next++; + if (l3->colour_next >= cachep->colour) + l3->colour_next = 0; + spin_unlock(&l3->list_lock); - spin_unlock(&cachep->spinlock); + offset *= cachep->colour_off; - check_irq_off(); if (local_flags & __GFP_WAIT) local_irq_enable(); @@ -2257,7 +2422,6 @@ static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid) if (local_flags & __GFP_WAIT) local_irq_disable(); check_irq_off(); - l3 = cachep->nodelists[nodeid]; spin_lock(&l3->list_lock); /* Make slab active. */ @@ -2299,14 +2463,14 @@ static void kfree_debugcheck(const void *objp) } } -static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, +static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, void *caller) { struct page *page; unsigned int objnr; struct slab *slabp; - objp -= obj_dbghead(cachep); + objp -= obj_offset(cachep); kfree_debugcheck(objp); page = virt_to_page(objp); @@ -2338,31 +2502,31 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, if (cachep->flags & SLAB_STORE_USER) *dbg_userword(cachep, objp) = caller; - objnr = (objp - slabp->s_mem) / cachep->objsize; + objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; BUG_ON(objnr >= cachep->num); - BUG_ON(objp != slabp->s_mem + objnr * cachep->objsize); + BUG_ON(objp != slabp->s_mem + objnr * cachep->buffer_size); if (cachep->flags & SLAB_DEBUG_INITIAL) { /* Need to call the slab's constructor so the * caller can perform a verify of its state (debugging). * Called without the cache-lock held. */ - cachep->ctor(objp + obj_dbghead(cachep), + cachep->ctor(objp + obj_offset(cachep), cachep, SLAB_CTOR_CONSTRUCTOR | SLAB_CTOR_VERIFY); } if (cachep->flags & SLAB_POISON && cachep->dtor) { /* we want to cache poison the object, * call the destruction callback */ - cachep->dtor(objp + obj_dbghead(cachep), cachep, 0); + cachep->dtor(objp + obj_offset(cachep), cachep, 0); } if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) { + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) { store_stackinfo(cachep, objp, (unsigned long)caller); kernel_map_pages(virt_to_page(objp), - cachep->objsize / PAGE_SIZE, 0); + cachep->buffer_size / PAGE_SIZE, 0); } else { poison_obj(cachep, objp, POISON_FREE); } @@ -2373,7 +2537,7 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, return objp; } -static void check_slabp(kmem_cache_t *cachep, struct slab *slabp) +static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) { kmem_bufctl_t i; int entries = 0; @@ -2406,14 +2570,14 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp) #define check_slabp(x,y) do { } while(0) #endif -static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags) +static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; struct kmem_list3 *l3; struct array_cache *ac; check_irq_off(); - ac = ac_data(cachep); + ac = cpu_cache_get(cachep); retry: batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -2458,22 +2622,12 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags) check_slabp(cachep, slabp); check_spinlock_acquired(cachep); while (slabp->inuse < cachep->num && batchcount--) { - kmem_bufctl_t next; STATS_INC_ALLOCED(cachep); STATS_INC_ACTIVE(cachep); STATS_SET_HIGH(cachep); - /* get obj pointer */ - ac->entry[ac->avail++] = slabp->s_mem + - slabp->free * cachep->objsize; - - slabp->inuse++; - next = slab_bufctl(slabp)[slabp->free]; -#if DEBUG - slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE; - WARN_ON(numa_node_id() != slabp->nodeid); -#endif - slabp->free = next; + ac->entry[ac->avail++] = slab_get_obj(cachep, slabp, + numa_node_id()); } check_slabp(cachep, slabp); @@ -2495,7 +2649,7 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags) x = cache_grow(cachep, flags, numa_node_id()); // cache_grow can reenable interrupts, then ac could change. - ac = ac_data(cachep); + ac = cpu_cache_get(cachep); if (!x && ac->avail == 0) // no objects in sight? abort return NULL; @@ -2507,7 +2661,7 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags) } static inline void -cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags) +cache_alloc_debugcheck_before(struct kmem_cache *cachep, gfp_t flags) { might_sleep_if(flags & __GFP_WAIT); #if DEBUG @@ -2516,16 +2670,16 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags) } #if DEBUG -static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags, +static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, gfp_t flags, void *objp, void *caller) { if (!objp) return objp; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->objsize / PAGE_SIZE, 1); + cachep->buffer_size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -2550,7 +2704,7 @@ static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags, *dbg_redzone1(cachep, objp) = RED_ACTIVE; *dbg_redzone2(cachep, objp) = RED_ACTIVE; } - objp += obj_dbghead(cachep); + objp += obj_offset(cachep); if (cachep->ctor && cachep->flags & SLAB_POISON) { unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR; @@ -2565,13 +2719,22 @@ static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags, #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) #endif -static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags) +static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; +#ifdef CONFIG_NUMA + if (unlikely(current->mempolicy && !in_interrupt())) { + int nid = slab_node(current->mempolicy); + + if (nid != numa_node_id()) + return __cache_alloc_node(cachep, flags, nid); + } +#endif + check_irq_off(); - ac = ac_data(cachep); + ac = cpu_cache_get(cachep); if (likely(ac->avail)) { STATS_INC_ALLOCHIT(cachep); ac->touched = 1; @@ -2583,7 +2746,8 @@ static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags) return objp; } -static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags) +static __always_inline void * +__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) { unsigned long save_flags; void *objp; @@ -2594,7 +2758,7 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags) objp = ____cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, - __builtin_return_address(0)); + caller); prefetchw(objp); return objp; } @@ -2603,19 +2767,19 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags) /* * A interface to enable slab creation on nodeid */ -static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid) +static void *__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) { struct list_head *entry; struct slab *slabp; struct kmem_list3 *l3; void *obj; - kmem_bufctl_t next; int x; l3 = cachep->nodelists[nodeid]; BUG_ON(!l3); retry: + check_irq_off(); spin_lock(&l3->list_lock); entry = l3->slabs_partial.next; if (entry == &l3->slabs_partial) { @@ -2635,14 +2799,7 @@ static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid) BUG_ON(slabp->inuse == cachep->num); - /* get obj pointer */ - obj = slabp->s_mem + slabp->free * cachep->objsize; - slabp->inuse++; - next = slab_bufctl(slabp)[slabp->free]; -#if DEBUG - slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE; -#endif - slabp->free = next; + obj = slab_get_obj(cachep, slabp, nodeid); check_slabp(cachep, slabp); l3->free_objects--; /* move slabp to correct slabp list: */ @@ -2673,7 +2830,7 @@ static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid) /* * Caller needs to acquire correct kmem_list's list_lock */ -static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, +static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects, int node) { int i; @@ -2682,29 +2839,14 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, for (i = 0; i < nr_objects; i++) { void *objp = objpp[i]; struct slab *slabp; - unsigned int objnr; - slabp = page_get_slab(virt_to_page(objp)); + slabp = virt_to_slab(objp); l3 = cachep->nodelists[node]; list_del(&slabp->list); - objnr = (objp - slabp->s_mem) / cachep->objsize; check_spinlock_acquired_node(cachep, node); check_slabp(cachep, slabp); - -#if DEBUG - /* Verify that the slab belongs to the intended node */ - WARN_ON(slabp->nodeid != node); - - if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) { - printk(KERN_ERR "slab: double free detected in cache " - "'%s', objp %p\n", cachep->name, objp); - BUG(); - } -#endif - slab_bufctl(slabp)[objnr] = slabp->free; - slabp->free = objnr; + slab_put_obj(cachep, slabp, objp, node); STATS_DEC_ACTIVE(cachep); - slabp->inuse--; l3->free_objects++; check_slabp(cachep, slabp); @@ -2726,7 +2868,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, } } -static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac) +static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) { int batchcount; struct kmem_list3 *l3; @@ -2785,9 +2927,9 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac) * * Called with disabled ints. */ -static inline void __cache_free(kmem_cache_t *cachep, void *objp) +static inline void __cache_free(struct kmem_cache *cachep, void *objp) { - struct array_cache *ac = ac_data(cachep); + struct array_cache *ac = cpu_cache_get(cachep); check_irq_off(); objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0)); @@ -2798,7 +2940,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) #ifdef CONFIG_NUMA { struct slab *slabp; - slabp = page_get_slab(virt_to_page(objp)); + slabp = virt_to_slab(objp); if (unlikely(slabp->nodeid != numa_node_id())) { struct array_cache *alien = NULL; int nodeid = slabp->nodeid; @@ -2844,9 +2986,9 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) * Allocate an object from this cache. The flags are only relevant * if the cache has no available objects. */ -void *kmem_cache_alloc(kmem_cache_t *cachep, gfp_t flags) +void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - return __cache_alloc(cachep, flags); + return __cache_alloc(cachep, flags, __builtin_return_address(0)); } EXPORT_SYMBOL(kmem_cache_alloc); @@ -2864,12 +3006,12 @@ EXPORT_SYMBOL(kmem_cache_alloc); * * Currently only used for dentry validation. */ -int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr) +int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr) { unsigned long addr = (unsigned long)ptr; unsigned long min_addr = PAGE_OFFSET; unsigned long align_mask = BYTES_PER_WORD - 1; - unsigned long size = cachep->objsize; + unsigned long size = cachep->buffer_size; struct page *page; if (unlikely(addr < min_addr)) @@ -2905,32 +3047,23 @@ int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr) * New and improved: it will now make sure that the object gets * put on the correct node list so that there is no false sharing. */ -void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid) +void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) { unsigned long save_flags; void *ptr; - if (nodeid == -1) - return __cache_alloc(cachep, flags); - - if (unlikely(!cachep->nodelists[nodeid])) { - /* Fall back to __cache_alloc if we run into trouble */ - printk(KERN_WARNING - "slab: not allocating in inactive node %d for cache %s\n", - nodeid, cachep->name); - return __cache_alloc(cachep, flags); - } - cache_alloc_debugcheck_before(cachep, flags); local_irq_save(save_flags); - if (nodeid == numa_node_id()) + + if (nodeid == -1 || nodeid == numa_node_id() || + !cachep->nodelists[nodeid]) ptr = ____cache_alloc(cachep, flags); else ptr = __cache_alloc_node(cachep, flags, nodeid); local_irq_restore(save_flags); - ptr = - cache_alloc_debugcheck_after(cachep, flags, ptr, - __builtin_return_address(0)); + + ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, + __builtin_return_address(0)); return ptr; } @@ -2938,7 +3071,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node); void *kmalloc_node(size_t size, gfp_t flags, int node) { - kmem_cache_t *cachep; + struct kmem_cache *cachep; cachep = kmem_find_general_cachep(size, flags); if (unlikely(cachep == NULL)) @@ -2969,9 +3102,10 @@ EXPORT_SYMBOL(kmalloc_node); * platforms. For example, on i386, it means that the memory must come * from the first 16MB. */ -void *__kmalloc(size_t size, gfp_t flags) +static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, + void *caller) { - kmem_cache_t *cachep; + struct kmem_cache *cachep; /* If you want to save a few bytes .text space: replace * __ with kmem_. @@ -2981,10 +3115,27 @@ void *__kmalloc(size_t size, gfp_t flags) cachep = __find_general_cachep(size, flags); if (unlikely(cachep == NULL)) return NULL; - return __cache_alloc(cachep, flags); + return __cache_alloc(cachep, flags, caller); +} + +#ifndef CONFIG_DEBUG_SLAB + +void *__kmalloc(size_t size, gfp_t flags) +{ + return __do_kmalloc(size, flags, NULL); } EXPORT_SYMBOL(__kmalloc); +#else + +void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller) +{ + return __do_kmalloc(size, flags, caller); +} +EXPORT_SYMBOL(__kmalloc_track_caller); + +#endif + #ifdef CONFIG_SMP /** * __alloc_percpu - allocate one copy of the object for every present @@ -3042,7 +3193,7 @@ EXPORT_SYMBOL(__alloc_percpu); * Free an object which was previously allocated from this * cache. */ -void kmem_cache_free(kmem_cache_t *cachep, void *objp) +void kmem_cache_free(struct kmem_cache *cachep, void *objp) { unsigned long flags; @@ -3063,15 +3214,15 @@ EXPORT_SYMBOL(kmem_cache_free); */ void kfree(const void *objp) { - kmem_cache_t *c; + struct kmem_cache *c; unsigned long flags; if (unlikely(!objp)) return; local_irq_save(flags); kfree_debugcheck(objp); - c = page_get_cache(virt_to_page(objp)); - mutex_debug_check_no_locks_freed(objp, obj_reallen(c)); + c = virt_to_cache(objp); + mutex_debug_check_no_locks_freed(objp, obj_size(c)); __cache_free(c, (void *)objp); local_irq_restore(flags); } @@ -3100,13 +3251,13 @@ void free_percpu(const void *objp) EXPORT_SYMBOL(free_percpu); #endif -unsigned int kmem_cache_size(kmem_cache_t *cachep) +unsigned int kmem_cache_size(struct kmem_cache *cachep) { - return obj_reallen(cachep); + return obj_size(cachep); } EXPORT_SYMBOL(kmem_cache_size); -const char *kmem_cache_name(kmem_cache_t *cachep) +const char *kmem_cache_name(struct kmem_cache *cachep) { return cachep->name; } @@ -3115,7 +3266,7 @@ EXPORT_SYMBOL_GPL(kmem_cache_name); /* * This initializes kmem_list3 for all nodes. */ -static int alloc_kmemlist(kmem_cache_t *cachep) +static int alloc_kmemlist(struct kmem_cache *cachep) { int node; struct kmem_list3 *l3; @@ -3171,7 +3322,7 @@ static int alloc_kmemlist(kmem_cache_t *cachep) } struct ccupdate_struct { - kmem_cache_t *cachep; + struct kmem_cache *cachep; struct array_cache *new[NR_CPUS]; }; @@ -3181,13 +3332,13 @@ static void do_ccupdate_local(void *info) struct array_cache *old; check_irq_off(); - old = ac_data(new->cachep); + old = cpu_cache_get(new->cachep); new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()]; new->new[smp_processor_id()] = old; } -static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount, +static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared) { struct ccupdate_struct new; @@ -3208,11 +3359,11 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount, smp_call_function_all_cpus(do_ccupdate_local, (void *)&new); check_irq_on(); - spin_lock_irq(&cachep->spinlock); + spin_lock(&cachep->spinlock); cachep->batchcount = batchcount; cachep->limit = limit; cachep->shared = shared; - spin_unlock_irq(&cachep->spinlock); + spin_unlock(&cachep->spinlock); for_each_online_cpu(i) { struct array_cache *ccold = new.new[i]; @@ -3233,7 +3384,7 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount, return 0; } -static void enable_cpucache(kmem_cache_t *cachep) +static void enable_cpucache(struct kmem_cache *cachep) { int err; int limit, shared; @@ -3246,13 +3397,13 @@ static void enable_cpucache(kmem_cache_t *cachep) * The numbers are guessed, we should auto-tune as described by * Bonwick. */ - if (cachep->objsize > 131072) + if (cachep->buffer_size > 131072) limit = 1; - else if (cachep->objsize > PAGE_SIZE) + else if (cachep->buffer_size > PAGE_SIZE) limit = 8; - else if (cachep->objsize > 1024) + else if (cachep->buffer_size > 1024) limit = 24; - else if (cachep->objsize > 256) + else if (cachep->buffer_size > 256) limit = 54; else limit = 120; @@ -3267,7 +3418,7 @@ static void enable_cpucache(kmem_cache_t *cachep) */ shared = 0; #ifdef CONFIG_SMP - if (cachep->objsize <= PAGE_SIZE) + if (cachep->buffer_size <= PAGE_SIZE) shared = 8; #endif @@ -3285,7 +3436,7 @@ static void enable_cpucache(kmem_cache_t *cachep) cachep->name, -err); } -static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac, +static void drain_array_locked(struct kmem_cache *cachep, struct array_cache *ac, int force, int node) { int tofree; @@ -3314,7 +3465,7 @@ static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac, * - clear the per-cpu caches for this CPU. * - return freeable pages to the main free memory pool. * - * If we cannot acquire the cache chain semaphore then just give up - we'll + * If we cannot acquire the cache chain mutex then just give up - we'll * try again on the next iteration. */ static void cache_reap(void *unused) @@ -3322,7 +3473,7 @@ static void cache_reap(void *unused) struct list_head *walk; struct kmem_list3 *l3; - if (down_trylock(&cache_chain_sem)) { + if (!mutex_trylock(&cache_chain_mutex)) { /* Give up. Setup the next iteration. */ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); @@ -3330,12 +3481,12 @@ static void cache_reap(void *unused) } list_for_each(walk, &cache_chain) { - kmem_cache_t *searchp; + struct kmem_cache *searchp; struct list_head *p; int tofree; struct slab *slabp; - searchp = list_entry(walk, kmem_cache_t, next); + searchp = list_entry(walk, struct kmem_cache, next); if (searchp->flags & SLAB_NO_REAP) goto next; @@ -3344,10 +3495,10 @@ static void cache_reap(void *unused) l3 = searchp->nodelists[numa_node_id()]; if (l3->alien) - drain_alien_cache(searchp, l3); + drain_alien_cache(searchp, l3->alien); spin_lock_irq(&l3->list_lock); - drain_array_locked(searchp, ac_data(searchp), 0, + drain_array_locked(searchp, cpu_cache_get(searchp), 0, numa_node_id()); if (time_after(l3->next_reap, jiffies)) @@ -3393,7 +3544,7 @@ static void cache_reap(void *unused) cond_resched(); } check_irq_on(); - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); drain_remote_pages(); /* Setup the next iteration */ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); @@ -3429,7 +3580,7 @@ static void *s_start(struct seq_file *m, loff_t *pos) loff_t n = *pos; struct list_head *p; - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); if (!n) print_slabinfo_header(m); p = cache_chain.next; @@ -3438,25 +3589,25 @@ static void *s_start(struct seq_file *m, loff_t *pos) if (p == &cache_chain) return NULL; } - return list_entry(p, kmem_cache_t, next); + return list_entry(p, struct kmem_cache, next); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { - kmem_cache_t *cachep = p; + struct kmem_cache *cachep = p; ++*pos; return cachep->next.next == &cache_chain ? NULL - : list_entry(cachep->next.next, kmem_cache_t, next); + : list_entry(cachep->next.next, struct kmem_cache, next); } static void s_stop(struct seq_file *m, void *p) { - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); } static int s_show(struct seq_file *m, void *p) { - kmem_cache_t *cachep = p; + struct kmem_cache *cachep = p; struct list_head *q; struct slab *slabp; unsigned long active_objs; @@ -3468,8 +3619,7 @@ static int s_show(struct seq_file *m, void *p) int node; struct kmem_list3 *l3; - check_irq_on(); - spin_lock_irq(&cachep->spinlock); + spin_lock(&cachep->spinlock); active_objs = 0; num_slabs = 0; for_each_online_node(node) { @@ -3477,7 +3627,8 @@ static int s_show(struct seq_file *m, void *p) if (!l3) continue; - spin_lock(&l3->list_lock); + check_irq_on(); + spin_lock_irq(&l3->list_lock); list_for_each(q, &l3->slabs_full) { slabp = list_entry(q, struct slab, list); @@ -3502,9 +3653,10 @@ static int s_show(struct seq_file *m, void *p) num_slabs++; } free_objects += l3->free_objects; - shared_avail += l3->shared->avail; + if (l3->shared) + shared_avail += l3->shared->avail; - spin_unlock(&l3->list_lock); + spin_unlock_irq(&l3->list_lock); } num_slabs += active_slabs; num_objs = num_slabs * cachep->num; @@ -3516,7 +3668,7 @@ static int s_show(struct seq_file *m, void *p) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", - name, active_objs, num_objs, cachep->objsize, + name, active_objs, num_objs, cachep->buffer_size, cachep->num, (1 << cachep->gfporder)); seq_printf(m, " : tunables %4u %4u %4u", cachep->limit, cachep->batchcount, cachep->shared); @@ -3548,7 +3700,7 @@ static int s_show(struct seq_file *m, void *p) } #endif seq_putc(m, '\n'); - spin_unlock_irq(&cachep->spinlock); + spin_unlock(&cachep->spinlock); return 0; } @@ -3603,10 +3755,11 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer, return -EINVAL; /* Find the cache in the chain of caches. */ - down(&cache_chain_sem); + mutex_lock(&cache_chain_mutex); res = -EINVAL; list_for_each(p, &cache_chain) { - kmem_cache_t *cachep = list_entry(p, kmem_cache_t, next); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, + next); if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || @@ -3620,7 +3773,7 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer, break; } } - up(&cache_chain_sem); + mutex_unlock(&cache_chain_mutex); if (res >= 0) res = count; return res; @@ -3644,5 +3797,5 @@ unsigned int ksize(const void *objp) if (unlikely(objp == NULL)) return 0; - return obj_reallen(page_get_cache(virt_to_page(objp))); + return obj_size(virt_to_cache(objp)); } diff --git a/mm/slob.c b/mm/slob.c index 1c240c4b71d9..a1f42bdc0245 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -336,7 +336,7 @@ EXPORT_SYMBOL(slab_reclaim_pages); #ifdef CONFIG_SMP -void *__alloc_percpu(size_t size, size_t align) +void *__alloc_percpu(size_t size) { int i; struct percpu_data *pdata = kmalloc(sizeof (*pdata), GFP_KERNEL); diff --git a/mm/swap.c b/mm/swap.c index cbb48e721ab9..76247424dea1 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -34,19 +34,22 @@ /* How many pages do we try to swap or page in/out together? */ int page_cluster; -void put_page(struct page *page) +static void put_compound_page(struct page *page) { - if (unlikely(PageCompound(page))) { - page = (struct page *)page_private(page); - if (put_page_testzero(page)) { - void (*dtor)(struct page *page); + page = (struct page *)page_private(page); + if (put_page_testzero(page)) { + void (*dtor)(struct page *page); - dtor = (void (*)(struct page *))page[1].mapping; - (*dtor)(page); - } - return; + dtor = (void (*)(struct page *))page[1].mapping; + (*dtor)(page); } - if (put_page_testzero(page)) +} + +void put_page(struct page *page) +{ + if (unlikely(PageCompound(page))) + put_compound_page(page); + else if (put_page_testzero(page)) __page_cache_release(page); } EXPORT_SYMBOL(put_page); @@ -174,6 +177,32 @@ void lru_add_drain(void) put_cpu(); } +#ifdef CONFIG_NUMA +static void lru_add_drain_per_cpu(void *dummy) +{ + lru_add_drain(); +} + +/* + * Returns 0 for success + */ +int lru_add_drain_all(void) +{ + return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL); +} + +#else + +/* + * Returns 0 for success + */ +int lru_add_drain_all(void) +{ + lru_add_drain(); + return 0; +} +#endif + /* * This path almost never happens for VM activity - pages are normally * freed via pagevecs. But it gets used by networking. @@ -218,6 +247,15 @@ void release_pages(struct page **pages, int nr, int cold) struct page *page = pages[i]; struct zone *pagezone; + if (unlikely(PageCompound(page))) { + if (zone) { + spin_unlock_irq(&zone->lru_lock); + zone = NULL; + } + put_compound_page(page); + continue; + } + if (!put_page_testzero(page)) continue; diff --git a/mm/swap_state.c b/mm/swap_state.c index 7b09ac503fec..db8a3d3e1636 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -27,6 +27,7 @@ static struct address_space_operations swap_aops = { .writepage = swap_writepage, .sync_page = block_sync_page, .set_page_dirty = __set_page_dirty_nobuffers, + .migratepage = migrate_page, }; static struct backing_dev_info swap_backing_dev_info = { diff --git a/mm/swapfile.c b/mm/swapfile.c index 957fef43fa60..1f9cf0d073b8 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -25,6 +25,7 @@ #include <linux/rmap.h> #include <linux/security.h> #include <linux/backing-dev.h> +#include <linux/mutex.h> #include <linux/capability.h> #include <linux/syscalls.h> @@ -46,12 +47,12 @@ struct swap_list_t swap_list = {-1, -1}; struct swap_info_struct swap_info[MAX_SWAPFILES]; -static DECLARE_MUTEX(swapon_sem); +static DEFINE_MUTEX(swapon_mutex); /* * We need this because the bdev->unplug_fn can sleep and we cannot * hold swap_lock while calling the unplug_fn. And swap_lock - * cannot be turned into a semaphore. + * cannot be turned into a mutex. */ static DECLARE_RWSEM(swap_unplug_sem); @@ -553,6 +554,15 @@ static int unuse_mm(struct mm_struct *mm, return 0; } +#ifdef CONFIG_MIGRATION +int remove_vma_swap(struct vm_area_struct *vma, struct page *page) +{ + swp_entry_t entry = { .val = page_private(page) }; + + return unuse_vma(vma, entry, page); +} +#endif + /* * Scan swap_map from current position to next entry still in use. * Recycle to start on reaching the end, returning 0 when empty. @@ -645,6 +655,7 @@ static int try_to_unuse(unsigned int type) */ swap_map = &si->swap_map[i]; entry = swp_entry(type, i); +again: page = read_swap_cache_async(entry, NULL, 0); if (!page) { /* @@ -679,6 +690,12 @@ static int try_to_unuse(unsigned int type) wait_on_page_locked(page); wait_on_page_writeback(page); lock_page(page); + if (!PageSwapCache(page)) { + /* Page migration has occured */ + unlock_page(page); + page_cache_release(page); + goto again; + } wait_on_page_writeback(page); /* @@ -1161,7 +1178,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile) up_write(&swap_unplug_sem); destroy_swap_extents(p); - down(&swapon_sem); + mutex_lock(&swapon_mutex); spin_lock(&swap_lock); drain_mmlist(); @@ -1180,7 +1197,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile) p->swap_map = NULL; p->flags = 0; spin_unlock(&swap_lock); - up(&swapon_sem); + mutex_unlock(&swapon_mutex); vfree(swap_map); inode = mapping->host; if (S_ISBLK(inode->i_mode)) { @@ -1209,7 +1226,7 @@ static void *swap_start(struct seq_file *swap, loff_t *pos) int i; loff_t l = *pos; - down(&swapon_sem); + mutex_lock(&swapon_mutex); for (i = 0; i < nr_swapfiles; i++, ptr++) { if (!(ptr->flags & SWP_USED) || !ptr->swap_map) @@ -1238,7 +1255,7 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) static void swap_stop(struct seq_file *swap, void *v) { - up(&swapon_sem); + mutex_unlock(&swapon_mutex); } static int swap_show(struct seq_file *swap, void *v) @@ -1540,7 +1557,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) goto bad_swap; } - down(&swapon_sem); + mutex_lock(&swapon_mutex); spin_lock(&swap_lock); p->flags = SWP_ACTIVE; nr_swap_pages += nr_good_pages; @@ -1566,7 +1583,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) swap_info[prev].next = p - swap_info; } spin_unlock(&swap_lock); - up(&swapon_sem); + mutex_unlock(&swapon_mutex); error = 0; goto out; bad_swap: diff --git a/mm/vmscan.c b/mm/vmscan.c index bf903b2d198f..1838c15ca4fd 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -71,6 +71,9 @@ struct scan_control { int may_writepage; + /* Can pages be swapped as part of reclaim? */ + int may_swap; + /* This context's SWAP_CLUSTER_MAX. If freeing memory for * suspend, we effectively ignore SWAP_CLUSTER_MAX. * In this context, it doesn't matter that we scan the @@ -440,6 +443,10 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) BUG_ON(PageActive(page)); sc->nr_scanned++; + + if (!sc->may_swap && page_mapped(page)) + goto keep_locked; + /* Double the slab pressure for mapped and swapcache pages */ if (page_mapped(page) || PageSwapCache(page)) sc->nr_scanned++; @@ -458,6 +465,8 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) * Try to allocate it some swap space here. */ if (PageAnon(page) && !PageSwapCache(page)) { + if (!sc->may_swap) + goto keep_locked; if (!add_to_swap(page, GFP_ATOMIC)) goto activate_locked; } @@ -472,7 +481,13 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) * processes. Try to unmap it here. */ if (page_mapped(page) && mapping) { - switch (try_to_unmap(page)) { + /* + * No unmapping if we do not swap + */ + if (!sc->may_swap) + goto keep_locked; + + switch (try_to_unmap(page, 0)) { case SWAP_FAIL: goto activate_locked; case SWAP_AGAIN: @@ -487,7 +502,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) goto keep_locked; if (!may_enter_fs) goto keep_locked; - if (laptop_mode && !sc->may_writepage) + if (!sc->may_writepage) goto keep_locked; /* Page is dirty, try to write it out here */ @@ -586,7 +601,7 @@ static inline void move_to_lru(struct page *page) } /* - * Add isolated pages on the list back to the LRU + * Add isolated pages on the list back to the LRU. * * returns the number of pages put back. */ @@ -604,6 +619,15 @@ int putback_lru_pages(struct list_head *l) } /* + * Non migratable page + */ +int fail_migrate_page(struct page *newpage, struct page *page) +{ + return -EIO; +} +EXPORT_SYMBOL(fail_migrate_page); + +/* * swapout a single page * page is locked upon entry, unlocked on exit */ @@ -612,7 +636,7 @@ static int swap_page(struct page *page) struct address_space *mapping = page_mapping(page); if (page_mapped(page) && mapping) - if (try_to_unmap(page) != SWAP_SUCCESS) + if (try_to_unmap(page, 1) != SWAP_SUCCESS) goto unlock_retry; if (PageDirty(page)) { @@ -648,6 +672,167 @@ unlock_retry: retry: return -EAGAIN; } +EXPORT_SYMBOL(swap_page); + +/* + * Page migration was first developed in the context of the memory hotplug + * project. The main authors of the migration code are: + * + * IWAMOTO Toshihiro <iwamoto@valinux.co.jp> + * Hirokazu Takahashi <taka@valinux.co.jp> + * Dave Hansen <haveblue@us.ibm.com> + * Christoph Lameter <clameter@sgi.com> + */ + +/* + * Remove references for a page and establish the new page with the correct + * basic settings to be able to stop accesses to the page. + */ +int migrate_page_remove_references(struct page *newpage, + struct page *page, int nr_refs) +{ + struct address_space *mapping = page_mapping(page); + struct page **radix_pointer; + + /* + * Avoid doing any of the following work if the page count + * indicates that the page is in use or truncate has removed + * the page. + */ + if (!mapping || page_mapcount(page) + nr_refs != page_count(page)) + return 1; + + /* + * Establish swap ptes for anonymous pages or destroy pte + * maps for files. + * + * In order to reestablish file backed mappings the fault handlers + * will take the radix tree_lock which may then be used to stop + * processses from accessing this page until the new page is ready. + * + * A process accessing via a swap pte (an anonymous page) will take a + * page_lock on the old page which will block the process until the + * migration attempt is complete. At that time the PageSwapCache bit + * will be examined. If the page was migrated then the PageSwapCache + * bit will be clear and the operation to retrieve the page will be + * retried which will find the new page in the radix tree. Then a new + * direct mapping may be generated based on the radix tree contents. + * + * If the page was not migrated then the PageSwapCache bit + * is still set and the operation may continue. + */ + try_to_unmap(page, 1); + + /* + * Give up if we were unable to remove all mappings. + */ + if (page_mapcount(page)) + return 1; + + write_lock_irq(&mapping->tree_lock); + + radix_pointer = (struct page **)radix_tree_lookup_slot( + &mapping->page_tree, + page_index(page)); + + if (!page_mapping(page) || page_count(page) != nr_refs || + *radix_pointer != page) { + write_unlock_irq(&mapping->tree_lock); + return 1; + } + + /* + * Now we know that no one else is looking at the page. + * + * Certain minimal information about a page must be available + * in order for other subsystems to properly handle the page if they + * find it through the radix tree update before we are finished + * copying the page. + */ + get_page(newpage); + newpage->index = page->index; + newpage->mapping = page->mapping; + if (PageSwapCache(page)) { + SetPageSwapCache(newpage); + set_page_private(newpage, page_private(page)); + } + + *radix_pointer = newpage; + __put_page(page); + write_unlock_irq(&mapping->tree_lock); + + return 0; +} +EXPORT_SYMBOL(migrate_page_remove_references); + +/* + * Copy the page to its new location + */ +void migrate_page_copy(struct page *newpage, struct page *page) +{ + copy_highpage(newpage, page); + + if (PageError(page)) + SetPageError(newpage); + if (PageReferenced(page)) + SetPageReferenced(newpage); + if (PageUptodate(page)) + SetPageUptodate(newpage); + if (PageActive(page)) + SetPageActive(newpage); + if (PageChecked(page)) + SetPageChecked(newpage); + if (PageMappedToDisk(page)) + SetPageMappedToDisk(newpage); + + if (PageDirty(page)) { + clear_page_dirty_for_io(page); + set_page_dirty(newpage); + } + + ClearPageSwapCache(page); + ClearPageActive(page); + ClearPagePrivate(page); + set_page_private(page, 0); + page->mapping = NULL; + + /* + * If any waiters have accumulated on the new page then + * wake them up. + */ + if (PageWriteback(newpage)) + end_page_writeback(newpage); +} +EXPORT_SYMBOL(migrate_page_copy); + +/* + * Common logic to directly migrate a single page suitable for + * pages that do not use PagePrivate. + * + * Pages are locked upon entry and exit. + */ +int migrate_page(struct page *newpage, struct page *page) +{ + BUG_ON(PageWriteback(page)); /* Writeback must be complete */ + + if (migrate_page_remove_references(newpage, page, 2)) + return -EAGAIN; + + migrate_page_copy(newpage, page); + + /* + * Remove auxiliary swap entries and replace + * them with real ptes. + * + * Note that a real pte entry will allow processes that are not + * waiting on the page lock to use the new page via the page tables + * before the new page is unlocked. + */ + remove_from_swap(newpage); + return 0; +} +EXPORT_SYMBOL(migrate_page); + /* * migrate_pages * @@ -658,14 +843,9 @@ retry: * pages are swapped out. * * The function returns after 10 attempts or if no pages - * are movable anymore because t has become empty + * are movable anymore because to has become empty * or no retryable pages exist anymore. * - * SIMPLIFIED VERSION: This implementation of migrate_pages - * is only swapping out pages and never touches the second - * list. The direct migration patchset - * extends this function to avoid the use of swap. - * * Return: Number of pages not migrated when "to" ran empty. */ int migrate_pages(struct list_head *from, struct list_head *to, @@ -686,6 +866,9 @@ redo: retry = 0; list_for_each_entry_safe(page, page2, from, lru) { + struct page *newpage = NULL; + struct address_space *mapping; + cond_resched(); rc = 0; @@ -693,6 +876,9 @@ redo: /* page was freed from under us. So we are done. */ goto next; + if (to && list_empty(to)) + break; + /* * Skip locked pages during the first two passes to give the * functions holding the lock time to release the page. Later we @@ -729,12 +915,84 @@ redo: } } + if (!to) { + rc = swap_page(page); + goto next; + } + + newpage = lru_to_page(to); + lock_page(newpage); + /* - * Page is properly locked and writeback is complete. + * Pages are properly locked and writeback is complete. * Try to migrate the page. */ - rc = swap_page(page); - goto next; + mapping = page_mapping(page); + if (!mapping) + goto unlock_both; + + if (mapping->a_ops->migratepage) { + /* + * Most pages have a mapping and most filesystems + * should provide a migration function. Anonymous + * pages are part of swap space which also has its + * own migration function. This is the most common + * path for page migration. + */ + rc = mapping->a_ops->migratepage(newpage, page); + goto unlock_both; + } + + /* + * Default handling if a filesystem does not provide + * a migration function. We can only migrate clean + * pages so try to write out any dirty pages first. + */ + if (PageDirty(page)) { + switch (pageout(page, mapping)) { + case PAGE_KEEP: + case PAGE_ACTIVATE: + goto unlock_both; + + case PAGE_SUCCESS: + unlock_page(newpage); + goto next; + + case PAGE_CLEAN: + ; /* try to migrate the page below */ + } + } + + /* + * Buffers are managed in a filesystem specific way. + * We must have no buffers or drop them. + */ + if (!page_has_buffers(page) || + try_to_release_page(page, GFP_KERNEL)) { + rc = migrate_page(newpage, page); + goto unlock_both; + } + + /* + * On early passes with mapped pages simply + * retry. There may be a lock held for some + * buffers that may go away. Later + * swap them out. + */ + if (pass > 4) { + /* + * Persistently unable to drop buffers..... As a + * measure of last resort we fall back to + * swap_page(). + */ + unlock_page(newpage); + newpage = NULL; + rc = swap_page(page); + goto next; + } + +unlock_both: + unlock_page(newpage); unlock_page: unlock_page(page); @@ -747,7 +1005,10 @@ next: list_move(&page->lru, failed); nr_failed++; } else { - /* Success */ + if (newpage) { + /* Successful migration. Return page to LRU */ + move_to_lru(newpage); + } list_move(&page->lru, moved); } } @@ -760,46 +1021,33 @@ next: return nr_failed + retry; } -static void lru_add_drain_per_cpu(void *dummy) -{ - lru_add_drain(); -} - /* * Isolate one page from the LRU lists and put it on the - * indicated list. Do necessary cache draining if the - * page is not on the LRU lists yet. + * indicated list with elevated refcount. * * Result: * 0 = page not on LRU list * 1 = page removed from LRU list and added to the specified list. - * -ENOENT = page is being freed elsewhere. */ int isolate_lru_page(struct page *page) { - int rc = 0; - struct zone *zone = page_zone(page); + int ret = 0; -redo: - spin_lock_irq(&zone->lru_lock); - rc = __isolate_lru_page(page); - if (rc == 1) { - if (PageActive(page)) - del_page_from_active_list(zone, page); - else - del_page_from_inactive_list(zone, page); - } - spin_unlock_irq(&zone->lru_lock); - if (rc == 0) { - /* - * Maybe this page is still waiting for a cpu to drain it - * from one of the lru lists? - */ - rc = schedule_on_each_cpu(lru_add_drain_per_cpu, NULL); - if (rc == 0 && PageLRU(page)) - goto redo; + if (PageLRU(page)) { + struct zone *zone = page_zone(page); + spin_lock_irq(&zone->lru_lock); + if (TestClearPageLRU(page)) { + ret = 1; + get_page(page); + if (PageActive(page)) + del_page_from_active_list(zone, page); + else + del_page_from_inactive_list(zone, page); + } + spin_unlock_irq(&zone->lru_lock); } - return rc; + + return ret; } #endif @@ -831,18 +1079,20 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src, page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); - switch (__isolate_lru_page(page)) { - case 1: - /* Succeeded to isolate page */ - list_move(&page->lru, dst); - nr_taken++; - break; - case -ENOENT: - /* Not possible to isolate */ - list_move(&page->lru, src); - break; - default: + if (!TestClearPageLRU(page)) BUG(); + list_del(&page->lru); + if (get_page_testone(page)) { + /* + * It is being freed elsewhere + */ + __put_page(page); + SetPageLRU(page); + list_add(&page->lru, src); + continue; + } else { + list_add(&page->lru, dst); + nr_taken++; } } @@ -945,9 +1195,47 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) struct page *page; struct pagevec pvec; int reclaim_mapped = 0; - long mapped_ratio; - long distress; - long swap_tendency; + + if (unlikely(sc->may_swap)) { + long mapped_ratio; + long distress; + long swap_tendency; + + /* + * `distress' is a measure of how much trouble we're having + * reclaiming pages. 0 -> no problems. 100 -> great trouble. + */ + distress = 100 >> zone->prev_priority; + + /* + * The point of this algorithm is to decide when to start + * reclaiming mapped memory instead of just pagecache. Work out + * how much memory + * is mapped. + */ + mapped_ratio = (sc->nr_mapped * 100) / total_memory; + + /* + * Now decide how much we really want to unmap some pages. The + * mapped ratio is downgraded - just because there's a lot of + * mapped memory doesn't necessarily mean that page reclaim + * isn't succeeding. + * + * The distress ratio is important - we don't want to start + * going oom. + * + * A 100% value of vm_swappiness overrides this algorithm + * altogether. + */ + swap_tendency = mapped_ratio / 2 + distress + vm_swappiness; + + /* + * Now use this metric to decide whether to start moving mapped + * memory onto the inactive list. + */ + if (swap_tendency >= 100) + reclaim_mapped = 1; + } lru_add_drain(); spin_lock_irq(&zone->lru_lock); @@ -957,37 +1245,6 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) zone->nr_active -= pgmoved; spin_unlock_irq(&zone->lru_lock); - /* - * `distress' is a measure of how much trouble we're having reclaiming - * pages. 0 -> no problems. 100 -> great trouble. - */ - distress = 100 >> zone->prev_priority; - - /* - * The point of this algorithm is to decide when to start reclaiming - * mapped memory instead of just pagecache. Work out how much memory - * is mapped. - */ - mapped_ratio = (sc->nr_mapped * 100) / total_memory; - - /* - * Now decide how much we really want to unmap some pages. The mapped - * ratio is downgraded - just because there's a lot of mapped memory - * doesn't necessarily mean that page reclaim isn't succeeding. - * - * The distress ratio is important - we don't want to start going oom. - * - * A 100% value of vm_swappiness overrides this algorithm altogether. - */ - swap_tendency = mapped_ratio / 2 + distress + vm_swappiness; - - /* - * Now use this metric to decide whether to start moving mapped memory - * onto the inactive list. - */ - if (swap_tendency >= 100) - reclaim_mapped = 1; - while (!list_empty(&l_hold)) { cond_resched(); page = lru_to_page(&l_hold); @@ -1176,7 +1433,8 @@ int try_to_free_pages(struct zone **zones, gfp_t gfp_mask) int i; sc.gfp_mask = gfp_mask; - sc.may_writepage = 0; + sc.may_writepage = !laptop_mode; + sc.may_swap = 1; inc_page_state(allocstall); @@ -1278,7 +1536,8 @@ loop_again: total_scanned = 0; total_reclaimed = 0; sc.gfp_mask = GFP_KERNEL; - sc.may_writepage = 0; + sc.may_writepage = !laptop_mode; + sc.may_swap = 1; sc.nr_mapped = read_page_state(nr_mapped); inc_page_state(pageoutrun); @@ -1362,9 +1621,7 @@ scan: sc.nr_reclaimed = 0; sc.priority = priority; sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX; - atomic_inc(&zone->reclaim_in_progress); shrink_zone(zone, &sc); - atomic_dec(&zone->reclaim_in_progress); reclaim_state->reclaimed_slab = 0; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages); @@ -1576,3 +1833,115 @@ static int __init kswapd_init(void) } module_init(kswapd_init) + +#ifdef CONFIG_NUMA +/* + * Zone reclaim mode + * + * If non-zero call zone_reclaim when the number of free pages falls below + * the watermarks. + * + * In the future we may add flags to the mode. However, the page allocator + * should only have to check that zone_reclaim_mode != 0 before calling + * zone_reclaim(). + */ +int zone_reclaim_mode __read_mostly; + +#define RECLAIM_OFF 0 +#define RECLAIM_ZONE (1<<0) /* Run shrink_cache on the zone */ +#define RECLAIM_WRITE (1<<1) /* Writeout pages during reclaim */ +#define RECLAIM_SWAP (1<<2) /* Swap pages out during reclaim */ +#define RECLAIM_SLAB (1<<3) /* Do a global slab shrink if the zone is out of memory */ + +/* + * Mininum time between zone reclaim scans + */ +int zone_reclaim_interval __read_mostly = 30*HZ; + +/* + * Priority for ZONE_RECLAIM. This determines the fraction of pages + * of a node considered for each zone_reclaim. 4 scans 1/16th of + * a zone. + */ +#define ZONE_RECLAIM_PRIORITY 4 + +/* + * Try to free up some pages from this zone through reclaim. + */ +int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) +{ + int nr_pages; + struct task_struct *p = current; + struct reclaim_state reclaim_state; + struct scan_control sc; + cpumask_t mask; + int node_id; + + if (time_before(jiffies, + zone->last_unsuccessful_zone_reclaim + zone_reclaim_interval)) + return 0; + + if (!(gfp_mask & __GFP_WAIT) || + zone->all_unreclaimable || + atomic_read(&zone->reclaim_in_progress) > 0) + return 0; + + node_id = zone->zone_pgdat->node_id; + mask = node_to_cpumask(node_id); + if (!cpus_empty(mask) && node_id != numa_node_id()) + return 0; + + sc.may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE); + sc.may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP); + sc.nr_scanned = 0; + sc.nr_reclaimed = 0; + sc.priority = ZONE_RECLAIM_PRIORITY + 1; + sc.nr_mapped = read_page_state(nr_mapped); + sc.gfp_mask = gfp_mask; + + disable_swap_token(); + + nr_pages = 1 << order; + if (nr_pages > SWAP_CLUSTER_MAX) + sc.swap_cluster_max = nr_pages; + else + sc.swap_cluster_max = SWAP_CLUSTER_MAX; + + cond_resched(); + p->flags |= PF_MEMALLOC; + reclaim_state.reclaimed_slab = 0; + p->reclaim_state = &reclaim_state; + + /* + * Free memory by calling shrink zone with increasing priorities + * until we have enough memory freed. + */ + do { + sc.priority--; + shrink_zone(zone, &sc); + + } while (sc.nr_reclaimed < nr_pages && sc.priority > 0); + + if (sc.nr_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) { + /* + * shrink_slab does not currently allow us to determine + * how many pages were freed in the zone. So we just + * shake the slab and then go offnode for a single allocation. + * + * shrink_slab will free memory on all zones and may take + * a long time. + */ + shrink_slab(sc.nr_scanned, gfp_mask, order); + sc.nr_reclaimed = 1; /* Avoid getting the off node timeout */ + } + + p->reclaim_state = NULL; + current->flags &= ~PF_MEMALLOC; + + if (sc.nr_reclaimed == 0) + zone->last_unsuccessful_zone_reclaim = jiffies; + + return sc.nr_reclaimed >= nr_pages; +} +#endif + diff --git a/net/802/p8023.c b/net/802/p8023.c index d23e906456eb..53cf05709283 100644 --- a/net/802/p8023.c +++ b/net/802/p8023.c @@ -59,3 +59,5 @@ void destroy_8023_client(struct datalink_proto *dl) EXPORT_SYMBOL(destroy_8023_client); EXPORT_SYMBOL(make_8023_client); + +MODULE_LICENSE("GPL"); diff --git a/net/802/psnap.c b/net/802/psnap.c index 4d638944d933..34e42968b477 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -59,8 +59,10 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, proto = find_snap_client(skb->h.raw); if (proto) { /* Pass the frame on. */ + u8 *hdr = skb->data; skb->h.raw += 5; skb_pull(skb, 5); + skb_postpull_rcsum(skb, hdr, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); } else { skb->sk = NULL; diff --git a/net/Kconfig b/net/Kconfig index 9296b269d675..5126f58d9c44 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -27,6 +27,13 @@ if NET menu "Networking options" +config NETDEBUG + bool "Network packet debugging" + help + You can say Y here if you want to get additional messages useful in + debugging bad packets, but can overwhelm logs under denial of service + attacks. + source "net/packet/Kconfig" source "net/unix/Kconfig" source "net/xfrm/Kconfig" @@ -150,6 +157,7 @@ endif source "net/dccp/Kconfig" source "net/sctp/Kconfig" +source "net/tipc/Kconfig" source "net/atm/Kconfig" source "net/bridge/Kconfig" source "net/8021q/Kconfig" @@ -159,7 +167,6 @@ source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" -source "net/tipc/Kconfig" config NET_DIVERT bool "Frame Diverter (EXPERIMENTAL)" diff --git a/net/atm/signaling.c b/net/atm/signaling.c index e7211a7f382c..93ad59a28ef5 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -56,7 +56,8 @@ static void sigd_put_skb(struct sk_buff *skb) remove_wait_queue(&sigd_sleep,&wait); #else if (!sigd) { - printk(KERN_WARNING "atmsvc: no signaling demon\n"); + if (net_ratelimit()) + printk(KERN_WARNING "atmsvc: no signaling demon\n"); kfree_skb(skb); return; } diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index bdb6458c6bd5..97bdec73d17e 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -143,13 +143,15 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) static int hci_sock_release(struct socket *sock) { struct sock *sk = sock->sk; - struct hci_dev *hdev = hci_pi(sk)->hdev; + struct hci_dev *hdev; BT_DBG("sock %p sk %p", sock, sk); if (!sk) return 0; + hdev = hci_pi(sk)->hdev; + bt_sock_unlink(&hci_sk_list, sk); if (hdev) { @@ -311,14 +313,18 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add { struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; struct sock *sk = sock->sk; + struct hci_dev *hdev = hci_pi(sk)->hdev; BT_DBG("sock %p sk %p", sock, sk); + if (!hdev) + return -EBADFD; + lock_sock(sk); *addr_len = sizeof(*haddr); haddr->hci_family = AF_BLUETOOTH; - haddr->hci_dev = hci_pi(sk)->hdev->id; + haddr->hci_dev = hdev->id; release_sock(sk); return 0; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 0d89d6434136..5b4253c61f62 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -46,13 +46,15 @@ #include <net/bluetooth/l2cap.h> #include <net/bluetooth/rfcomm.h> -#define VERSION "1.6" - #ifndef CONFIG_BT_RFCOMM_DEBUG #undef BT_DBG #define BT_DBG(D...) #endif +#define VERSION "1.7" + +static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; + static struct task_struct *rfcomm_thread; static DECLARE_MUTEX(rfcomm_sem); @@ -623,7 +625,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU; + l2cap_pi(sk)->imtu = l2cap_mtu; release_sock(sk); s = rfcomm_session_add(sock, BT_BOUND); @@ -1868,7 +1870,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = RFCOMM_MAX_L2CAP_MTU; + l2cap_pi(sk)->imtu = l2cap_mtu; release_sock(sk); /* Start listening on the socket */ @@ -2070,6 +2072,9 @@ static void __exit rfcomm_exit(void) module_init(rfcomm_init); module_exit(rfcomm_exit); +module_param(l2cap_mtu, uint, 0644); +MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); + MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION); MODULE_VERSION(VERSION); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index ba442883e877..7fa3a5a9971f 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -79,9 +79,14 @@ static int port_cost(struct net_device *dev) */ static void port_carrier_check(void *arg) { - struct net_bridge_port *p = arg; + struct net_device *dev = arg; + struct net_bridge_port *p; rtnl_lock(); + p = dev->br_port; + if (!p) + goto done; + if (netif_carrier_ok(p->dev)) { u32 cost = port_cost(p->dev); @@ -97,9 +102,24 @@ static void port_carrier_check(void *arg) br_stp_disable_port(p); spin_unlock_bh(&p->br->lock); } +done: rtnl_unlock(); } +static void release_nbp(struct kobject *kobj) +{ + struct net_bridge_port *p + = container_of(kobj, struct net_bridge_port, kobj); + kfree(p); +} + +static struct kobj_type brport_ktype = { +#ifdef CONFIG_SYSFS + .sysfs_ops = &brport_sysfs_ops, +#endif + .release = release_nbp, +}; + static void destroy_nbp(struct net_bridge_port *p) { struct net_device *dev = p->dev; @@ -108,7 +128,7 @@ static void destroy_nbp(struct net_bridge_port *p) p->dev = NULL; dev_put(dev); - br_sysfs_freeif(p); + kobject_put(&p->kobj); } static void destroy_nbp_rcu(struct rcu_head *head) @@ -118,17 +138,25 @@ static void destroy_nbp_rcu(struct rcu_head *head) destroy_nbp(p); } -/* called with RTNL */ +/* Delete port(interface) from bridge is done in two steps. + * via RCU. First step, marks device as down. That deletes + * all the timers and stops new packets from flowing through. + * + * Final cleanup doesn't occur until after all CPU's finished + * processing packets. + * + * Protected from multiple admin operations by RTNL mutex + */ static void del_nbp(struct net_bridge_port *p) { struct net_bridge *br = p->br; struct net_device *dev = p->dev; - dev->br_port = NULL; + sysfs_remove_link(&br->ifobj, dev->name); + dev_set_promiscuity(dev, -1); cancel_delayed_work(&p->carrier_check); - flush_scheduled_work(); spin_lock_bh(&br->lock); br_stp_disable_port(p); @@ -138,10 +166,10 @@ static void del_nbp(struct net_bridge_port *p) list_del_rcu(&p->list); - del_timer_sync(&p->message_age_timer); - del_timer_sync(&p->forward_delay_timer); - del_timer_sync(&p->hold_timer); - + rcu_assign_pointer(dev->br_port, NULL); + + kobject_del(&p->kobj); + call_rcu(&p->rcu, destroy_nbp_rcu); } @@ -151,7 +179,6 @@ static void del_br(struct net_bridge *br) struct net_bridge_port *p, *n; list_for_each_entry_safe(p, n, &br->port_list, list) { - br_sysfs_removeif(p); del_nbp(p); } @@ -245,13 +272,17 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->dev = dev; p->path_cost = port_cost(dev); p->priority = 0x8000 >> BR_PORT_BITS; - dev->br_port = p; p->port_no = index; br_init_port(p); p->state = BR_STATE_DISABLED; - INIT_WORK(&p->carrier_check, port_carrier_check, p); + INIT_WORK(&p->carrier_check, port_carrier_check, dev); kobject_init(&p->kobj); + kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); + p->kobj.ktype = &brport_ktype; + p->kobj.parent = &(dev->class_dev.kobj); + p->kobj.kset = NULL; + return p; } @@ -379,30 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (dev->br_port != NULL) return -EBUSY; - if (IS_ERR(p = new_nbp(br, dev))) + p = new_nbp(br, dev); + if (IS_ERR(p)) return PTR_ERR(p); - if ((err = br_fdb_insert(br, p, dev->dev_addr))) - destroy_nbp(p); - - else if ((err = br_sysfs_addif(p))) - del_nbp(p); - else { - dev_set_promiscuity(dev, 1); + err = kobject_add(&p->kobj); + if (err) + goto err0; - list_add_rcu(&p->list, &br->port_list); + err = br_fdb_insert(br, p, dev->dev_addr); + if (err) + goto err1; - spin_lock_bh(&br->lock); - br_stp_recalculate_bridge_id(br); - br_features_recompute(br); - if ((br->dev->flags & IFF_UP) - && (dev->flags & IFF_UP) && netif_carrier_ok(dev)) - br_stp_enable_port(p); - spin_unlock_bh(&br->lock); + err = br_sysfs_addif(p); + if (err) + goto err2; - dev_set_mtu(br->dev, br_min_mtu(br)); - } + rcu_assign_pointer(dev->br_port, p); + dev_set_promiscuity(dev, 1); + + list_add_rcu(&p->list, &br->port_list); + + spin_lock_bh(&br->lock); + br_stp_recalculate_bridge_id(br); + br_features_recompute(br); + schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE); + spin_unlock_bh(&br->lock); + dev_set_mtu(br->dev, br_min_mtu(br)); + kobject_uevent(&p->kobj, KOBJ_ADD); + + return 0; +err2: + br_fdb_delete_by_port(br, p); +err1: + kobject_del(&p->kobj); +err0: + kobject_put(&p->kobj); return err; } @@ -414,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) if (!p || p->br != br) return -EINVAL; - br_sysfs_removeif(p); del_nbp(p); spin_lock_bh(&br->lock); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e3a73cead6b6..4eef83755315 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -45,18 +45,20 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) int br_handle_frame_finish(struct sk_buff *skb) { const unsigned char *dest = eth_hdr(skb)->h_dest; - struct net_bridge_port *p = skb->dev->br_port; - struct net_bridge *br = p->br; + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); + struct net_bridge *br; struct net_bridge_fdb_entry *dst; int passedup = 0; + if (!p || p->state == BR_STATE_DISABLED) + goto drop; + /* insert into forwarding database after filtering to avoid spoofing */ - br_fdb_update(p->br, p, eth_hdr(skb)->h_source); + br = p->br; + br_fdb_update(br, p, eth_hdr(skb)->h_source); - if (p->state == BR_STATE_LEARNING) { - kfree_skb(skb); - goto out; - } + if (p->state == BR_STATE_LEARNING) + goto drop; if (br->dev->flags & IFF_PROMISC) { struct sk_buff *skb2; @@ -93,6 +95,9 @@ int br_handle_frame_finish(struct sk_buff *skb) out: return 0; +drop: + kfree_skb(skb); + goto out; } /* diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 7cac3fb9f809..6bb0c7eb1ef0 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -51,9 +51,6 @@ #define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr) #define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr) -#define has_bridge_parent(device) ((device)->br_port != NULL) -#define bridge_parent(device) ((device)->br_port->br->dev) - #ifdef CONFIG_SYSCTL static struct ctl_table_header *brnf_sysctl_header; static int brnf_call_iptables = 1; @@ -98,6 +95,12 @@ static struct rtable __fake_rtable = { .rt_flags = 0, }; +static inline struct net_device *bridge_parent(const struct net_device *dev) +{ + struct net_bridge_port *port = rcu_dereference(dev->br_port); + + return port ? port->br->dev : NULL; +} /* PF_BRIDGE/PRE_ROUTING *********************************************/ /* Undo the changes made for ip6tables PREROUTING and continue the @@ -189,11 +192,15 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; skb->dev = bridge_parent(skb->dev); - if (skb->protocol == __constant_htons(ETH_P_8021Q)) { - skb_pull(skb, VLAN_HLEN); - skb->nh.raw += VLAN_HLEN; + if (!skb->dev) + kfree_skb(skb); + else { + if (skb->protocol == __constant_htons(ETH_P_8021Q)) { + skb_pull(skb, VLAN_HLEN); + skb->nh.raw += VLAN_HLEN; + } + skb->dst->output(skb); } - skb->dst->output(skb); return 0; } @@ -270,7 +277,7 @@ bridged_dnat: } /* Some common code for IPv4/IPv6 */ -static void setup_pre_routing(struct sk_buff *skb) +static struct net_device *setup_pre_routing(struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = skb->nf_bridge; @@ -282,6 +289,8 @@ static void setup_pre_routing(struct sk_buff *skb) nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; nf_bridge->physindev = skb->dev; skb->dev = bridge_parent(skb->dev); + + return skb->dev; } /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ @@ -376,7 +385,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, nf_bridge_put(skb->nf_bridge); if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) return NF_DROP; - setup_pre_routing(skb); + if (!setup_pre_routing(skb)) + return NF_DROP; NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, br_nf_pre_routing_finish_ipv6); @@ -465,7 +475,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, nf_bridge_put(skb->nf_bridge); if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) return NF_DROP; - setup_pre_routing(skb); + if (!setup_pre_routing(skb)) + return NF_DROP; store_orig_dstaddr(skb); NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, @@ -539,11 +550,16 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, struct sk_buff *skb = *pskb; struct nf_bridge_info *nf_bridge; struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); + struct net_device *parent; int pf; if (!skb->nf_bridge) return NF_ACCEPT; + parent = bridge_parent(out); + if (!parent) + return NF_DROP; + if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) pf = PF_INET; else @@ -564,8 +580,8 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, nf_bridge->mask |= BRNF_BRIDGED; nf_bridge->physoutdev = skb->dev; - NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), - bridge_parent(out), br_nf_forward_finish); + NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), parent, + br_nf_forward_finish); return NF_STOLEN; } @@ -688,6 +704,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, goto out; } realoutdev = bridge_parent(skb->dev); + if (!realoutdev) + return NF_DROP; #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) /* iptables should match -o br0.x */ @@ -701,9 +719,11 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, /* IP forwarded traffic has a physindev, locally * generated traffic hasn't. */ if (realindev != NULL) { - if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) && - has_bridge_parent(realindev)) - realindev = bridge_parent(realindev); + if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) { + struct net_device *parent = bridge_parent(realindev); + if (parent) + realindev = parent; + } NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev, realoutdev, br_nf_local_out_finish, @@ -743,6 +763,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, if (!nf_bridge) return NF_ACCEPT; + if (!realoutdev) + return NF_DROP; + if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) pf = PF_INET; else @@ -782,8 +805,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, print_error: if (skb->dev != NULL) { printk("[%s]", skb->dev->name); - if (has_bridge_parent(skb->dev)) - printk("[%s]", bridge_parent(skb->dev)->name); + if (realoutdev) + printk("[%s]", realoutdev->name); } printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, skb->data); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c5bd631ffcd5..8f10e09f251b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -232,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); #ifdef CONFIG_SYSFS /* br_sysfs_if.c */ +extern struct sysfs_ops brport_sysfs_ops; extern int br_sysfs_addif(struct net_bridge_port *p); -extern void br_sysfs_removeif(struct net_bridge_port *p); -extern void br_sysfs_freeif(struct net_bridge_port *p); /* br_sysfs_br.c */ extern int br_sysfs_addbr(struct net_device *dev); @@ -243,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev); #else #define br_sysfs_addif(p) (0) -#define br_sysfs_removeif(p) do { } while(0) -#define br_sysfs_freeif(p) kfree(p) #define br_sysfs_addbr(dev) (0) #define br_sysfs_delbr(dev) do { } while(0) #endif /* CONFIG_SYSFS */ diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index d071f1c9ad0b..296f6a487c52 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -133,29 +133,35 @@ void br_send_tcn_bpdu(struct net_bridge_port *p) static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; -/* NO locks */ +/* NO locks, but rcu_read_lock (preempt_disabled) */ int br_stp_handle_bpdu(struct sk_buff *skb) { - struct net_bridge_port *p = skb->dev->br_port; - struct net_bridge *br = p->br; + struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); + struct net_bridge *br; unsigned char *buf; + if (!p) + goto err; + + br = p->br; + spin_lock(&br->lock); + + if (p->state == BR_STATE_DISABLED || !(br->dev->flags & IFF_UP)) + goto out; + /* insert into forwarding database after filtering to avoid spoofing */ - br_fdb_update(p->br, p, eth_hdr(skb)->h_source); + br_fdb_update(br, p, eth_hdr(skb)->h_source); + + if (!br->stp_enabled) + goto out; /* need at least the 802 and STP headers */ if (!pskb_may_pull(skb, sizeof(header)+1) || memcmp(skb->data, header, sizeof(header))) - goto err; + goto out; buf = skb_pull(skb, sizeof(header)); - spin_lock_bh(&br->lock); - if (p->state == BR_STATE_DISABLED - || !(br->dev->flags & IFF_UP) - || !br->stp_enabled) - goto out; - if (buf[0] == BPDU_TYPE_CONFIG) { struct br_config_bpdu bpdu; @@ -201,7 +207,7 @@ int br_stp_handle_bpdu(struct sk_buff *skb) br_received_tcn_bpdu(p); } out: - spin_unlock_bh(&br->lock); + spin_unlock(&br->lock); err: kfree_skb(skb); return 0; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 0ac0355d16dd..c51c9e42aeb3 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj, return ret; } -/* called from kobject_put when port ref count goes to zero. */ -static void brport_release(struct kobject *kobj) -{ - kfree(container_of(kobj, struct net_bridge_port, kobj)); -} - -static struct sysfs_ops brport_sysfs_ops = { +struct sysfs_ops brport_sysfs_ops = { .show = brport_show, .store = brport_store, }; -static struct kobj_type brport_ktype = { - .sysfs_ops = &brport_sysfs_ops, - .release = brport_release, -}; - - /* * Add sysfs entries to ethernet device added to a bridge. * Creates a brport subdirectory with bridge attributes. @@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p) struct brport_attribute **a; int err; - ASSERT_RTNL(); - - kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); - p->kobj.ktype = &brport_ktype; - p->kobj.parent = &(p->dev->class_dev.kobj); - p->kobj.kset = NULL; - - err = kobject_add(&p->kobj); - if(err) - goto out1; - err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, SYSFS_BRIDGE_PORT_LINK); if (err) @@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p) goto out2; } - err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); - if (err) - goto out2; - - kobject_uevent(&p->kobj, KOBJ_ADD); - return 0; - out2: - kobject_del(&p->kobj); - out1: + err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); +out2: return err; } - -void br_sysfs_removeif(struct net_bridge_port *p) -{ - pr_debug("br_sysfs_removeif\n"); - sysfs_remove_link(&p->br->ifobj, p->dev->name); - kobject_uevent(&p->kobj, KOBJ_REMOVE); - kobject_del(&p->kobj); -} - -void br_sysfs_freeif(struct net_bridge_port *p) -{ - pr_debug("br_sysfs_freeif\n"); - kobject_put(&p->kobj); -} diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index ce617b3dbbb8..802baf755ef4 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -46,7 +46,7 @@ #define PRINTR(format, args...) do { if (net_ratelimit()) \ printk(format , ## args); } while (0) -static unsigned int nlbufsiz = 4096; +static unsigned int nlbufsiz = NLMSG_GOODSIZE; module_param(nlbufsiz, uint, 0600); MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " "(defaults to 4096)"); @@ -98,12 +98,14 @@ static void ulog_timer(unsigned long data) static struct sk_buff *ulog_alloc_skb(unsigned int size) { struct sk_buff *skb; + unsigned int n; - skb = alloc_skb(nlbufsiz, GFP_ATOMIC); + n = max(size, nlbufsiz); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " - "of size %ub!\n", nlbufsiz); - if (size < nlbufsiz) { + "of size %ub!\n", n); + if (n > size) { /* try to allocate only as much as we need for * current packet */ skb = alloc_skb(size, GFP_ATOMIC); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 00729b3604f8..cbd4020cc84d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -934,6 +934,13 @@ static int do_replace(void __user *user, unsigned int len) BUGPRINT("Entries_size never zero\n"); return -EINVAL; } + /* overflow check */ + if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + return -ENOMEM; + countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) diff --git a/net/core/datagram.c b/net/core/datagram.c index f8d322e1ea92..b8ce6bf81188 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -247,49 +247,74 @@ EXPORT_SYMBOL(skb_kill_datagram); int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, struct iovec *to, int len) { - int i, err, fraglen, end = 0; - struct sk_buff *next = skb_shinfo(skb)->frag_list; + int start = skb_headlen(skb); + int i, copy = start - offset; - if (!len) - return 0; + /* Copy header. */ + if (copy > 0) { + if (copy > len) + copy = len; + if (memcpy_toiovec(to, skb->data + offset, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + } -next_skb: - fraglen = skb_headlen(skb); - i = -1; + /* Copy paged appendix. Hmm... why does this look so complicated? */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; - while (1) { - int start = end; + BUG_TRAP(start <= offset + len); - if ((end += fraglen) > offset) { - int copy = end - offset, o = offset - start; + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + int err; + u8 *vaddr; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; if (copy > len) copy = len; - if (i == -1) - err = memcpy_toiovec(to, skb->data + o, copy); - else { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - struct page *page = frag->page; - void *p = kmap(page) + frag->page_offset + o; - err = memcpy_toiovec(to, p, copy); - kunmap(page); - } + vaddr = kmap(page); + err = memcpy_toiovec(to, vaddr + frag->page_offset + + offset - start, copy); + kunmap(page); if (err) goto fault; if (!(len -= copy)) return 0; offset += copy; } - if (++i >= skb_shinfo(skb)->nr_frags) - break; - fraglen = skb_shinfo(skb)->frags[i].size; + start = end; } - if (next) { - skb = next; - BUG_ON(skb_shinfo(skb)->frag_list); - next = skb->next; - goto next_skb; + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_iovec(list, + offset - start, + to, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + } + start = end; + } } + if (!len) + return 0; + fault: return -EFAULT; } diff --git a/net/core/dev.c b/net/core/dev.c index fd070a098f20..2afb0de95329 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2543,13 +2543,14 @@ int dev_ioctl(unsigned int cmd, void __user *arg) case SIOCBONDENSLAVE: case SIOCBONDRELEASE: case SIOCBONDSETHWADDR: - case SIOCBONDSLAVEINFOQUERY: - case SIOCBONDINFOQUERY: case SIOCBONDCHANGEACTIVE: case SIOCBRADDIF: case SIOCBRDELIF: if (!capable(CAP_NET_ADMIN)) return -EPERM; + /* fall through */ + case SIOCBONDSLAVEINFOQUERY: + case SIOCBONDINFOQUERY: dev_load(ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); @@ -3236,7 +3237,7 @@ static int __init net_dev_init(void) * Initialise the packet receive queues. */ - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); diff --git a/net/core/filter.c b/net/core/filter.c index 9540946a48f3..93fbd01d2259 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -64,7 +64,7 @@ static inline void *load_pointer(struct sk_buff *skb, int k, } /** - * sk_run_filter - run a filter on a socket + * sk_run_filter - run a filter on a socket * @skb: buffer to run the filter on * @filter: filter to apply * @flen: length of filter @@ -78,8 +78,8 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int { struct sock_filter *fentry; /* We walk down these */ void *ptr; - u32 A = 0; /* Accumulator */ - u32 X = 0; /* Index Register */ + u32 A = 0; /* Accumulator */ + u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ u32 tmp; int k; diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 3827f881f429..da16f8fd1494 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1860,13 +1860,14 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, */ mod_cur_headers(pkt_dev); - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC); + datalen = (odev->hard_header_len + 16) & ~0xf; + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } - skb_reserve(skb, 16); + skb_reserve(skb, datalen); /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 8700379685e0..eca2976abb25 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -455,7 +455,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) if (!skb) return; - if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) { + if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) { kfree_skb(skb); return; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d0732e9c8560..6766f118f070 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -135,13 +135,15 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone) { + kmem_cache_t *cache; struct skb_shared_info *shinfo; struct sk_buff *skb; u8 *data; + cache = fclone ? skbuff_fclone_cache : skbuff_head_cache; + /* Get the HEAD */ - skb = kmem_cache_alloc(fclone ? skbuff_fclone_cache : skbuff_head_cache, - gfp_mask & ~__GFP_DMA); + skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA); if (!skb) goto out; @@ -180,7 +182,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, out: return skb; nodata: - kmem_cache_free(skbuff_head_cache, skb); + kmem_cache_free(cache, skb); skb = NULL; goto out; } diff --git a/net/core/utils.c b/net/core/utils.c index ac1d1fcf8673..fdc4f38bc46c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -121,7 +121,7 @@ void __init net_random_init(void) { int i; - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, i+jiffies); } @@ -133,7 +133,7 @@ static int net_random_reseed(void) unsigned long seed[NR_CPUS]; get_random_bytes(seed, sizeof(seed)); - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, seed[i]); } diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index d2b5933b4510..add3cae65e2d 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c @@ -15,7 +15,6 @@ #include <linux/config.h> #include <linux/module.h> -#include <asm/bug.h> #include <asm/div64.h> #include "tfrc.h" diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 00f983226672..dc0487b5bace 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -119,7 +119,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err != 0) goto failure; - err = ip_route_newports(&rt, inet->sport, inet->dport, sk); + err = ip_route_newports(&rt, IPPROTO_DCCP, inet->sport, inet->dport, + sk); if (err != 0) goto failure; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index df074259f9c3..80c4d048869e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -468,6 +468,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, done: if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); + dst_release(dst); return err; } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 7a121802faa9..960aa78cdb97 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -350,6 +350,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, u8 src[ETH_ALEN]; struct ieee80211_crypt_data *crypt = NULL; int keyidx = 0; + int can_be_decrypted = 0; hdr = (struct ieee80211_hdr_4addr *)skb->data; stats = &ieee->stats; @@ -410,12 +411,23 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, return 1; } - if (is_multicast_ether_addr(hdr->addr1) - ? ieee->host_mc_decrypt : ieee->host_decrypt) { + can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) || + is_broadcast_ether_addr(hdr->addr2)) ? + ieee->host_mc_decrypt : ieee->host_decrypt; + + if (can_be_decrypted) { int idx = 0; - if (skb->len >= hdrlen + 3) + if (skb->len >= hdrlen + 3) { + /* Top two-bits of byte 3 are the key index */ idx = skb->data[hdrlen + 3] >> 6; + } + + /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx + * is only allowed 2-bits of storage, no value of idx can + * be provided via above code that would result in idx + * being out of range */ crypt = ieee->crypt[idx]; + #ifdef NOT_YET sta = NULL; @@ -553,7 +565,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && + if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) goto rx_dropped; @@ -617,7 +629,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possible reassembled) full MSDU payload; possibly still * encrypted/authenticated */ - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && + if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) goto rx_dropped; @@ -1439,7 +1451,7 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, break; case IEEE80211_STYPE_PROBE_REQ: - IEEE80211_DEBUG_MGMT("recieved auth (%d)\n", + IEEE80211_DEBUG_MGMT("received auth (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); @@ -1473,7 +1485,7 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, break; case IEEE80211_STYPE_AUTH: - IEEE80211_DEBUG_MGMT("recieved auth (%d)\n", + IEEE80211_DEBUG_MGMT("received auth (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 23e1630f50b7..f87c6b89f845 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -232,15 +232,18 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee, return start; } +#define SCAN_ITEM_SIZE 128 + int ieee80211_wx_get_scan(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct ieee80211_network *network; unsigned long flags; + int err = 0; char *ev = extra; - char *stop = ev + IW_SCAN_MAX_DATA; + char *stop = ev + wrqu->data.length; int i = 0; IEEE80211_DEBUG_WX("Getting scan\n"); @@ -249,6 +252,11 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, list_for_each_entry(network, &ieee->network_list, list) { i++; + if (stop - ev < SCAN_ITEM_SIZE) { + err = -E2BIG; + break; + } + if (ieee->scan_age == 0 || time_after(network->last_scanned + ieee->scan_age, jiffies)) ev = ipw2100_translate_scan(ieee, ev, stop, network); @@ -270,7 +278,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); - return 0; + return err; } int ieee80211_wx_set_encode(struct ieee80211_device *ieee, diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 95b9d81ac488..3ffa60dadc0c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa) if (!skb) netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); - else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { + else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { kfree_skb(skb); netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); } else { diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ef4724de7350..0f4145babb14 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, } nl->nlmsg_flags = NLM_F_REQUEST; - nl->nlmsg_pid = current->pid; + nl->nlmsg_pid = 0; nl->nlmsg_seq = 0; nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); if (cmd == SIOCDELRT) { diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 105039eb7629..e7bbff4340bb 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -192,7 +192,7 @@ int sysctl_icmp_echo_ignore_all; int sysctl_icmp_echo_ignore_broadcasts = 1; /* Control parameter - ignore bogus broadcast responses? */ -int sysctl_icmp_ignore_bogus_error_responses; +int sysctl_icmp_ignore_bogus_error_responses = 1; /* * Configurable global rate limit. @@ -385,7 +385,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) u32 daddr; if (ip_options_echo(&icmp_param->replyopts, skb)) - goto out; + return; if (icmp_xmit_lock()) return; @@ -416,7 +416,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) ip_rt_put(rt); out_unlock: icmp_xmit_unlock(); -out:; } @@ -525,7 +524,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) iph->tos; if (ip_options_echo(&icmp_param.replyopts, skb_in)) - goto ende; + goto out_unlock; /* diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 192092b89e53..64ce52bf0485 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -233,7 +233,18 @@ static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type, case IGMPV3_MODE_IS_EXCLUDE: if (gdeleted || sdeleted) return 0; - return !(pmc->gsquery && !psf->sf_gsresp); + if (!(pmc->gsquery && !psf->sf_gsresp)) { + if (pmc->sfmode == MCAST_INCLUDE) + return 1; + /* don't include if this source is excluded + * in all filters + */ + if (psf->sf_count[MCAST_INCLUDE]) + return type == IGMPV3_MODE_IS_INCLUDE; + return pmc->sfcount[MCAST_EXCLUDE] == + psf->sf_count[MCAST_EXCLUDE]; + } + return 0; case IGMPV3_CHANGE_TO_INCLUDE: if (gdeleted || sdeleted) return 0; @@ -385,7 +396,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, struct igmpv3_report *pih; struct igmpv3_grec *pgr = NULL; struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list; - int scount, first, isquery, truncate; + int scount, stotal, first, isquery, truncate; if (pmc->multiaddr == IGMP_ALL_HOSTS) return skb; @@ -395,25 +406,13 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, truncate = type == IGMPV3_MODE_IS_EXCLUDE || type == IGMPV3_CHANGE_TO_EXCLUDE; + stotal = scount = 0; + psf_list = sdeleted ? &pmc->tomb : &pmc->sources; - if (!*psf_list) { - if (type == IGMPV3_ALLOW_NEW_SOURCES || - type == IGMPV3_BLOCK_OLD_SOURCES) - return skb; - if (pmc->crcount || isquery) { - /* make sure we have room for group header and at - * least one source. - */ - if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)+ - sizeof(__u32)) { - igmpv3_sendpack(skb); - skb = NULL; /* add_grhead will get a new one */ - } - skb = add_grhead(skb, pmc, type, &pgr); - } - return skb; - } + if (!*psf_list) + goto empty_source; + pih = skb ? (struct igmpv3_report *)skb->h.igmph : NULL; /* EX and TO_EX get a fresh packet, if needed */ @@ -426,7 +425,6 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } } first = 1; - scount = 0; psf_prev = NULL; for (psf=*psf_list; psf; psf=psf_next) { u32 *psrc; @@ -460,7 +458,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } psrc = (u32 *)skb_put(skb, sizeof(u32)); *psrc = psf->sf_inaddr; - scount++; + scount++; stotal++; if ((type == IGMPV3_ALLOW_NEW_SOURCES || type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) { psf->sf_crcount--; @@ -475,6 +473,21 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } psf_prev = psf; } + +empty_source: + if (!stotal) { + if (type == IGMPV3_ALLOW_NEW_SOURCES || + type == IGMPV3_BLOCK_OLD_SOURCES) + return skb; + if (pmc->crcount || isquery) { + /* make sure we have room for group header */ + if (skb && AVAILABLE(skb)<sizeof(struct igmpv3_grec)) { + igmpv3_sendpack(skb); + skb = NULL; /* add_grhead will get a new one */ + } + skb = add_grhead(skb, pmc, type, &pgr); + } + } if (pgr) pgr->grec_nsrcs = htons(scount); @@ -557,11 +570,11 @@ static void igmpv3_send_cr(struct in_device *in_dev) skb = add_grec(skb, pmc, dtype, 1, 1); } if (pmc->crcount) { - pmc->crcount--; if (pmc->sfmode == MCAST_EXCLUDE) { type = IGMPV3_CHANGE_TO_INCLUDE; skb = add_grec(skb, pmc, type, 1, 0); } + pmc->crcount--; if (pmc->crcount == 0) { igmpv3_clear_zeros(&pmc->tomb); igmpv3_clear_zeros(&pmc->sources); @@ -594,12 +607,12 @@ static void igmpv3_send_cr(struct in_device *in_dev) /* filter mode changes */ if (pmc->crcount) { - pmc->crcount--; if (pmc->sfmode == MCAST_EXCLUDE) type = IGMPV3_CHANGE_TO_EXCLUDE; else type = IGMPV3_CHANGE_TO_INCLUDE; skb = add_grec(skb, pmc, type, 0, 0); + pmc->crcount--; } spin_unlock_bh(&pmc->lock); } @@ -735,7 +748,8 @@ static void igmp_timer_expire(unsigned long data) ip_ma_put(im); } -static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) +/* mark EXCLUDE-mode sources */ +static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) { struct ip_sf_list *psf; int i, scount; @@ -744,6 +758,37 @@ static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) for (psf=pmc->sources; psf; psf=psf->sf_next) { if (scount == nsrcs) break; + for (i=0; i<nsrcs; i++) { + /* skip inactive filters */ + if (pmc->sfcount[MCAST_INCLUDE] || + pmc->sfcount[MCAST_EXCLUDE] != + psf->sf_count[MCAST_EXCLUDE]) + continue; + if (srcs[i] == psf->sf_inaddr) { + scount++; + break; + } + } + } + pmc->gsquery = 0; + if (scount == nsrcs) /* all sources excluded */ + return 0; + return 1; +} + +static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) +{ + struct ip_sf_list *psf; + int i, scount; + + if (pmc->sfmode == MCAST_EXCLUDE) + return igmp_xmarksources(pmc, nsrcs, srcs); + + /* mark INCLUDE-mode sources */ + scount = 0; + for (psf=pmc->sources; psf; psf=psf->sf_next) { + if (scount == nsrcs) + break; for (i=0; i<nsrcs; i++) if (srcs[i] == psf->sf_inaddr) { psf->sf_gsresp = 1; @@ -751,6 +796,12 @@ static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) break; } } + if (!scount) { + pmc->gsquery = 0; + return 0; + } + pmc->gsquery = 1; + return 1; } static void igmp_heard_report(struct in_device *in_dev, u32 group) @@ -845,6 +896,8 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, */ read_lock(&in_dev->mc_list_lock); for (im=in_dev->mc_list; im!=NULL; im=im->next) { + int changed; + if (group && group != im->multiaddr) continue; if (im->multiaddr == IGMP_ALL_HOSTS) @@ -854,10 +907,11 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, im->gsquery = im->gsquery && mark; else im->gsquery = mark; - if (im->gsquery) - igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs); + changed = !im->gsquery || + igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs); spin_unlock_bh(&im->lock); - igmp_mod_timer(im, max_delay); + if (changed) + igmp_mod_timer(im, max_delay); } read_unlock(&in_dev->mc_list_lock); } @@ -916,7 +970,7 @@ int igmp_rcv(struct sk_buff *skb) case IGMP_MTRACE_RESP: break; default: - NETDEBUG(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type); + break; } drop: @@ -1510,7 +1564,7 @@ static void sf_markstate(struct ip_mc_list *pmc) static int sf_setstate(struct ip_mc_list *pmc) { - struct ip_sf_list *psf; + struct ip_sf_list *psf, *dpsf; int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; int qrv = pmc->interface->mr_qrv; int new_in, rv; @@ -1522,8 +1576,46 @@ static int sf_setstate(struct ip_mc_list *pmc) !psf->sf_count[MCAST_INCLUDE]; } else new_in = psf->sf_count[MCAST_INCLUDE] != 0; - if (new_in != psf->sf_oldin) { - psf->sf_crcount = qrv; + if (new_in) { + if (!psf->sf_oldin) { + struct ip_sf_list *prev = NULL; + + for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) { + if (dpsf->sf_inaddr == psf->sf_inaddr) + break; + prev = dpsf; + } + if (dpsf) { + if (prev) + prev->sf_next = dpsf->sf_next; + else + pmc->tomb = dpsf->sf_next; + kfree(dpsf); + } + psf->sf_crcount = qrv; + rv++; + } + } else if (psf->sf_oldin) { + + psf->sf_crcount = 0; + /* + * add or update "delete" records if an active filter + * is now inactive + */ + for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) + if (dpsf->sf_inaddr == psf->sf_inaddr) + break; + if (!dpsf) { + dpsf = (struct ip_sf_list *) + kmalloc(sizeof(*dpsf), GFP_ATOMIC); + if (!dpsf) + continue; + *dpsf = *psf; + /* pmc->lock held by callers */ + dpsf->sf_next = pmc->tomb; + pmc->tomb = dpsf; + } + dpsf->sf_crcount = qrv; rv++; } } diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index d34a9fa608e0..342d0b9098f5 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c @@ -228,7 +228,7 @@ static void wrandom_set_nhinfo(__u32 network, struct multipath_dest *d, *target_dest = NULL; /* store the weight information for a certain route */ - spin_lock(&state[state_idx].lock); + spin_lock_bh(&state[state_idx].lock); /* find state entry for gateway or add one if necessary */ list_for_each_entry_rcu(r, &state[state_idx].head, list) { @@ -276,7 +276,7 @@ static void wrandom_set_nhinfo(__u32 network, * we are finished */ - spin_unlock(&state[state_idx].lock); + spin_unlock_bh(&state[state_idx].lock); } static void __multipath_free(struct rcu_head *head) @@ -302,7 +302,7 @@ static void wrandom_flush(void) for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { struct multipath_route *r; - spin_lock(&state[i].lock); + spin_lock_bh(&state[i].lock); list_for_each_entry_rcu(r, &state[i].head, list) { struct multipath_dest *d; list_for_each_entry_rcu(d, &r->dests, list) { @@ -315,7 +315,7 @@ static void wrandom_flush(void) __multipath_free); } - spin_unlock(&state[i].lock); + spin_unlock_bh(&state[i].lock); } } diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index afe3d8f8177d..dd1048be8a01 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -807,6 +807,13 @@ static int do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index c9ebbe0d2d9c..e0b5926c76f9 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1216,7 +1216,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK << 8; + type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); @@ -1567,6 +1567,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); +MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); static int __init ctnetlink_init(void) { diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index d3c5a371f993..4ba4463cec28 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c @@ -71,6 +71,7 @@ static int tftp_help(struct sk_buff **pskb, exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; exp->mask.src.ip = 0xffffffff; + exp->mask.src.u.udp.port = 0; exp->mask.dst.ip = 0xffffffff; exp->mask.dst.u.udp.port = 0xffff; exp->mask.dst.protonum = 0xff; diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index ad438fb185b8..92c54999a19d 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -209,8 +209,8 @@ ip_nat_in(unsigned int hooknum, && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - if (ct->tuplehash[dir].tuple.src.ip != - ct->tuplehash[!dir].tuple.dst.ip) { + if (ct->tuplehash[dir].tuple.dst.ip != + ct->tuplehash[!dir].tuple.src.ip) { dst_release((*pskb)->dst); (*pskb)->dst = NULL; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2371b2062c2d..16f47c675fef 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -921,6 +921,13 @@ do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 641dbc477650..180a9ea57b69 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -35,6 +35,10 @@ * each nlgroup you are using, so the total kernel memory usage increases * by that factor. * + * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since + * nlbufsiz is used with alloc_skb, which adds another + * sizeof(struct skb_shared_info). Use NLMSG_GOODSIZE instead. + * * flushtimeout: * Specify, after how many hundredths of a second the queue should be * flushed even if it is not full yet. @@ -76,7 +80,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) -static unsigned int nlbufsiz = 4096; +static unsigned int nlbufsiz = NLMSG_GOODSIZE; module_param(nlbufsiz, uint, 0400); MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); @@ -143,22 +147,26 @@ static void ulog_timer(unsigned long data) static struct sk_buff *ulog_alloc_skb(unsigned int size) { struct sk_buff *skb; + unsigned int n; /* alloc skb which should be big enough for a whole * multipart message. WARNING: has to be <= 131000 * due to slab allocator restrictions */ - skb = alloc_skb(nlbufsiz, GFP_ATOMIC); + n = max(size, nlbufsiz); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { - PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", - nlbufsiz); + PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n); - /* try to allocate only as much as we need for - * current packet */ + if (n > size) { + /* try to allocate only as much as we need for + * current packet */ - skb = alloc_skb(size, GFP_ATOMIC); - if (!skb) - PRINTR("ipt_ULOG: can't even allocate %ub\n", size); + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + PRINTR("ipt_ULOG: can't even allocate %ub\n", + size); + } } return skb; diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c index 18ca8258a1c5..5a7a265280f9 100644 --- a/net/ipv4/netfilter/ipt_policy.c +++ b/net/ipv4/netfilter/ipt_policy.c @@ -26,10 +26,13 @@ MODULE_LICENSE("GPL"); static inline int match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) { -#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \ + ^ e->invert.x)) +#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) - return MATCH(saddr, x->props.saddr.a4 & e->smask) && - MATCH(daddr, x->id.daddr.a4 & e->dmask) && + return MATCH_ADDR(saddr, smask, x->props.saddr.a4) && + MATCH_ADDR(daddr, dmask, x->id.daddr.a4) && MATCH(proto, x->id.proto) && MATCH(mode, x->props.mode) && MATCH(spi, x->id.spi) && @@ -89,7 +92,7 @@ match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) return 0; } - return strict ? 1 : 0; + return strict ? i == info->len : 0; } static int match(const struct sk_buff *skb, diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 39d49dc333a7..1b167c4bb3be 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) res += proto->stats[cpu].inuse; return res; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 165a4d81efa4..f29a12da5109 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -40,12 +40,12 @@ */ #include <linux/config.h> +#include <linux/types.h> #include <asm/atomic.h> #include <asm/byteorder.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/ioctls.h> -#include <linux/types.h> #include <linux/stddef.h> #include <linux/slab.h> #include <linux/errno.h> diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f2e82afc15b3..d82c242ea704 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -241,7 +241,8 @@ static int rt_hash_log; static unsigned int rt_hash_rnd; static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); -#define RT_CACHE_STAT_INC(field) (__get_cpu_var(rt_cache_stat).field++) +#define RT_CACHE_STAT_INC(field) \ + (per_cpu(rt_cache_stat, raw_smp_processor_id()).field++) static int rt_intern_hash(unsigned hash, struct rtable *rth, struct rtable **res); diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 3284cfb993e6..128de4d7c0b7 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c @@ -230,7 +230,6 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, if (tp->snd_cwnd < tp->snd_cwnd_clamp) tp->snd_cwnd++; tp->snd_cwnd_cnt = 0; - ca->ccount++; } } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a97ed5416c28..e9a54ae7d690 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk) tp->rcvq_space.space = space; - if (sysctl_tcp_moderate_rcvbuf) { + if (sysctl_tcp_moderate_rcvbuf && + !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { int new_clamp = space; /* Receive space grows, normalize in order to diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6ea353907af5..233bdf259965 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -236,7 +236,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (err) goto failure; - err = ip_route_newports(&rt, inet->sport, inet->dport, sk); + err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); if (err) goto failure; @@ -1845,7 +1845,6 @@ void __init tcp_v4_init(struct net_proto_family *ops) } EXPORT_SYMBOL(ipv4_specific); -EXPORT_SYMBOL(inet_bind_bucket_create); EXPORT_SYMBOL(tcp_hashinfo); EXPORT_SYMBOL(tcp_prot); EXPORT_SYMBOL(tcp_unhash); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 42196ba3b0b9..45f7ae58f2c0 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -8,7 +8,6 @@ * */ -#include <asm/bug.h> #include <linux/compiler.h> #include <linux/config.h> #include <linux/inetdevice.h> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d328d5986143..b7d8822c1be4 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2165,6 +2165,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, dev->name); break; } + + if (idev) + idev->if_flags |= IF_READY; } else { if (!netif_carrier_ok(dev)) { /* device is still not ready. */ @@ -3321,9 +3324,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) switch (event) { case RTM_NEWADDR: - dst_hold(&ifp->rt->u.dst); - if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL)) - dst_release(&ifp->rt->u.dst); + ip6_ins_rt(ifp->rt, NULL, NULL, NULL); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); break; @@ -3334,8 +3335,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) dst_hold(&ifp->rt->u.dst); if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) dst_free(&ifp->rt->u.dst); - else - dst_release(&ifp->rt->u.dst); break; } } diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 064ffab82a9f..6c9711ac1c03 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -369,12 +369,6 @@ int inet6_destroy_sock(struct sock *sk) struct sk_buff *skb; struct ipv6_txoptions *opt; - /* - * Release destination entry - */ - - sk_dst_reset(sk); - /* Release rx options */ if ((skb = xchg(&np->pktoptions, NULL)) != NULL) diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 6c05c7978bef..807c021d64a2 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1252,8 +1252,7 @@ int igmp6_event_query(struct sk_buff *skb) } } else { for (ma = idev->mc_list; ma; ma=ma->next) { - if (group_type != IPV6_ADDR_ANY && - !ipv6_addr_equal(group, &ma->mca_addr)) + if (!ipv6_addr_equal(group, &ma->mca_addr)) continue; spin_lock_bh(&ma->mca_lock); if (ma->mca_flags & MAF_TIMER_RUNNING) { @@ -1268,11 +1267,10 @@ int igmp6_event_query(struct sk_buff *skb) ma->mca_flags &= ~MAF_GSQUERY; } if (!(ma->mca_flags & MAF_GSQUERY) || - mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) + mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) igmp6_group_queried(ma, max_delay); spin_unlock_bh(&ma->mca_lock); - if (group_type != IPV6_ADDR_ANY) - break; + break; } } read_unlock_bh(&idev->lock); @@ -1351,7 +1349,7 @@ static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type, * in all filters */ if (psf->sf_count[MCAST_INCLUDE]) - return 0; + return type == MLD2_MODE_IS_INCLUDE; return pmc->mca_sfcount[MCAST_EXCLUDE] == psf->sf_count[MCAST_EXCLUDE]; } @@ -1966,7 +1964,7 @@ static void sf_markstate(struct ifmcaddr6 *pmc) static int sf_setstate(struct ifmcaddr6 *pmc) { - struct ip6_sf_list *psf; + struct ip6_sf_list *psf, *dpsf; int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; int qrv = pmc->idev->mc_qrv; int new_in, rv; @@ -1978,8 +1976,48 @@ static int sf_setstate(struct ifmcaddr6 *pmc) !psf->sf_count[MCAST_INCLUDE]; } else new_in = psf->sf_count[MCAST_INCLUDE] != 0; - if (new_in != psf->sf_oldin) { - psf->sf_crcount = qrv; + if (new_in) { + if (!psf->sf_oldin) { + struct ip6_sf_list *prev = NULL; + + for (dpsf=pmc->mca_tomb; dpsf; + dpsf=dpsf->sf_next) { + if (ipv6_addr_equal(&dpsf->sf_addr, + &psf->sf_addr)) + break; + prev = dpsf; + } + if (dpsf) { + if (prev) + prev->sf_next = dpsf->sf_next; + else + pmc->mca_tomb = dpsf->sf_next; + kfree(dpsf); + } + psf->sf_crcount = qrv; + rv++; + } + } else if (psf->sf_oldin) { + psf->sf_crcount = 0; + /* + * add or update "delete" records if an active filter + * is now inactive + */ + for (dpsf=pmc->mca_tomb; dpsf; dpsf=dpsf->sf_next) + if (ipv6_addr_equal(&dpsf->sf_addr, + &psf->sf_addr)) + break; + if (!dpsf) { + dpsf = (struct ip6_sf_list *) + kmalloc(sizeof(*dpsf), GFP_ATOMIC); + if (!dpsf) + continue; + *dpsf = *psf; + /* pmc->mca_lock held by callers */ + dpsf->sf_next = pmc->mca_tomb; + pmc->mca_tomb = dpsf; + } + dpsf->sf_crcount = qrv; rv++; } } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 847068fd3367..74ff56c322f4 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -978,6 +978,13 @@ do_replace(void __user *user, unsigned int len) if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index afe1cc4c18a5..3d39ec924041 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -26,8 +26,9 @@ MODULE_LICENSE("GPL"); static inline int match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) { -#define MATCH_ADDR(x,y,z) (!e->match.x || \ - ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x) +#define MATCH_ADDR(x,y,z) (!e->match.x || \ + ((!ip6_masked_addrcmp(&e->x.a6, &e->y.a6, z)) \ + ^ e->invert.x)) #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) && @@ -91,7 +92,7 @@ match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info) return 0; } - return strict ? 1 : 0; + return strict ? i == info->len : 0; } static int match(const struct sk_buff *skb, diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 50a13e75d70e..4238b1ed8860 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for (cpu=0; cpu<NR_CPUS; cpu++) + for_each_cpu(cpu) res += proto->stats[cpu].inuse; return res; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 66f1d12ea578..ae20a0ec9bd8 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -35,7 +35,6 @@ #include <linux/skbuff.h> #include <asm/uaccess.h> #include <asm/ioctls.h> -#include <asm/bug.h> #include <net/ip.h> #include <net/sock.h> @@ -804,10 +803,7 @@ back_from_confirm: err = rawv6_push_pending_frames(sk, &fl, rp); } done: - ip6_dst_store(sk, dst, - ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? - &np->daddr : NULL); - + dst_release(dst); release_sock(sk); out: fl6_sock_release(flowlabel); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 66d04004afda..ca9cf6853755 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -515,6 +515,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, done: if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); + dst_release(dst); return err; } diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 69bd957380e7..91cce8b2d7a5 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -11,7 +11,6 @@ * */ -#include <asm/bug.h> #include <linux/compiler.h> #include <linux/config.h> #include <linux/netdevice.h> diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index 890bac0d4a56..e3debbdb67f5 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -343,12 +343,12 @@ static void irda_task_timer_expired(void *data) static void irda_device_setup(struct net_device *dev) { dev->hard_header_len = 0; - dev->addr_len = 0; + dev->addr_len = LAP_ALEN; dev->type = ARPHRD_IRDA; dev->tx_queue_len = 8; /* Window size + 1 s-frame */ - memset(dev->broadcast, 0xff, 4); + memset(dev->broadcast, 0xff, LAP_ALEN); dev->mtu = 2048; dev->flags = IFF_NOARP; diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index 07ec326c71f5..f65c7a83bc5c 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c @@ -696,7 +696,7 @@ irnet_daddr_to_dname(irnet_socket * self) { /* Yes !!! Get it.. */ strlcpy(self->rname, discoveries[i].info, sizeof(self->rname)); - self->rname[NICKNAME_MAX_LEN + 1] = '\0'; + self->rname[sizeof(self->rname) - 1] = '\0'; DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n", self->daddr, self->rname); kfree(discoveries); diff --git a/net/key/af_key.c b/net/key/af_key.c index 43f1ce74187d..ae86d237a456 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1620,6 +1620,7 @@ static int key_notify_sa_flush(struct km_event *c) return -ENOBUFS; hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto); + hdr->sadb_msg_type = SADB_FLUSH; hdr->sadb_msg_seq = c->seq; hdr->sadb_msg_pid = c->pid; hdr->sadb_msg_version = PF_KEY_V2; @@ -2385,6 +2386,7 @@ static int key_notify_policy_flush(struct km_event *c) if (!skb_out) return -ENOBUFS; hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); + hdr->sadb_msg_type = SADB_X_SPDFLUSH; hdr->sadb_msg_seq = c->seq; hdr->sadb_msg_pid = c->pid; hdr->sadb_msg_version = PF_KEY_V2; diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 99c0a0fa4a97..0e550127fa7e 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -102,8 +102,6 @@ config NF_CT_NETLINK help This option enables support for a netlink-based userspace interface -endmenu - config NETFILTER_XTABLES tristate "Netfilter Xtables support (required for ip_tables)" help @@ -361,3 +359,5 @@ config NETFILTER_XT_MATCH_TCPMSS To compile it as a module, choose M here. If unsure, say N. +endmenu + diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 62bb509f05d4..0ce337a1d974 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -188,7 +188,7 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; struct nf_conntrack_protocol * __nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) { - if (unlikely(nf_ct_protos[l3proto] == NULL)) + if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) return &nf_conntrack_generic_protocol; return nf_ct_protos[l3proto][protocol]; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index ab0c920f0d30..6f210f399762 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -657,8 +657,6 @@ static int __init init(void) /* FIXME should be configurable whether IPv4 and IPv6 FTP connections are tracked or not - YK */ for (i = 0; i < ports_c; i++) { - memset(&ftp[i], 0, sizeof(struct nf_conntrack_helper)); - ftp[i][0].tuple.src.l3num = PF_INET; ftp[i][1].tuple.src.l3num = PF_INET6; for (j = 0; j < 2; j++) { diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 73ab16bc7d40..9ff3463037e1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1232,7 +1232,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, b = skb->tail; - type |= NFNL_SUBSYS_CTNETLINK << 8; + type |= NFNL_SUBSYS_CTNETLINK_EXP << 8; nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); @@ -1589,6 +1589,7 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); +MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); static int __init ctnetlink_init(void) { diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e10512e229b6..3b3c781b40c0 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -37,7 +37,7 @@ #include "../bridge/br_private.h" #endif -#define NFULNL_NLBUFSIZ_DEFAULT 4096 +#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ @@ -314,24 +314,28 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size) { struct sk_buff *skb; + unsigned int n; UDEBUG("entered (%u, %u)\n", inst_size, pkt_size); /* alloc skb which should be big enough for a whole multipart * message. WARNING: has to be <= 128k due to slab restrictions */ - skb = alloc_skb(inst_size, GFP_ATOMIC); + n = max(inst_size, pkt_size); + skb = alloc_skb(n, GFP_ATOMIC); if (!skb) { PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n", inst_size); - /* try to allocate only as much as we need for current - * packet */ + if (n > pkt_size) { + /* try to allocate only as much as we need for current + * packet */ - skb = alloc_skb(pkt_size, GFP_ATOMIC); - if (!skb) - PRINTR("nfnetlink_log: can't even alloc %u bytes\n", - pkt_size); + skb = alloc_skb(pkt_size, GFP_ATOMIC); + if (!skb) + PRINTR("nfnetlink_log: can't even alloc %u " + "bytes\n", pkt_size); + } } return skb; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 18ed9c5d209c..cac38b2e147a 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -825,7 +825,8 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, } if (nfqa[NFQA_MARK-1]) - skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1])); + entry->skb->nfmark = ntohl(*(u_int32_t *) + NFA_DATA(nfqa[NFQA_MARK-1])); issue_verdict(entry, verdict); instance_put(queue); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2101b45d2ec6..6b9772d95872 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -702,7 +702,8 @@ struct sock *netlink_getsockbyfilp(struct file *filp) * 0: continue * 1: repeat lookup - reference dropped while waiting for socket memory. */ -int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo) +int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, + long timeo, struct sock *ssk) { struct netlink_sock *nlk; @@ -712,7 +713,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t test_bit(0, &nlk->state)) { DECLARE_WAITQUEUE(wait, current); if (!timeo) { - if (!nlk->pid) + if (!ssk || nlk_sk(ssk)->pid == 0) netlink_overrun(sk); sock_put(sk); kfree_skb(skb); @@ -797,7 +798,7 @@ retry: kfree_skb(skb); return PTR_ERR(sk); } - err = netlink_attachskb(sk, skb, nonblock, timeo); + err = netlink_attachskb(sk, skb, nonblock, timeo, ssk); if (err == 1) goto retry; if (err) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 4ae1538c54a9..43e72419c868 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -238,7 +238,7 @@ int genl_register_family(struct genl_family *family) sizeof(struct nlattr *), GFP_KERNEL); if (family->attrbuf == NULL) { err = -ENOMEM; - goto errout; + goto errout_locked; } } else family->attrbuf = NULL; @@ -288,7 +288,7 @@ int genl_unregister_family(struct genl_family *family) return -ENOENT; } -static inline int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, +static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) { struct genl_ops *ops; @@ -375,7 +375,7 @@ static void genl_rcv(struct sock *sk, int len) do { if (genl_trylock()) return; - netlink_run_queue(sk, &qlen, &genl_rcv_msg); + netlink_run_queue(sk, &qlen, genl_rcv_msg); genl_unlock(); } while (qlen && genl_sock && genl_sock->sk_receive_queue.qlen); } @@ -549,10 +549,8 @@ static int __init genl_init(void) netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV); genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID, genl_rcv, THIS_MODULE); - if (genl_sock == NULL) { + if (genl_sock == NULL) panic("GENL: Cannot initialize generic netlink\n"); - return -ENOMEM; - } return 0; @@ -560,7 +558,6 @@ errout_register: genl_unregister_family(&genl_ctrl); errout: panic("GENL: Cannot register controller: %d\n", err); - return err; } subsys_initcall(genl_init); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ee93abc71cb8..9db7dbdb16e6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -365,7 +365,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, */ err = -EMSGSIZE; - if(len>dev->mtu+dev->hard_header_len) + if (len > dev->mtu + dev->hard_header_len) goto out_unlock; err = -ENOBUFS; @@ -935,7 +935,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add * Check legality */ - if(addr_len!=sizeof(struct sockaddr)) + if (addr_len != sizeof(struct sockaddr)) return -EINVAL; strlcpy(name,uaddr->sa_data,sizeof(name)); @@ -1092,7 +1092,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, * retries. */ - if(skb==NULL) + if (skb == NULL) goto out; /* @@ -1392,8 +1392,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, if (level != SOL_PACKET) return -ENOPROTOOPT; - if (get_user(len,optlen)) - return -EFAULT; + if (get_user(len, optlen)) + return -EFAULT; if (len < 0) return -EINVAL; @@ -1419,9 +1419,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, return -ENOPROTOOPT; } - if (put_user(len, optlen)) - return -EFAULT; - return 0; + if (put_user(len, optlen)) + return -EFAULT; + return 0; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 4aa6fc60357c..cb78b50868ee 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -257,20 +257,26 @@ int sctp_rcv(struct sk_buff *skb) */ sctp_bh_lock_sock(sk); + /* It is possible that the association could have moved to a different + * socket if it is peeled off. If so, update the sk. + */ + if (sk != rcvr->sk) { + sctp_bh_lock_sock(rcvr->sk); + sctp_bh_unlock_sock(sk); + sk = rcvr->sk; + } + if (sock_owned_by_user(sk)) sk_add_backlog(sk, skb); else sctp_backlog_rcv(sk, skb); - /* Release the sock and any reference counts we took in the - * lookup calls. + /* Release the sock and the sock ref we took in the lookup calls. + * The asoc/ep ref will be released in sctp_backlog_rcv. */ sctp_bh_unlock_sock(sk); - if (asoc) - sctp_association_put(asoc); - else - sctp_endpoint_put(ep); sock_put(sk); + return ret; discard_it: @@ -296,12 +302,50 @@ discard_release: int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) { struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; - struct sctp_inq *inqueue = &chunk->rcvr->inqueue; - - sctp_inq_push(inqueue, chunk); + struct sctp_inq *inqueue = NULL; + struct sctp_ep_common *rcvr = NULL; + + rcvr = chunk->rcvr; + + BUG_TRAP(rcvr->sk == sk); + + if (rcvr->dead) { + sctp_chunk_free(chunk); + } else { + inqueue = &chunk->rcvr->inqueue; + sctp_inq_push(inqueue, chunk); + } + + /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ + if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) + sctp_association_put(sctp_assoc(rcvr)); + else + sctp_endpoint_put(sctp_ep(rcvr)); + return 0; } +void sctp_backlog_migrate(struct sctp_association *assoc, + struct sock *oldsk, struct sock *newsk) +{ + struct sk_buff *skb; + struct sctp_chunk *chunk; + + skb = oldsk->sk_backlog.head; + oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL; + while (skb != NULL) { + struct sk_buff *next = skb->next; + + chunk = SCTP_INPUT_CB(skb)->chunk; + skb->next = NULL; + if (&assoc->base == chunk->rcvr) + sk_add_backlog(newsk, skb); + else + sk_add_backlog(oldsk, skb); + skb = next; + } +} + /* Handle icmp frag needed error. */ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t, __u32 pmtu) @@ -544,10 +588,16 @@ int sctp_rcv_ootb(struct sk_buff *skb) sctp_errhdr_t *err; ch = (sctp_chunkhdr_t *) skb->data; - ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length)); /* Scan through all the chunks in the packet. */ - while (ch_end > (__u8 *)ch && ch_end < skb->tail) { + do { + /* Break out if chunk length is less then minimal. */ + if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t)) + break; + + ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); + if (ch_end > skb->tail) + break; /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the * receiver MUST silently discard the OOTB packet and take no @@ -578,8 +628,7 @@ int sctp_rcv_ootb(struct sk_buff *skb) } ch = (sctp_chunkhdr_t *) ch_end; - ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length)); - } + } while (ch_end < skb->tail); return 0; diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 2d33922c044b..297b8951463e 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -73,8 +73,10 @@ void sctp_inq_free(struct sctp_inq *queue) /* If there is a packet which is currently being worked on, * free it as well. */ - if (queue->in_progress) + if (queue->in_progress) { sctp_chunk_free(queue->in_progress); + queue->in_progress = NULL; + } if (queue->malloced) { /* Dump the master memory segment. */ diff --git a/net/sctp/output.c b/net/sctp/output.c index a40991ef72c9..437cba7260a4 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -608,7 +608,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, * When a Fast Retransmit is being performed the sender SHOULD * ignore the value of cwnd and SHOULD NOT delay retransmission. */ - if (!chunk->fast_retransmit) + if (chunk->fast_retransmit <= 0) if (transport->flight_size >= transport->cwnd) { retval = SCTP_XMIT_RWND_FULL; goto finish; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index efb72faba20c..f148f9576dd2 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -406,7 +406,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, * chunks that are not yet acked should be added to the * retransmit queue. */ - if ((fast_retransmit && chunk->fast_retransmit) || + if ((fast_retransmit && (chunk->fast_retransmit > 0)) || (!fast_retransmit && !chunk->tsn_gap_acked)) { /* RFC 2960 6.2.1 Processing a Received SACK * @@ -603,7 +603,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, /* Mark the chunk as ineligible for fast retransmit * after it is retransmitted. */ - chunk->fast_retransmit = 0; + if (chunk->fast_retransmit > 0) + chunk->fast_retransmit = -1; *start_timer = 1; q->empty = 0; @@ -621,7 +622,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, list_for_each(lchunk1, lqueue) { chunk1 = list_entry(lchunk1, struct sctp_chunk, transmitted_list); - chunk1->fast_retransmit = 0; + if (chunk1->fast_retransmit > 0) + chunk1->fast_retransmit = -1; } } } @@ -1562,11 +1564,11 @@ static void sctp_mark_missing(struct sctp_outq *q, /* * M4) If any DATA chunk is found to have a * 'TSN.Missing.Report' - * value larger than or equal to 4, mark that chunk for + * value larger than or equal to 3, mark that chunk for * retransmission and start the fast retransmit procedure. */ - if (chunk->tsn_missing_report >= 4) { + if (chunk->tsn_missing_report >= 3) { chunk->fast_retransmit = 1; do_fast_retransmit = 1; } diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 6e4dc28874d7..d47a52c303a8 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -176,7 +176,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) { - if (*pos > sctp_ep_hashsize) + if (*pos >= sctp_ep_hashsize) return NULL; if (*pos < 0) @@ -185,8 +185,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n"); - ++*pos; - return (void *)pos; } @@ -198,11 +196,9 @@ static void sctp_eps_seq_stop(struct seq_file *seq, void *v) static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - if (*pos > sctp_ep_hashsize) + if (++*pos >= sctp_ep_hashsize) return NULL; - ++*pos; - return pos; } @@ -214,19 +210,19 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) struct sctp_ep_common *epb; struct sctp_endpoint *ep; struct sock *sk; - int hash = *(int *)v; + int hash = *(loff_t *)v; - if (hash > sctp_ep_hashsize) + if (hash >= sctp_ep_hashsize) return -ENOMEM; - head = &sctp_ep_hashtable[hash-1]; + head = &sctp_ep_hashtable[hash]; sctp_local_bh_disable(); read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { ep = sctp_ep(epb); sk = epb->sk; seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, - sctp_sk(sk)->type, sk->sk_state, hash-1, + sctp_sk(sk)->type, sk->sk_state, hash, epb->bind_addr.port, sock_i_uid(sk), sock_i_ino(sk)); @@ -283,7 +279,7 @@ void sctp_eps_proc_exit(void) static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) { - if (*pos > sctp_assoc_hashsize) + if (*pos >= sctp_assoc_hashsize) return NULL; if (*pos < 0) @@ -293,8 +289,6 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) seq_printf(seq, " ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " "RPORT LADDRS <-> RADDRS\n"); - ++*pos; - return (void *)pos; } @@ -306,11 +300,9 @@ static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - if (*pos > sctp_assoc_hashsize) + if (++*pos >= sctp_assoc_hashsize) return NULL; - ++*pos; - return pos; } @@ -321,12 +313,12 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) struct sctp_ep_common *epb; struct sctp_association *assoc; struct sock *sk; - int hash = *(int *)v; + int hash = *(loff_t *)v; - if (hash > sctp_assoc_hashsize) + if (hash >= sctp_assoc_hashsize) return -ENOMEM; - head = &sctp_assoc_hashtable[hash-1]; + head = &sctp_assoc_hashtable[hash]; sctp_local_bh_disable(); read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { @@ -335,7 +327,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ", assoc, sk, sctp_sk(sk)->type, sk->sk_state, - assoc->state, hash-1, assoc->assoc_id, + assoc->state, hash, assoc->assoc_id, (sk->sk_rcvbuf - assoc->rwnd), assoc->sndbuf_used, sock_i_uid(sk), sock_i_ino(sk), diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 556c495c6922..5e0de3c0eead 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1275,7 +1275,12 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, unsigned int keylen; char *key; - headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE; + /* Header size is static data prior to the actual cookie, including + * any padding. + */ + headersize = sizeof(sctp_paramhdr_t) + + (sizeof(struct sctp_signed_cookie) - + sizeof(struct sctp_cookie)); bodysize = sizeof(struct sctp_cookie) + ntohs(init_chunk->chunk_hdr->length) + addrs_len; @@ -1354,7 +1359,7 @@ struct sctp_association *sctp_unpack_cookie( struct sctp_signed_cookie *cookie; struct sctp_cookie *bear_cookie; int headersize, bodysize, fixed_size; - __u8 digest[SCTP_SIGNATURE_SIZE]; + __u8 *digest = ep->digest; struct scatterlist sg; unsigned int keylen, len; char *key; @@ -1362,7 +1367,12 @@ struct sctp_association *sctp_unpack_cookie( struct sk_buff *skb = chunk->skb; struct timeval tv; - headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE; + /* Header size is static data prior to the actual cookie, including + * any padding. + */ + headersize = sizeof(sctp_chunkhdr_t) + + (sizeof(struct sctp_signed_cookie) - + sizeof(struct sctp_cookie)); bodysize = ntohs(chunk->chunk_hdr->length) - headersize; fixed_size = headersize + sizeof(struct sctp_cookie); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index b8b38aba92b3..8d1dc24bab4c 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1300,7 +1300,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, "T1 INIT Timeout adjustment" " init_err_counter: %d" " cycle: %d" - " timeout: %d\n", + " timeout: %ld\n", asoc->init_err_counter, asoc->init_cycle, asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); @@ -1328,7 +1328,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, SCTP_DEBUG_PRINTK( "T1 COOKIE Timeout adjustment" " init_err_counter: %d" - " timeout: %d\n", + " timeout: %ld\n", asoc->init_err_counter, asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 477d7f80dba6..2b9a832b29a7 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -884,7 +884,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, { struct sctp_transport *transport = (struct sctp_transport *) arg; - if (asoc->overall_error_count > asoc->max_retrans) { + if (asoc->overall_error_count >= asoc->max_retrans) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -2122,7 +2122,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, struct sctp_bind_addr *bp; int attempts = asoc->init_err_counter + 1; - if (attempts >= asoc->max_init_attempts) { + if (attempts > asoc->max_init_attempts) { sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_STALE_COOKIE)); return SCTP_DISPOSITION_DELETE_TCB; @@ -3090,6 +3090,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, break; ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); + if (ch_end > skb->tail) + break; if (SCTP_CID_SHUTDOWN_ACK == ch->type) ootb_shut_ack = 1; @@ -4638,7 +4640,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); - if (attempts < asoc->max_init_attempts) { + if (attempts <= asoc->max_init_attempts) { bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); if (!repl) @@ -4695,7 +4697,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); - if (attempts < asoc->max_init_attempts) { + if (attempts <= asoc->max_init_attempts) { repl = sctp_make_cookie_echo(asoc, NULL); if (!repl) return SCTP_DISPOSITION_NOMEM; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c98ee375ba5e..0ea947eb6813 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2995,7 +2995,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->hbinterval = jiffies_to_msecs(sctp_hb_interval); sp->pathmaxrxt = sctp_max_retrans_path; sp->pathmtu = 0; // allow default discovery - sp->sackdelay = sctp_sack_timeout; + sp->sackdelay = jiffies_to_msecs(sctp_sack_timeout); sp->param_flags = SPP_HB_ENABLE | SPP_PMTUD_ENABLE | SPP_SACKDELAY_ENABLE; @@ -5426,7 +5426,7 @@ out: return err; do_error: - if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) + if (asoc->init_err_counter + 1 > asoc->max_init_attempts) err = -ETIMEDOUT; else err = -ECONNREFUSED; @@ -5602,8 +5602,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, */ newsp->type = type; + spin_lock_bh(&oldsk->sk_lock.slock); + /* Migrate the backlog from oldsk to newsk. */ + sctp_backlog_migrate(assoc, oldsk, newsk); /* Migrate the association to the new socket. */ sctp_assoc_migrate(assoc, newsk); + spin_unlock_bh(&oldsk->sk_lock.slock); /* If the association on the newsk is already closed before accept() * is called, set RCV_SHUTDOWN flag. diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index fcd7096c953d..dc6f3ff32358 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -159,12 +159,9 @@ static ctl_table sctp_table[] = { .ctl_name = NET_SCTP_PRESERVE_ENABLE, .procname = "cookie_preserve_enable", .data = &sctp_cookie_preserve_enable, - .maxlen = sizeof(long), + .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sctp_sysctl_jiffies_ms, - .extra1 = &rto_timer_min, - .extra2 = &rto_timer_max + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_RTO_ALPHA, diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 68d73e2dd155..160f62ad1cc5 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -350,7 +350,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) tp->rto_pending = 0; SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d " - "rttvar: %d, rto: %d\n", __FUNCTION__, + "rttvar: %d, rto: %ld\n", __FUNCTION__, tp, rtt, tp->srtt, tp->rttvar, tp->rto); } diff --git a/net/socket.c b/net/socket.c index b38a263853c3..a00851f981db 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2078,7 +2078,7 @@ void socket_seq_show(struct seq_file *seq) int cpu; int counter = 0; - for (cpu = 0; cpu < NR_CPUS; cpu++) + for_each_cpu(cpu) counter += per_cpu(sockets_in_use, cpu); /* It can be negative, by the way. 8) */ diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9ac1b8c26c01..8d6f1a176b15 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -184,7 +184,7 @@ rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) */ struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, - int taskflags) + int flags) { struct rpc_cred_cache *cache = auth->au_credcache; HLIST_HEAD(free); @@ -193,7 +193,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, *cred = NULL; int nr = 0; - if (!(taskflags & RPC_TASK_ROOTCREDS)) + if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) nr = acred->uid & RPC_CREDCACHE_MASK; retry: spin_lock(&rpc_credcache_lock); @@ -202,7 +202,7 @@ retry: hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { struct rpc_cred *entry; entry = hlist_entry(pos, struct rpc_cred, cr_hash); - if (entry->cr_ops->crmatch(acred, entry, taskflags)) { + if (entry->cr_ops->crmatch(acred, entry, flags)) { hlist_del(&entry->cr_hash); cred = entry; break; @@ -224,7 +224,7 @@ retry: rpcauth_destroy_credlist(&free); if (!cred) { - new = auth->au_ops->crcreate(auth, acred, taskflags); + new = auth->au_ops->crcreate(auth, acred, flags); if (!IS_ERR(new)) { #ifdef RPC_DEBUG new->cr_magic = RPCAUTH_CRED_MAGIC; @@ -232,13 +232,21 @@ retry: goto retry; } else cred = new; + } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) + && cred->cr_ops->cr_init != NULL + && !(flags & RPCAUTH_LOOKUP_NEW)) { + int res = cred->cr_ops->cr_init(auth, cred); + if (res < 0) { + put_rpccred(cred); + cred = ERR_PTR(res); + } } return (struct rpc_cred *) cred; } struct rpc_cred * -rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) +rpcauth_lookupcred(struct rpc_auth *auth, int flags) { struct auth_cred acred = { .uid = current->fsuid, @@ -250,7 +258,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) dprintk("RPC: looking up %s cred\n", auth->au_ops->au_name); get_group_info(acred.group_info); - ret = auth->au_ops->lookup_cred(auth, &acred, taskflags); + ret = auth->au_ops->lookup_cred(auth, &acred, flags); put_group_info(acred.group_info); return ret; } @@ -265,11 +273,14 @@ rpcauth_bindcred(struct rpc_task *task) .group_info = current->group_info, }; struct rpc_cred *ret; + int flags = 0; dprintk("RPC: %4d looking up %s cred\n", task->tk_pid, task->tk_auth->au_ops->au_name); get_group_info(acred.group_info); - ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); + if (task->tk_flags & RPC_TASK_ROOTCREDS) + flags |= RPCAUTH_LOOKUP_ROOTCREDS; + ret = auth->au_ops->lookup_cred(auth, &acred, flags); if (!IS_ERR(ret)) task->tk_msg.rpc_cred = ret; else diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8d782282ec19..bb46efd92e57 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -158,6 +158,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) old = gss_cred->gc_ctx; gss_cred->gc_ctx = ctx; cred->cr_flags |= RPCAUTH_CRED_UPTODATE; + cred->cr_flags &= ~RPCAUTH_CRED_NEW; write_unlock(&gss_ctx_lock); if (old) gss_put_ctx(old); @@ -580,7 +581,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } else { struct auth_cred acred = { .uid = uid }; spin_unlock(&gss_auth->lock); - cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0); + cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); if (IS_ERR(cred)) { err = PTR_ERR(cred); goto err_put_ctx; @@ -758,13 +759,13 @@ gss_destroy_cred(struct rpc_cred *rc) * Lookup RPCSEC_GSS cred for the current process */ static struct rpc_cred * -gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { - return rpcauth_lookup_credcache(auth, acred, taskflags); + return rpcauth_lookup_credcache(auth, acred, flags); } static struct rpc_cred * -gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); struct gss_cred *cred = NULL; @@ -785,13 +786,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) */ cred->gc_flags = 0; cred->gc_base.cr_ops = &gss_credops; + cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; cred->gc_service = gss_auth->service; - do { - err = gss_create_upcall(gss_auth, cred); - } while (err == -EAGAIN); - if (err < 0) - goto out_err; - return &cred->gc_base; out_err: @@ -801,13 +797,34 @@ out_err: } static int -gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags) +gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) +{ + struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); + struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); + int err; + + do { + err = gss_create_upcall(gss_auth, gss_cred); + } while (err == -EAGAIN); + return err; +} + +static int +gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) { struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); + /* + * If the searchflags have set RPCAUTH_LOOKUP_NEW, then + * we don't really care if the credential has expired or not, + * since the caller should be prepared to reinitialise it. + */ + if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) + goto out; /* Don't match with creds that have expired. */ if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) return 0; +out: return (rc->cr_uid == acred->uid); } @@ -1241,6 +1258,7 @@ static struct rpc_authops authgss_ops = { static struct rpc_credops gss_credops = { .cr_name = "AUTH_GSS", .crdestroy = gss_destroy_cred, + .cr_init = gss_cred_init, .crmatch = gss_match, .crmarshal = gss_marshal, .crrefresh = gss_refresh, diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index e4ada15ed856..23632d84d8d7 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -420,7 +420,8 @@ static int rsc_parse(struct cache_detail *cd, gss_mech_put(gm); goto out; } - if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) { + status = gss_import_sec_context(buf, len, gm, &rsci.mechctx); + if (status) { gss_mech_put(gm); goto out; } @@ -586,6 +587,20 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci, } static int +gss_write_null_verf(struct svc_rqst *rqstp) +{ + u32 *p; + + svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL)); + p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len; + /* don't really need to check if head->iov_len > PAGE_SIZE ... */ + *p++ = 0; + if (!xdr_ressize_check(rqstp, p)) + return -1; + return 0; +} + +static int gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq) { u32 xdr_seq; @@ -741,6 +756,21 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) return SVC_OK; } +static inline int +gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) +{ + struct rsc *rsci; + + if (rsip->major_status != GSS_S_COMPLETE) + return gss_write_null_verf(rqstp); + rsci = gss_svc_searchbyctx(&rsip->out_handle); + if (rsci == NULL) { + rsip->major_status = GSS_S_NO_CONTEXT; + return gss_write_null_verf(rqstp); + } + return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); +} + /* * Accept an rpcsec packet. * If context establishment, punt to user space @@ -876,11 +906,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) case -ENOENT: goto drop; case 0: - rsci = gss_svc_searchbyctx(&rsip->out_handle); - if (!rsci) { - goto drop; - } - if (gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN)) + if (gss_write_init_verf(rqstp, rsip)) goto drop; if (resv->iov_len + 4 > PAGE_SIZE) goto drop; diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 1b3ed4fd1987..df14b6bfbf10 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -75,7 +75,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) atomic_set(&cred->uc_count, 1); cred->uc_flags = RPCAUTH_CRED_UPTODATE; - if (flags & RPC_TASK_ROOTCREDS) { + if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { cred->uc_uid = 0; cred->uc_gid = 0; cred->uc_gids[0] = NOGROUP; @@ -108,12 +108,12 @@ unx_destroy_cred(struct rpc_cred *cred) * request root creds (e.g. for NFS swapping). */ static int -unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) +unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) { struct unx_cred *cred = (struct unx_cred *) rcred; int i; - if (!(taskflags & RPC_TASK_ROOTCREDS)) { + if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { int groups; if (cred->uc_uid != acred->uid diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9764c80ab0b2..a5c0c7b6e151 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -38,44 +38,42 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly; #define RPC_UPCALL_TIMEOUT (30*HZ) -static void -__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err) +static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, + void (*destroy_msg)(struct rpc_pipe_msg *), int err) { struct rpc_pipe_msg *msg; - void (*destroy_msg)(struct rpc_pipe_msg *); - destroy_msg = rpci->ops->destroy_msg; - while (!list_empty(head)) { + if (list_empty(head)) + return; + do { msg = list_entry(head->next, struct rpc_pipe_msg, list); - list_del_init(&msg->list); + list_del(&msg->list); msg->errno = err; destroy_msg(msg); - } -} - -static void -__rpc_purge_upcall(struct inode *inode, int err) -{ - struct rpc_inode *rpci = RPC_I(inode); - - __rpc_purge_list(rpci, &rpci->pipe, err); - rpci->pipelen = 0; + } while (!list_empty(head)); wake_up(&rpci->waitq); } static void rpc_timeout_upcall_queue(void *data) { + LIST_HEAD(free_list); struct rpc_inode *rpci = (struct rpc_inode *)data; struct inode *inode = &rpci->vfs_inode; + void (*destroy_msg)(struct rpc_pipe_msg *); - mutex_lock(&inode->i_mutex); - if (rpci->ops == NULL) - goto out; - if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) - __rpc_purge_upcall(inode, -ETIMEDOUT); -out: - mutex_unlock(&inode->i_mutex); + spin_lock(&inode->i_lock); + if (rpci->ops == NULL) { + spin_unlock(&inode->i_lock); + return; + } + destroy_msg = rpci->ops->destroy_msg; + if (rpci->nreaders == 0) { + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; + } + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); } int @@ -84,7 +82,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) struct rpc_inode *rpci = RPC_I(inode); int res = -EPIPE; - mutex_lock(&inode->i_mutex); + spin_lock(&inode->i_lock); if (rpci->ops == NULL) goto out; if (rpci->nreaders) { @@ -100,7 +98,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) res = 0; } out: - mutex_unlock(&inode->i_mutex); + spin_unlock(&inode->i_lock); wake_up(&rpci->waitq); return res; } @@ -115,21 +113,29 @@ static void rpc_close_pipes(struct inode *inode) { struct rpc_inode *rpci = RPC_I(inode); + struct rpc_pipe_ops *ops; mutex_lock(&inode->i_mutex); - if (rpci->ops != NULL) { + ops = rpci->ops; + if (ops != NULL) { + LIST_HEAD(free_list); + + spin_lock(&inode->i_lock); rpci->nreaders = 0; - __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE); - __rpc_purge_upcall(inode, -EPIPE); - rpci->nwriters = 0; - if (rpci->ops->release_pipe) - rpci->ops->release_pipe(inode); + list_splice_init(&rpci->in_upcall, &free_list); + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; rpci->ops = NULL; + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); + rpci->nwriters = 0; + if (ops->release_pipe) + ops->release_pipe(inode); + cancel_delayed_work(&rpci->queue_timeout); + flush_scheduled_work(); } rpc_inode_setowner(inode, NULL); mutex_unlock(&inode->i_mutex); - cancel_delayed_work(&rpci->queue_timeout); - flush_scheduled_work(); } static struct inode * @@ -177,16 +183,26 @@ rpc_pipe_release(struct inode *inode, struct file *filp) goto out; msg = (struct rpc_pipe_msg *)filp->private_data; if (msg != NULL) { + spin_lock(&inode->i_lock); msg->errno = -EAGAIN; - list_del_init(&msg->list); + list_del(&msg->list); + spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } if (filp->f_mode & FMODE_WRITE) rpci->nwriters --; - if (filp->f_mode & FMODE_READ) + if (filp->f_mode & FMODE_READ) { rpci->nreaders --; - if (!rpci->nreaders) - __rpc_purge_upcall(inode, -EAGAIN); + if (rpci->nreaders == 0) { + LIST_HEAD(free_list); + spin_lock(&inode->i_lock); + list_splice_init(&rpci->pipe, &free_list); + rpci->pipelen = 0; + spin_unlock(&inode->i_lock); + rpc_purge_list(rpci, &free_list, + rpci->ops->destroy_msg, -EAGAIN); + } + } if (rpci->ops->release_pipe) rpci->ops->release_pipe(inode); out: @@ -209,6 +225,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) } msg = filp->private_data; if (msg == NULL) { + spin_lock(&inode->i_lock); if (!list_empty(&rpci->pipe)) { msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, @@ -218,6 +235,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) filp->private_data = msg; msg->copied = 0; } + spin_unlock(&inode->i_lock); if (msg == NULL) goto out_unlock; } @@ -225,7 +243,9 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) res = rpci->ops->upcall(filp, msg, buf, len); if (res < 0 || msg->len == msg->copied) { filp->private_data = NULL; - list_del_init(&msg->list); + spin_lock(&inode->i_lock); + list_del(&msg->list); + spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } out_unlock: @@ -610,7 +630,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) return ERR_PTR(error); dir = nd->dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(nd); + dentry = lookup_one_len(nd->last.name, nd->dentry, nd->last.len); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -672,7 +692,7 @@ rpc_rmdir(char *path) return error; dir = nd.dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(&nd); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; @@ -733,7 +753,7 @@ rpc_unlink(char *path) return error; dir = nd.dentry->d_inode; mutex_lock(&dir->i_mutex); - dentry = lookup_hash(&nd); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 7415406aa1ae..802d4fe0f55c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -908,10 +908,10 @@ void rpc_release_task(struct rpc_task *task) /** * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it - * @clnt - pointer to RPC client - * @flags - RPC flags - * @ops - RPC call ops - * @data - user call data + * @clnt: pointer to RPC client + * @flags: RPC flags + * @ops: RPC call ops + * @data: user call data */ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *ops, @@ -930,6 +930,7 @@ EXPORT_SYMBOL(rpc_run_task); /** * rpc_find_parent - find the parent of a child task. * @child: child task + * @parent: parent task * * Checks that the parent task is still sleeping on the * queue 'childq'. If so returns a pointer to the parent. diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index e67613e4eb18..50580620e897 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1527,6 +1527,7 @@ svc_defer(struct cache_req *req) dr->handle.owner = rqstp->rq_server; dr->prot = rqstp->rq_prot; dr->addr = rqstp->rq_addr; + dr->daddr = rqstp->rq_daddr; dr->argslen = rqstp->rq_arg.len >> 2; memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2); } @@ -1552,6 +1553,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp) rqstp->rq_arg.len = dr->argslen<<2; rqstp->rq_prot = dr->prot; rqstp->rq_addr = dr->addr; + rqstp->rq_daddr = dr->daddr; return dr->argslen<<2; } diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig index 05ab18e62dee..3891cc00087d 100644 --- a/net/tipc/Kconfig +++ b/net/tipc/Kconfig @@ -8,7 +8,12 @@ menu "TIPC Configuration (EXPERIMENTAL)" config TIPC tristate "The TIPC Protocol (EXPERIMENTAL)" ---help--- - TBD. + The Transparent Inter Process Communication (TIPC) protocol is + specially designed for intra cluster communication. This protocol + originates from Ericsson where it has been used in carrier grade + cluster applications for many years. + + For more information about TIPC, see http://tipc.sourceforge.net. This protocol support is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you diff --git a/net/tipc/addr.c b/net/tipc/addr.c index eca22260c98c..0be25e175b93 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -47,7 +47,7 @@ u32 tipc_get_addr(void) } /** - * addr_domain_valid - validates a network domain address + * tipc_addr_domain_valid - validates a network domain address * * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, * where Z, C, and N are non-zero and do not exceed the configured limits. @@ -55,7 +55,7 @@ u32 tipc_get_addr(void) * Returns 1 if domain address is valid, otherwise 0 */ -int addr_domain_valid(u32 addr) +int tipc_addr_domain_valid(u32 addr) { u32 n = tipc_node(addr); u32 c = tipc_cluster(addr); @@ -79,7 +79,7 @@ int addr_domain_valid(u32 addr) } /** - * addr_node_valid - validates a proposed network address for this node + * tipc_addr_node_valid - validates a proposed network address for this node * * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed * the configured limits. @@ -87,8 +87,8 @@ int addr_domain_valid(u32 addr) * Returns 1 if address can be used, otherwise 0 */ -int addr_node_valid(u32 addr) +int tipc_addr_node_valid(u32 addr) { - return (addr_domain_valid(addr) && tipc_node(addr)); + return (tipc_addr_domain_valid(addr) && tipc_node(addr)); } diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 02ca71783e2e..bcfebb3cbbf3 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -122,7 +122,7 @@ static inline char *addr_string_fill(char *string, u32 addr) return string; } -int addr_domain_valid(u32); -int addr_node_valid(u32 addr); +int tipc_addr_domain_valid(u32); +int tipc_addr_node_valid(u32 addr); #endif diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 9713d622efb8..a7b04f397c12 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -82,7 +82,7 @@ struct bcbearer { struct bearer bearer; struct media media; struct bcbearer_pair bpairs[MAX_BEARERS]; - struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI]; + struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; }; /** @@ -104,7 +104,7 @@ static struct bclink *bclink = NULL; static struct link *bcl = NULL; static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED; -char bc_link_name[] = "multicast-link"; +char tipc_bclink_name[] = "multicast-link"; static inline u32 buf_seqno(struct sk_buff *buf) @@ -178,19 +178,19 @@ static void bclink_retransmit_pkt(u32 after, u32 to) buf = buf->next; } if (buf != NULL) - link_retransmit(bcl, buf, mod(to - after)); + tipc_link_retransmit(bcl, buf, mod(to - after)); spin_unlock_bh(&bc_lock); } /** - * bclink_acknowledge - handle acknowledgement of broadcast packets + * tipc_bclink_acknowledge - handle acknowledgement of broadcast packets * @n_ptr: node that sent acknowledgement info * @acked: broadcast sequence # that has been acknowledged * * Node is locked, bc_lock unlocked. */ -void bclink_acknowledge(struct node *n_ptr, u32 acked) +void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked) { struct sk_buff *crs; struct sk_buff *next; @@ -226,16 +226,16 @@ void bclink_acknowledge(struct node *n_ptr, u32 acked) /* Try resolving broadcast link congestion, if necessary */ if (unlikely(bcl->next_out)) - link_push_queue(bcl); + tipc_link_push_queue(bcl); if (unlikely(released && !list_empty(&bcl->waiting_ports))) - link_wakeup_ports(bcl, 0); + tipc_link_wakeup_ports(bcl, 0); spin_unlock_bh(&bc_lock); } /** * bclink_send_ack - unicast an ACK msg * - * net_lock and node lock set + * tipc_net_lock and node lock set */ static void bclink_send_ack(struct node *n_ptr) @@ -243,13 +243,13 @@ static void bclink_send_ack(struct node *n_ptr) struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1]; if (l_ptr != NULL) - link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } /** * bclink_send_nack- broadcast a NACK msg * - * net_lock and node lock set + * tipc_net_lock and node lock set */ static void bclink_send_nack(struct node *n_ptr) @@ -271,11 +271,11 @@ static void bclink_send_nack(struct node *n_ptr) msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); msg_set_bcast_tag(msg, tipc_own_tag); - if (bearer_send(&bcbearer->bearer, buf, 0)) { + if (tipc_bearer_send(&bcbearer->bearer, buf, 0)) { bcl->stats.sent_nacks++; buf_discard(buf); } else { - bearer_schedule(bcl->b_ptr, bcl); + tipc_bearer_schedule(bcl->b_ptr, bcl); bcl->proto_msg_queue = buf; bcl->stats.bearer_congs++; } @@ -291,12 +291,12 @@ static void bclink_send_nack(struct node *n_ptr) } /** - * bclink_check_gap - send a NACK if a sequence gap exists + * tipc_bclink_check_gap - send a NACK if a sequence gap exists * - * net_lock and node lock set + * tipc_net_lock and node lock set */ -void bclink_check_gap(struct node *n_ptr, u32 last_sent) +void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent) { if (!n_ptr->bclink.supported || less_eq(last_sent, mod(n_ptr->bclink.last_in))) @@ -309,19 +309,19 @@ void bclink_check_gap(struct node *n_ptr, u32 last_sent) } /** - * bclink_peek_nack - process a NACK msg meant for another node + * tipc_bclink_peek_nack - process a NACK msg meant for another node * - * Only net_lock set. + * Only tipc_net_lock set. */ -void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) +void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) { - struct node *n_ptr = node_find(dest); + struct node *n_ptr = tipc_node_find(dest); u32 my_after, my_to; - if (unlikely(!n_ptr || !node_is_up(n_ptr))) + if (unlikely(!n_ptr || !tipc_node_is_up(n_ptr))) return; - node_lock(n_ptr); + tipc_node_lock(n_ptr); /* * Modify gap to suppress unnecessary NACKs from this node */ @@ -364,20 +364,20 @@ void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) bclink_set_gap(n_ptr); } } - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); } /** - * bclink_send_msg - broadcast a packet to all nodes in cluster + * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster */ -int bclink_send_msg(struct sk_buff *buf) +int tipc_bclink_send_msg(struct sk_buff *buf) { int res; spin_lock_bh(&bc_lock); - res = link_send_buf(bcl, buf); + res = tipc_link_send_buf(bcl, buf); if (unlikely(res == -ELINKCONG)) buf_discard(buf); else @@ -393,22 +393,22 @@ int bclink_send_msg(struct sk_buff *buf) } /** - * bclink_recv_pkt - receive a broadcast packet, and deliver upwards + * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards * - * net_lock is read_locked, no other locks set + * tipc_net_lock is read_locked, no other locks set */ -void bclink_recv_pkt(struct sk_buff *buf) +void tipc_bclink_recv_pkt(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); - struct node* node = node_find(msg_prevnode(msg)); + struct node* node = tipc_node_find(msg_prevnode(msg)); u32 next_in; u32 seqno; struct sk_buff *deferred; msg_dbg(msg, "<BC<<<"); - if (unlikely(!node || !node_is_up(node) || !node->bclink.supported || + if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || (msg_mc_netid(msg) != tipc_net_id))) { buf_discard(buf); return; @@ -417,14 +417,14 @@ void bclink_recv_pkt(struct sk_buff *buf) if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { msg_dbg(msg, "<BCNACK<<<"); if (msg_destnode(msg) == tipc_own_addr) { - node_lock(node); - bclink_acknowledge(node, msg_bcast_ack(msg)); - node_unlock(node); + tipc_node_lock(node); + tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); + tipc_node_unlock(node); bcl->stats.recv_nacks++; bclink_retransmit_pkt(msg_bcgap_after(msg), msg_bcgap_to(msg)); } else { - bclink_peek_nack(msg_destnode(msg), + tipc_bclink_peek_nack(msg_destnode(msg), msg_bcast_tag(msg), msg_bcgap_after(msg), msg_bcgap_to(msg)); @@ -433,7 +433,7 @@ void bclink_recv_pkt(struct sk_buff *buf) return; } - node_lock(node); + tipc_node_lock(node); receive: deferred = node->bclink.deferred_head; next_in = mod(node->bclink.last_in + 1); @@ -448,26 +448,26 @@ receive: bcl->stats.sent_acks++; } if (likely(msg_isdata(msg))) { - node_unlock(node); - port_recv_mcast(buf, NULL); + tipc_node_unlock(node); + tipc_port_recv_mcast(buf, NULL); } else if (msg_user(msg) == MSG_BUNDLER) { bcl->stats.recv_bundles++; bcl->stats.recv_bundled += msg_msgcnt(msg); - node_unlock(node); - link_recv_bundle(buf); + tipc_node_unlock(node); + tipc_link_recv_bundle(buf); } else if (msg_user(msg) == MSG_FRAGMENTER) { bcl->stats.recv_fragments++; - if (link_recv_fragment(&node->bclink.defragm, - &buf, &msg)) + if (tipc_link_recv_fragment(&node->bclink.defragm, + &buf, &msg)) bcl->stats.recv_fragmented++; - node_unlock(node); - net_route_msg(buf); + tipc_node_unlock(node); + tipc_net_route_msg(buf); } else { - node_unlock(node); - net_route_msg(buf); + tipc_node_unlock(node); + tipc_net_route_msg(buf); } if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { - node_lock(node); + tipc_node_lock(node); buf = deferred; msg = buf_msg(buf); node->bclink.deferred_head = deferred->next; @@ -478,9 +478,9 @@ receive: u32 gap_after = node->bclink.gap_after; u32 gap_to = node->bclink.gap_to; - if (link_defer_pkt(&node->bclink.deferred_head, - &node->bclink.deferred_tail, - buf)) { + if (tipc_link_defer_pkt(&node->bclink.deferred_head, + &node->bclink.deferred_tail, + buf)) { node->bclink.nack_sync++; bcl->stats.deferred_recv++; if (seqno == mod(gap_after + 1)) @@ -497,10 +497,10 @@ receive: bcl->stats.duplicates++; buf_discard(buf); } - node_unlock(node); + tipc_node_unlock(node); } -u32 bclink_get_last_sent(void) +u32 tipc_bclink_get_last_sent(void) { u32 last_sent = mod(bcl->next_out_no - 1); @@ -509,15 +509,15 @@ u32 bclink_get_last_sent(void) return last_sent; } -u32 bclink_acks_missing(struct node *n_ptr) +u32 tipc_bclink_acks_missing(struct node *n_ptr) { return (n_ptr->bclink.supported && - (bclink_get_last_sent() != n_ptr->bclink.acked)); + (tipc_bclink_get_last_sent() != n_ptr->bclink.acked)); } /** - * bcbearer_send - send a packet through the broadcast pseudo-bearer + * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer * * Send through as many bearers as necessary to reach all nodes * that support TIPC multicasting. @@ -525,9 +525,9 @@ u32 bclink_acks_missing(struct node *n_ptr) * Returns 0 if packet sent successfully, non-zero if not */ -int bcbearer_send(struct sk_buff *buf, - struct tipc_bearer *unused1, - struct tipc_media_addr *unused2) +int tipc_bcbearer_send(struct sk_buff *buf, + struct tipc_bearer *unused1, + struct tipc_media_addr *unused2) { static int send_count = 0; @@ -541,8 +541,8 @@ int bcbearer_send(struct sk_buff *buf, if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; - assert(cluster_bcast_nodes.count != 0); - bcbuf_set_acks(buf, cluster_bcast_nodes.count); + assert(tipc_cltr_bcast_nodes.count != 0); + bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count); msg = buf_msg(buf); msg_set_non_seq(msg); msg_set_mc_netid(msg, tipc_net_id); @@ -555,7 +555,7 @@ int bcbearer_send(struct sk_buff *buf, /* Send buffer over bearers until all targets reached */ - remains = cluster_bcast_nodes; + remains = tipc_cltr_bcast_nodes; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct bearer *p = bcbearer->bpairs[bp_index].primary; @@ -564,7 +564,7 @@ int bcbearer_send(struct sk_buff *buf, if (!p) break; /* no more bearers to try */ - nmap_diff(&remains, &p->nodes, &remains_new); + tipc_nmap_diff(&remains, &p->nodes, &remains_new); if (remains_new.count == remains.count) continue; /* bearer pair doesn't add anything */ @@ -597,10 +597,10 @@ update: } /** - * bcbearer_sort - create sets of bearer pairs used by broadcast bearer + * tipc_bcbearer_sort - create sets of bearer pairs used by broadcast bearer */ -void bcbearer_sort(void) +void tipc_bcbearer_sort(void) { struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp; struct bcbearer_pair *bp_curr; @@ -614,7 +614,7 @@ void bcbearer_sort(void) memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); for (b_index = 0; b_index < MAX_BEARERS; b_index++) { - struct bearer *b = &bearers[b_index]; + struct bearer *b = &tipc_bearers[b_index]; if (!b->active || !b->nodes.count) continue; @@ -630,7 +630,7 @@ void bcbearer_sort(void) bp_curr = bcbearer->bpairs; memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs)); - for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) { + for (pri = TIPC_MAX_LINK_PRI; pri >= 0; pri--) { if (!bp_temp[pri].primary) continue; @@ -638,8 +638,8 @@ void bcbearer_sort(void) bp_curr->primary = bp_temp[pri].primary; if (bp_temp[pri].secondary) { - if (nmap_equal(&bp_temp[pri].primary->nodes, - &bp_temp[pri].secondary->nodes)) { + if (tipc_nmap_equal(&bp_temp[pri].primary->nodes, + &bp_temp[pri].secondary->nodes)) { bp_curr->secondary = bp_temp[pri].secondary; } else { bp_curr++; @@ -654,14 +654,14 @@ void bcbearer_sort(void) } /** - * bcbearer_push - resolve bearer congestion + * tipc_bcbearer_push - resolve bearer congestion * * Forces bclink to push out any unsent packets, until all packets are gone * or congestion reoccurs. * No locks set when function called */ -void bcbearer_push(void) +void tipc_bcbearer_push(void) { struct bearer *b_ptr; @@ -669,20 +669,20 @@ void bcbearer_push(void) b_ptr = &bcbearer->bearer; if (b_ptr->publ.blocked) { b_ptr->publ.blocked = 0; - bearer_lock_push(b_ptr); + tipc_bearer_lock_push(b_ptr); } spin_unlock_bh(&bc_lock); } -int bclink_stats(char *buf, const u32 buf_size) +int tipc_bclink_stats(char *buf, const u32 buf_size) { struct print_buf pb; if (!bcl) return 0; - printbuf_init(&pb, buf, buf_size); + tipc_printbuf_init(&pb, buf, buf_size); spin_lock_bh(&bc_lock); @@ -718,10 +718,10 @@ int bclink_stats(char *buf, const u32 buf_size) : 0); spin_unlock_bh(&bc_lock); - return printbuf_validate(&pb); + return tipc_printbuf_validate(&pb); } -int bclink_reset_stats(void) +int tipc_bclink_reset_stats(void) { if (!bcl) return -ENOPROTOOPT; @@ -732,7 +732,7 @@ int bclink_reset_stats(void) return TIPC_OK; } -int bclink_set_queue_limits(u32 limit) +int tipc_bclink_set_queue_limits(u32 limit) { if (!bcl) return -ENOPROTOOPT; @@ -740,12 +740,12 @@ int bclink_set_queue_limits(u32 limit) return -EINVAL; spin_lock_bh(&bc_lock); - link_set_queue_limits(bcl, limit); + tipc_link_set_queue_limits(bcl, limit); spin_unlock_bh(&bc_lock); return TIPC_OK; } -int bclink_init(void) +int tipc_bclink_init(void) { bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC); bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); @@ -762,7 +762,7 @@ int bclink_init(void) memset(bcbearer, 0, sizeof(struct bcbearer)); INIT_LIST_HEAD(&bcbearer->bearer.cong_links); bcbearer->bearer.media = &bcbearer->media; - bcbearer->media.send_msg = bcbearer_send; + bcbearer->media.send_msg = tipc_bcbearer_send; sprintf(bcbearer->media.name, "tipc-multicast"); bcl = &bclink->link; @@ -772,27 +772,27 @@ int bclink_init(void) bclink->node.lock = SPIN_LOCK_UNLOCKED; bcl->owner = &bclink->node; bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; - link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); + tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); bcl->b_ptr = &bcbearer->bearer; bcl->state = WORKING_WORKING; - sprintf(bcl->name, bc_link_name); + sprintf(bcl->name, tipc_bclink_name); if (BCLINK_LOG_BUF_SIZE) { char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); if (!pb) goto nomem; - printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); + tipc_printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); } return TIPC_OK; } -void bclink_stop(void) +void tipc_bclink_stop(void) { spin_lock_bh(&bc_lock); if (bcbearer) { - link_stop(bcl); + tipc_link_stop(bcl); if (BCLINK_LOG_BUF_SIZE) kfree(bcl->print_buf.buf); bcl = NULL; diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 5430e524b4f9..0e3be2ab3307 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -70,14 +70,14 @@ struct port_list { struct node; -extern char bc_link_name[]; +extern char tipc_bclink_name[]; /** * nmap_get - determine if node exists in a node map */ -static inline int nmap_get(struct node_map *nm_ptr, u32 node) +static inline int tipc_nmap_get(struct node_map *nm_ptr, u32 node) { int n = tipc_node(node); int w = n / WSIZE; @@ -90,7 +90,7 @@ static inline int nmap_get(struct node_map *nm_ptr, u32 node) * nmap_add - add a node to a node map */ -static inline void nmap_add(struct node_map *nm_ptr, u32 node) +static inline void tipc_nmap_add(struct node_map *nm_ptr, u32 node) { int n = tipc_node(node); int w = n / WSIZE; @@ -106,7 +106,7 @@ static inline void nmap_add(struct node_map *nm_ptr, u32 node) * nmap_remove - remove a node from a node map */ -static inline void nmap_remove(struct node_map *nm_ptr, u32 node) +static inline void tipc_nmap_remove(struct node_map *nm_ptr, u32 node) { int n = tipc_node(node); int w = n / WSIZE; @@ -122,7 +122,7 @@ static inline void nmap_remove(struct node_map *nm_ptr, u32 node) * nmap_equal - test for equality of node maps */ -static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b) +static inline int tipc_nmap_equal(struct node_map *nm_a, struct node_map *nm_b) { return !memcmp(nm_a, nm_b, sizeof(*nm_a)); } @@ -134,8 +134,8 @@ static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b) * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) */ -static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b, - struct node_map *nm_diff) +static inline void tipc_nmap_diff(struct node_map *nm_a, struct node_map *nm_b, + struct node_map *nm_diff) { int stop = sizeof(nm_a->map) / sizeof(u32); int w; @@ -159,7 +159,7 @@ static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b, * port_list_add - add a port to a port list, ensuring no duplicates */ -static inline void port_list_add(struct port_list *pl_ptr, u32 port) +static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port) { struct port_list *item = pl_ptr; int i; @@ -194,7 +194,7 @@ static inline void port_list_add(struct port_list *pl_ptr, u32 port) * Note: First item is on stack, so it doesn't need to be released */ -static inline void port_list_free(struct port_list *pl_ptr) +static inline void tipc_port_list_free(struct port_list *pl_ptr) { struct port_list *item; struct port_list *next; @@ -206,18 +206,18 @@ static inline void port_list_free(struct port_list *pl_ptr) } -int bclink_init(void); -void bclink_stop(void); -void bclink_acknowledge(struct node *n_ptr, u32 acked); -int bclink_send_msg(struct sk_buff *buf); -void bclink_recv_pkt(struct sk_buff *buf); -u32 bclink_get_last_sent(void); -u32 bclink_acks_missing(struct node *n_ptr); -void bclink_check_gap(struct node *n_ptr, u32 seqno); -int bclink_stats(char *stats_buf, const u32 buf_size); -int bclink_reset_stats(void); -int bclink_set_queue_limits(u32 limit); -void bcbearer_sort(void); -void bcbearer_push(void); +int tipc_bclink_init(void); +void tipc_bclink_stop(void); +void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked); +int tipc_bclink_send_msg(struct sk_buff *buf); +void tipc_bclink_recv_pkt(struct sk_buff *buf); +u32 tipc_bclink_get_last_sent(void); +u32 tipc_bclink_acks_missing(struct node *n_ptr); +void tipc_bclink_check_gap(struct node *n_ptr, u32 seqno); +int tipc_bclink_stats(char *stats_buf, const u32 buf_size); +int tipc_bclink_reset_stats(void); +int tipc_bclink_set_queue_limits(u32 limit); +void tipc_bcbearer_sort(void); +void tipc_bcbearer_push(void); #endif diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 3dd19fdc5a2c..64dcb0f3a8b2 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -48,7 +48,7 @@ static struct media *media_list = 0; static u32 media_count = 0; -struct bearer *bearers = 0; +struct bearer *tipc_bearers = 0; /** * media_name_valid - validate media name @@ -107,7 +107,7 @@ int tipc_register_media(u32 media_type, u32 i; int res = -EINVAL; - write_lock_bh(&net_lock); + write_lock_bh(&tipc_net_lock); if (!media_list) goto exit; @@ -119,7 +119,8 @@ int tipc_register_media(u32 media_type, warn("Media registration error: no broadcast address supplied\n"); goto exit; } - if (bearer_priority >= TIPC_NUM_LINK_PRI) { + if ((bearer_priority < TIPC_MIN_LINK_PRI) && + (bearer_priority > TIPC_MAX_LINK_PRI)) { warn("Media registration error: priority %u\n", bearer_priority); goto exit; } @@ -164,15 +165,15 @@ int tipc_register_media(u32 media_type, dbg("Media <%s> registered\n", name); res = 0; exit: - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); return res; } /** - * media_addr_printf - record media address in print buffer + * tipc_media_addr_printf - record media address in print buffer */ -void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) +void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) { struct media *m_ptr; u32 media_type; @@ -200,25 +201,25 @@ void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) } /** - * media_get_names - record names of registered media in buffer + * tipc_media_get_names - record names of registered media in buffer */ -struct sk_buff *media_get_names(void) +struct sk_buff *tipc_media_get_names(void) { struct sk_buff *buf; struct media *m_ptr; int i; - buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); + buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); if (!buf) return NULL; - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { - cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, - strlen(m_ptr->name) + 1); + tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, + strlen(m_ptr->name) + 1); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return buf; } @@ -282,7 +283,7 @@ static struct bearer *bearer_find(const char *name) struct bearer *b_ptr; u32 i; - for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { + for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) return b_ptr; } @@ -290,16 +291,16 @@ static struct bearer *bearer_find(const char *name) } /** - * bearer_find - locates bearer object with matching interface name + * tipc_bearer_find_interface - locates bearer object with matching interface name */ -struct bearer *bearer_find_interface(const char *if_name) +struct bearer *tipc_bearer_find_interface(const char *if_name) { struct bearer *b_ptr; char *b_if_name; u32 i; - for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { + for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { if (!b_ptr->active) continue; b_if_name = strchr(b_ptr->publ.name, ':') + 1; @@ -310,54 +311,54 @@ struct bearer *bearer_find_interface(const char *if_name) } /** - * bearer_get_names - record names of bearers in buffer + * tipc_bearer_get_names - record names of bearers in buffer */ -struct sk_buff *bearer_get_names(void) +struct sk_buff *tipc_bearer_get_names(void) { struct sk_buff *buf; struct media *m_ptr; struct bearer *b_ptr; int i, j; - buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); + buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); if (!buf) return NULL; - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { for (j = 0; j < MAX_BEARERS; j++) { - b_ptr = &bearers[j]; + b_ptr = &tipc_bearers[j]; if (b_ptr->active && (b_ptr->media == m_ptr)) { - cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, - b_ptr->publ.name, - strlen(b_ptr->publ.name) + 1); + tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, + b_ptr->publ.name, + strlen(b_ptr->publ.name) + 1); } } } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return buf; } -void bearer_add_dest(struct bearer *b_ptr, u32 dest) +void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest) { - nmap_add(&b_ptr->nodes, dest); - disc_update_link_req(b_ptr->link_req); - bcbearer_sort(); + tipc_nmap_add(&b_ptr->nodes, dest); + tipc_disc_update_link_req(b_ptr->link_req); + tipc_bcbearer_sort(); } -void bearer_remove_dest(struct bearer *b_ptr, u32 dest) +void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest) { - nmap_remove(&b_ptr->nodes, dest); - disc_update_link_req(b_ptr->link_req); - bcbearer_sort(); + tipc_nmap_remove(&b_ptr->nodes, dest); + tipc_disc_update_link_req(b_ptr->link_req); + tipc_bcbearer_sort(); } /* * bearer_push(): Resolve bearer congestion. Force the waiting * links to push out their unsent packets, one packet per link * per iteration, until all packets are gone or congestion reoccurs. - * 'net_lock' is read_locked when this function is called + * 'tipc_net_lock' is read_locked when this function is called * bearer.lock must be taken before calling * Returns binary true(1) ore false(0) */ @@ -371,7 +372,7 @@ static int bearer_push(struct bearer *b_ptr) while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { - res = link_push_packet(ln); + res = tipc_link_push_packet(ln); if (res == PUSH_FAILED) break; if (res == PUSH_FINISHED) @@ -381,7 +382,7 @@ static int bearer_push(struct bearer *b_ptr) return list_empty(&b_ptr->cong_links); } -void bearer_lock_push(struct bearer *b_ptr) +void tipc_bearer_lock_push(struct bearer *b_ptr) { int res; @@ -389,7 +390,7 @@ void bearer_lock_push(struct bearer *b_ptr) res = bearer_push(b_ptr); spin_unlock_bh(&b_ptr->publ.lock); if (res) - bcbearer_push(); + tipc_bcbearer_push(); } @@ -404,7 +405,7 @@ void tipc_continue(struct tipc_bearer *tb_ptr) spin_lock_bh(&b_ptr->publ.lock); b_ptr->continue_count++; if (!list_empty(&b_ptr->cong_links)) - k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr); + tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); b_ptr->publ.blocked = 0; spin_unlock_bh(&b_ptr->publ.lock); } @@ -413,11 +414,11 @@ void tipc_continue(struct tipc_bearer *tb_ptr) * Schedule link for sending of messages after the bearer * has been deblocked by 'continue()'. This method is called * when somebody tries to send a message via this link while - * the bearer is congested. 'net_lock' is in read_lock here + * the bearer is congested. 'tipc_net_lock' is in read_lock here * bearer.lock is busy */ -static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) +static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) { list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); } @@ -426,24 +427,24 @@ static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) * Schedule link for sending of messages after the bearer * has been deblocked by 'continue()'. This method is called * when somebody tries to send a message via this link while - * the bearer is congested. 'net_lock' is in read_lock here, + * the bearer is congested. 'tipc_net_lock' is in read_lock here, * bearer.lock is free */ -void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) +void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) { spin_lock_bh(&b_ptr->publ.lock); - bearer_schedule_unlocked(b_ptr, l_ptr); + tipc_bearer_schedule_unlocked(b_ptr, l_ptr); spin_unlock_bh(&b_ptr->publ.lock); } /* - * bearer_resolve_congestion(): Check if there is bearer congestion, + * tipc_bearer_resolve_congestion(): Check if there is bearer congestion, * and if there is, try to resolve it before returning. - * 'net_lock' is read_locked when this function is called + * 'tipc_net_lock' is read_locked when this function is called */ -int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) +int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) { int res = 1; @@ -451,7 +452,7 @@ int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) return 1; spin_lock_bh(&b_ptr->publ.lock); if (!bearer_push(b_ptr)) { - bearer_schedule_unlocked(b_ptr, l_ptr); + tipc_bearer_schedule_unlocked(b_ptr, l_ptr); res = 0; } spin_unlock_bh(&b_ptr->publ.lock); @@ -476,14 +477,19 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) if (tipc_mode != TIPC_NET_MODE) return -ENOPROTOOPT; + if (!bearer_name_validate(name, &b_name) || - !addr_domain_valid(bcast_scope) || - !in_scope(bcast_scope, tipc_own_addr) || - (priority > TIPC_NUM_LINK_PRI)) + !tipc_addr_domain_valid(bcast_scope) || + !in_scope(bcast_scope, tipc_own_addr)) + return -EINVAL; + + if ((priority < TIPC_MIN_LINK_PRI || + priority > TIPC_MAX_LINK_PRI) && + (priority != TIPC_MEDIA_LINK_PRI)) return -EINVAL; - write_lock_bh(&net_lock); - if (!bearers) + write_lock_bh(&tipc_net_lock); + if (!tipc_bearers) goto failed; m_ptr = media_find(b_name.media_name); @@ -491,22 +497,23 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) warn("No media <%s>\n", b_name.media_name); goto failed; } - if (priority == TIPC_NUM_LINK_PRI) + + if (priority == TIPC_MEDIA_LINK_PRI) priority = m_ptr->priority; restart: bearer_id = MAX_BEARERS; with_this_prio = 1; for (i = MAX_BEARERS; i-- != 0; ) { - if (!bearers[i].active) { + if (!tipc_bearers[i].active) { bearer_id = i; continue; } - if (!strcmp(name, bearers[i].publ.name)) { + if (!strcmp(name, tipc_bearers[i].publ.name)) { warn("Bearer <%s> already enabled\n", name); goto failed; } - if ((bearers[i].priority == priority) && + if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { warn("Third bearer <%s> with priority %u, unable to lower to %u\n", @@ -523,7 +530,7 @@ restart: goto failed; } - b_ptr = &bearers[bearer_id]; + b_ptr = &tipc_bearers[bearer_id]; memset(b_ptr, 0, sizeof(struct bearer)); strcpy(b_ptr->publ.name, name); @@ -542,16 +549,16 @@ restart: INIT_LIST_HEAD(&b_ptr->cong_links); INIT_LIST_HEAD(&b_ptr->links); if (m_ptr->bcast) { - b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr, - bcast_scope, 2); + b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, + bcast_scope, 2); } b_ptr->publ.lock = SPIN_LOCK_UNLOCKED; - write_unlock_bh(&net_lock); - info("Enabled bearer <%s>, discovery domain %s\n", - name, addr_string_fill(addr_string, bcast_scope)); + write_unlock_bh(&tipc_net_lock); + info("Enabled bearer <%s>, discovery domain %s, priority %u\n", + name, addr_string_fill(addr_string, bcast_scope), priority); return 0; failed: - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); return res; } @@ -569,11 +576,11 @@ int tipc_block_bearer(const char *name) if (tipc_mode != TIPC_NET_MODE) return -ENOPROTOOPT; - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); b_ptr = bearer_find(name); if (!b_ptr) { warn("Attempt to block unknown bearer <%s>\n", name); - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return -EINVAL; } @@ -583,11 +590,11 @@ int tipc_block_bearer(const char *name) struct node *n_ptr = l_ptr->owner; spin_lock_bh(&n_ptr->lock); - link_reset(l_ptr); + tipc_link_reset(l_ptr); spin_unlock_bh(&n_ptr->lock); } spin_unlock_bh(&b_ptr->publ.lock); - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); info("Blocked bearer <%s>\n", name); return TIPC_OK; } @@ -595,7 +602,7 @@ int tipc_block_bearer(const char *name) /** * bearer_disable - * - * Note: This routine assumes caller holds net_lock. + * Note: This routine assumes caller holds tipc_net_lock. */ static int bearer_disable(const char *name) @@ -613,19 +620,19 @@ static int bearer_disable(const char *name) return -EINVAL; } - disc_stop_link_req(b_ptr->link_req); + tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->publ.lock); b_ptr->link_req = NULL; b_ptr->publ.blocked = 1; if (b_ptr->media->disable_bearer) { spin_unlock_bh(&b_ptr->publ.lock); - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); b_ptr->media->disable_bearer(&b_ptr->publ); - write_lock_bh(&net_lock); + write_lock_bh(&tipc_net_lock); spin_lock_bh(&b_ptr->publ.lock); } list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { - link_delete(l_ptr); + tipc_link_delete(l_ptr); } spin_unlock_bh(&b_ptr->publ.lock); info("Disabled bearer <%s>\n", name); @@ -637,54 +644,54 @@ int tipc_disable_bearer(const char *name) { int res; - write_lock_bh(&net_lock); + write_lock_bh(&tipc_net_lock); res = bearer_disable(name); - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); return res; } -int bearer_init(void) +int tipc_bearer_init(void) { int res; - write_lock_bh(&net_lock); - bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC); + write_lock_bh(&tipc_net_lock); + tipc_bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC); media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC); - if (bearers && media_list) { - memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer)); + if (tipc_bearers && media_list) { + memset(tipc_bearers, 0, MAX_BEARERS * sizeof(struct bearer)); memset(media_list, 0, MAX_MEDIA * sizeof(struct media)); res = TIPC_OK; } else { - kfree(bearers); + kfree(tipc_bearers); kfree(media_list); - bearers = 0; + tipc_bearers = 0; media_list = 0; res = -ENOMEM; } - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); return res; } -void bearer_stop(void) +void tipc_bearer_stop(void) { u32 i; - if (!bearers) + if (!tipc_bearers) return; for (i = 0; i < MAX_BEARERS; i++) { - if (bearers[i].active) - bearers[i].publ.blocked = 1; + if (tipc_bearers[i].active) + tipc_bearers[i].publ.blocked = 1; } for (i = 0; i < MAX_BEARERS; i++) { - if (bearers[i].active) - bearer_disable(bearers[i].publ.name); + if (tipc_bearers[i].active) + bearer_disable(tipc_bearers[i].publ.name); } - kfree(bearers); + kfree(tipc_bearers); kfree(media_list); - bearers = 0; + tipc_bearers = 0; media_list = 0; media_count = 0; } diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 21e63d3f0183..c4e7c1c3655b 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -37,7 +37,7 @@ #ifndef _TIPC_BEARER_H #define _TIPC_BEARER_H -#include <net/tipc/tipc_bearer.h> +#include "core.h" #include "bcast.h" #define MAX_BEARERS 8 @@ -114,26 +114,24 @@ struct bearer_name { struct link; -extern struct bearer *bearers; +extern struct bearer *tipc_bearers; -void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); -struct sk_buff *media_get_names(void); +void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); +struct sk_buff *tipc_media_get_names(void); -struct sk_buff *bearer_get_names(void); -void bearer_add_dest(struct bearer *b_ptr, u32 dest); -void bearer_remove_dest(struct bearer *b_ptr, u32 dest); -void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); -struct bearer *bearer_find_interface(const char *if_name); -int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); -int bearer_init(void); -void bearer_stop(void); -int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr, - struct tipc_media_addr *dest); -void bearer_lock_push(struct bearer *b_ptr); +struct sk_buff *tipc_bearer_get_names(void); +void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest); +void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest); +void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); +struct bearer *tipc_bearer_find_interface(const char *if_name); +int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); +int tipc_bearer_init(void); +void tipc_bearer_stop(void); +void tipc_bearer_lock_push(struct bearer *b_ptr); /** - * bearer_send- sends buffer to destination over bearer + * tipc_bearer_send- sends buffer to destination over bearer * * Returns true (1) if successful, or false (0) if unable to send * @@ -150,23 +148,23 @@ void bearer_lock_push(struct bearer *b_ptr); * and let TIPC's link code deal with the undelivered message. */ -static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf, - struct tipc_media_addr *dest) +static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf, + struct tipc_media_addr *dest) { return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); } /** - * bearer_congested - determines if bearer is currently congested + * tipc_bearer_congested - determines if bearer is currently congested */ -static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr) +static inline int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) { if (unlikely(b_ptr->publ.blocked)) return 1; if (likely(list_empty(&b_ptr->cong_links))) return 0; - return !bearer_resolve_congestion(b_ptr, l_ptr); + return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); } #endif diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index f0f7bac51d41..ab974ca19371 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c @@ -44,15 +44,15 @@ #include "msg.h" #include "bearer.h" -void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, - u32 lower, u32 upper); -struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest); +void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, + u32 lower, u32 upper); +struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest); -struct node **local_nodes = 0; -struct node_map cluster_bcast_nodes = {0,{0,}}; -u32 highest_allowed_slave = 0; +struct node **tipc_local_nodes = 0; +struct node_map tipc_cltr_bcast_nodes = {0,{0,}}; +u32 tipc_highest_allowed_slave = 0; -struct cluster *cluster_create(u32 addr) +struct cluster *tipc_cltr_create(u32 addr) { struct _zone *z_ptr; struct cluster *c_ptr; @@ -77,16 +77,16 @@ struct cluster *cluster_create(u32 addr) } memset(c_ptr->nodes, 0, alloc); if (in_own_cluster(addr)) - local_nodes = c_ptr->nodes; + tipc_local_nodes = c_ptr->nodes; c_ptr->highest_slave = LOWEST_SLAVE - 1; c_ptr->highest_node = 0; - z_ptr = zone_find(tipc_zone(addr)); + z_ptr = tipc_zone_find(tipc_zone(addr)); if (z_ptr == NULL) { - z_ptr = zone_create(addr); + z_ptr = tipc_zone_create(addr); } if (z_ptr != NULL) { - zone_attach_cluster(z_ptr, c_ptr); + tipc_zone_attach_cluster(z_ptr, c_ptr); c_ptr->owner = z_ptr; } else { @@ -97,23 +97,23 @@ struct cluster *cluster_create(u32 addr) return c_ptr; } -void cluster_delete(struct cluster *c_ptr) +void tipc_cltr_delete(struct cluster *c_ptr) { u32 n_num; if (!c_ptr) return; for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) { - node_delete(c_ptr->nodes[n_num]); + tipc_node_delete(c_ptr->nodes[n_num]); } for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) { - node_delete(c_ptr->nodes[n_num]); + tipc_node_delete(c_ptr->nodes[n_num]); } kfree(c_ptr->nodes); kfree(c_ptr); } -u32 cluster_next_node(struct cluster *c_ptr, u32 addr) +u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr) { struct node *n_ptr; u32 n_num = tipc_node(addr) + 1; @@ -122,24 +122,24 @@ u32 cluster_next_node(struct cluster *c_ptr, u32 addr) return addr; for (; n_num <= c_ptr->highest_node; n_num++) { n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && node_has_active_links(n_ptr)) + if (n_ptr && tipc_node_has_active_links(n_ptr)) return n_ptr->addr; } for (n_num = 1; n_num < tipc_node(addr); n_num++) { n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && node_has_active_links(n_ptr)) + if (n_ptr && tipc_node_has_active_links(n_ptr)) return n_ptr->addr; } return 0; } -void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr) +void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr) { u32 n_num = tipc_node(n_ptr->addr); u32 max_n_num = tipc_max_nodes; if (in_own_cluster(n_ptr->addr)) - max_n_num = highest_allowed_slave; + max_n_num = tipc_highest_allowed_slave; assert(n_num > 0); assert(n_num <= max_n_num); assert(c_ptr->nodes[n_num] == 0); @@ -149,12 +149,12 @@ void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr) } /** - * cluster_select_router - select router to a cluster + * tipc_cltr_select_router - select router to a cluster * * Uses deterministic and fair algorithm. */ -u32 cluster_select_router(struct cluster *c_ptr, u32 ref) +u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref) { u32 n_num; u32 ulim = c_ptr->highest_node; @@ -174,29 +174,29 @@ u32 cluster_select_router(struct cluster *c_ptr, u32 ref) /* Lookup upwards with wrap-around */ do { - if (node_is_up(c_ptr->nodes[n_num])) + if (tipc_node_is_up(c_ptr->nodes[n_num])) break; } while (++n_num <= ulim); if (n_num > ulim) { n_num = 1; do { - if (node_is_up(c_ptr->nodes[n_num])) + if (tipc_node_is_up(c_ptr->nodes[n_num])) break; } while (++n_num < tstart); if (n_num == tstart) return 0; } assert(n_num <= ulim); - return node_select_router(c_ptr->nodes[n_num], ref); + return tipc_node_select_router(c_ptr->nodes[n_num], ref); } /** - * cluster_select_node - select destination node within a remote cluster + * tipc_cltr_select_node - select destination node within a remote cluster * * Uses deterministic and fair algorithm. */ -struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) +struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector) { u32 n_num; u32 mask = tipc_max_nodes; @@ -215,11 +215,11 @@ struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) /* Lookup upwards with wrap-around */ for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) { - if (node_has_active_links(c_ptr->nodes[n_num])) + if (tipc_node_has_active_links(c_ptr->nodes[n_num])) return c_ptr->nodes[n_num]; } for (n_num = 1; n_num < start_entry; n_num++) { - if (node_has_active_links(c_ptr->nodes[n_num])) + if (tipc_node_has_active_links(c_ptr->nodes[n_num])) return c_ptr->nodes[n_num]; } return 0; @@ -229,7 +229,7 @@ struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) * Routing table management: See description in node.c */ -struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest) +struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) { u32 size = INT_H_SIZE + data_size; struct sk_buff *buf = buf_acquire(size); @@ -243,39 +243,39 @@ struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest) return buf; } -void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, +void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lower, u32 upper) { - struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); + struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr); struct tipc_msg *msg; if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, dest); msg_set_type(msg, ROUTE_ADDITION); - cluster_multicast(c_ptr, buf, lower, upper); + tipc_cltr_multicast(c_ptr, buf, lower, upper); } else { warn("Memory squeeze: broadcast of new route failed\n"); } } -void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, - u32 lower, u32 upper) +void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, + u32 lower, u32 upper) { - struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); + struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr); struct tipc_msg *msg; if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, dest); msg_set_type(msg, ROUTE_REMOVAL); - cluster_multicast(c_ptr, buf, lower, upper); + tipc_cltr_multicast(c_ptr, buf, lower, upper); } else { warn("Memory squeeze: broadcast of lost route failed\n"); } } -void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) +void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest) { struct sk_buff *buf; struct tipc_msg *msg; @@ -288,21 +288,21 @@ void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) assert(in_own_cluster(c_ptr->addr)); if (highest <= LOWEST_SLAVE) return; - buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1, - c_ptr->addr); + buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1, + c_ptr->addr); if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, c_ptr->addr); msg_set_type(msg, SLAVE_ROUTING_TABLE); for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) { if (c_ptr->nodes[n_num] && - node_has_active_links(c_ptr->nodes[n_num])) { + tipc_node_has_active_links(c_ptr->nodes[n_num])) { send = 1; msg_set_dataoctet(msg, n_num); } } if (send) - link_send(buf, dest, dest); + tipc_link_send(buf, dest, dest); else buf_discard(buf); } else { @@ -310,7 +310,7 @@ void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) } } -void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) +void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest) { struct sk_buff *buf; struct tipc_msg *msg; @@ -323,20 +323,20 @@ void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) assert(!is_slave(dest)); assert(in_own_cluster(dest)); highest = c_ptr->highest_node; - buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr); + buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr); if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, c_ptr->addr); msg_set_type(msg, EXT_ROUTING_TABLE); for (n_num = 1; n_num <= highest; n_num++) { if (c_ptr->nodes[n_num] && - node_has_active_links(c_ptr->nodes[n_num])) { + tipc_node_has_active_links(c_ptr->nodes[n_num])) { send = 1; msg_set_dataoctet(msg, n_num); } } if (send) - link_send(buf, dest, dest); + tipc_link_send(buf, dest, dest); else buf_discard(buf); } else { @@ -344,7 +344,7 @@ void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) } } -void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) +void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest) { struct sk_buff *buf; struct tipc_msg *msg; @@ -354,20 +354,20 @@ void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) assert(is_slave(dest)); assert(in_own_cluster(c_ptr->addr)); - buf = cluster_prepare_routing_msg(highest, c_ptr->addr); + buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr); if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, c_ptr->addr); msg_set_type(msg, LOCAL_ROUTING_TABLE); for (n_num = 1; n_num <= highest; n_num++) { if (c_ptr->nodes[n_num] && - node_has_active_links(c_ptr->nodes[n_num])) { + tipc_node_has_active_links(c_ptr->nodes[n_num])) { send = 1; msg_set_dataoctet(msg, n_num); } } if (send) - link_send(buf, dest, dest); + tipc_link_send(buf, dest, dest); else buf_discard(buf); } else { @@ -375,7 +375,7 @@ void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) } } -void cluster_recv_routing_table(struct sk_buff *buf) +void tipc_cltr_recv_routing_table(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); struct cluster *c_ptr; @@ -388,9 +388,9 @@ void cluster_recv_routing_table(struct sk_buff *buf) u32 c_num; u32 n_num; - c_ptr = cluster_find(rem_node); + c_ptr = tipc_cltr_find(rem_node); if (!c_ptr) { - c_ptr = cluster_create(rem_node); + c_ptr = tipc_cltr_create(rem_node); if (!c_ptr) { buf_discard(buf); return; @@ -412,10 +412,10 @@ void cluster_recv_routing_table(struct sk_buff *buf) u32 addr = tipc_addr(z_num, c_num, n_num); n_ptr = c_ptr->nodes[n_num]; if (!n_ptr) { - n_ptr = node_create(addr); + n_ptr = tipc_node_create(addr); } if (n_ptr) - node_add_router(n_ptr, router); + tipc_node_add_router(n_ptr, router); } } break; @@ -428,10 +428,10 @@ void cluster_recv_routing_table(struct sk_buff *buf) u32 addr = tipc_addr(z_num, c_num, slave_num); n_ptr = c_ptr->nodes[slave_num]; if (!n_ptr) { - n_ptr = node_create(addr); + n_ptr = tipc_node_create(addr); } if (n_ptr) - node_add_router(n_ptr, router); + tipc_node_add_router(n_ptr, router); } } break; @@ -445,9 +445,9 @@ void cluster_recv_routing_table(struct sk_buff *buf) } n_ptr = c_ptr->nodes[tipc_node(rem_node)]; if (!n_ptr) - n_ptr = node_create(rem_node); + n_ptr = tipc_node_create(rem_node); if (n_ptr) - node_add_router(n_ptr, router); + tipc_node_add_router(n_ptr, router); break; case ROUTE_REMOVAL: if (!is_slave(tipc_own_addr)) { @@ -459,7 +459,7 @@ void cluster_recv_routing_table(struct sk_buff *buf) } n_ptr = c_ptr->nodes[tipc_node(rem_node)]; if (n_ptr) - node_remove_router(n_ptr, router); + tipc_node_remove_router(n_ptr, router); break; default: assert(!"Illegal routing manager message received\n"); @@ -467,7 +467,7 @@ void cluster_recv_routing_table(struct sk_buff *buf) buf_discard(buf); } -void cluster_remove_as_router(struct cluster *c_ptr, u32 router) +void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router) { u32 start_entry; u32 tstop; @@ -486,17 +486,17 @@ void cluster_remove_as_router(struct cluster *c_ptr, u32 router) for (n_num = start_entry; n_num <= tstop; n_num++) { if (c_ptr->nodes[n_num]) { - node_remove_router(c_ptr->nodes[n_num], router); + tipc_node_remove_router(c_ptr->nodes[n_num], router); } } } /** - * cluster_multicast - multicast message to local nodes + * tipc_cltr_multicast - multicast message to local nodes */ -void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, - u32 lower, u32 upper) +void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf, + u32 lower, u32 upper) { struct sk_buff *buf_copy; struct node *n_ptr; @@ -505,9 +505,9 @@ void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, assert(lower <= upper); assert(((lower >= 1) && (lower <= tipc_max_nodes)) || - ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave))); + ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave))); assert(((upper >= 1) && (upper <= tipc_max_nodes)) || - ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave))); + ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave))); assert(in_own_cluster(c_ptr->addr)); tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; @@ -515,22 +515,22 @@ void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, tstop = upper; for (n_num = lower; n_num <= tstop; n_num++) { n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && node_has_active_links(n_ptr)) { + if (n_ptr && tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (buf_copy == NULL) break; msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); - link_send(buf_copy, n_ptr->addr, n_ptr->addr); + tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); } } buf_discard(buf); } /** - * cluster_broadcast - broadcast message to all nodes within cluster + * tipc_cltr_broadcast - broadcast message to all nodes within cluster */ -void cluster_broadcast(struct sk_buff *buf) +void tipc_cltr_broadcast(struct sk_buff *buf) { struct sk_buff *buf_copy; struct cluster *c_ptr; @@ -541,7 +541,7 @@ void cluster_broadcast(struct sk_buff *buf) u32 node_type; if (tipc_mode == TIPC_NET_MODE) { - c_ptr = cluster_find(tipc_own_addr); + c_ptr = tipc_cltr_find(tipc_own_addr); assert(in_own_cluster(c_ptr->addr)); /* For now */ /* Send to standard nodes, then repeat loop sending to slaves */ @@ -550,14 +550,14 @@ void cluster_broadcast(struct sk_buff *buf) for (node_type = 1; node_type <= 2; node_type++) { for (n_num = tstart; n_num <= tstop; n_num++) { n_ptr = c_ptr->nodes[n_num]; - if (n_ptr && node_has_active_links(n_ptr)) { + if (n_ptr && tipc_node_has_active_links(n_ptr)) { buf_copy = skb_copy(buf, GFP_ATOMIC); if (buf_copy == NULL) goto exit; msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); - link_send(buf_copy, n_ptr->addr, - n_ptr->addr); + tipc_link_send(buf_copy, n_ptr->addr, + n_ptr->addr); } } tstart = LOWEST_SLAVE; @@ -568,9 +568,9 @@ exit: buf_discard(buf); } -int cluster_init(void) +int tipc_cltr_init(void) { - highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; - return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM; + tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; + return tipc_cltr_create(tipc_own_addr) ? TIPC_OK : -ENOMEM; } diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h index 1ffb095991df..9963642e1058 100644 --- a/net/tipc/cluster.h +++ b/net/tipc/cluster.h @@ -60,29 +60,29 @@ struct cluster { }; -extern struct node **local_nodes; -extern u32 highest_allowed_slave; -extern struct node_map cluster_bcast_nodes; +extern struct node **tipc_local_nodes; +extern u32 tipc_highest_allowed_slave; +extern struct node_map tipc_cltr_bcast_nodes; -void cluster_remove_as_router(struct cluster *c_ptr, u32 router); -void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest); -struct node *cluster_select_node(struct cluster *c_ptr, u32 selector); -u32 cluster_select_router(struct cluster *c_ptr, u32 ref); -void cluster_recv_routing_table(struct sk_buff *buf); -struct cluster *cluster_create(u32 addr); -void cluster_delete(struct cluster *c_ptr); -void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr); -void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest); -void cluster_broadcast(struct sk_buff *buf); -int cluster_init(void); -u32 cluster_next_node(struct cluster *c_ptr, u32 addr); -void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); -void cluster_send_local_routes(struct cluster *c_ptr, u32 dest); -void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); +void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router); +void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest); +struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector); +u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref); +void tipc_cltr_recv_routing_table(struct sk_buff *buf); +struct cluster *tipc_cltr_create(u32 addr); +void tipc_cltr_delete(struct cluster *c_ptr); +void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr); +void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest); +void tipc_cltr_broadcast(struct sk_buff *buf); +int tipc_cltr_init(void); +u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr); +void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); +void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest); +void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); -static inline struct cluster *cluster_find(u32 addr) +static inline struct cluster *tipc_cltr_find(u32 addr) { - struct _zone *z_ptr = zone_find(addr); + struct _zone *z_ptr = tipc_zone_find(addr); if (z_ptr) return z_ptr->clusters[1]; diff --git a/net/tipc/config.c b/net/tipc/config.c index 8ddef4fce2c2..3c8e6740e5ae 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -70,13 +70,13 @@ static int req_tlv_space; /* request message TLV area size */ static int rep_headroom; /* reply message headroom to use */ -void cfg_link_event(u32 addr, char *name, int up) +void tipc_cfg_link_event(u32 addr, char *name, int up) { /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ } -struct sk_buff *cfg_reply_alloc(int payload_size) +struct sk_buff *tipc_cfg_reply_alloc(int payload_size) { struct sk_buff *buf; @@ -86,14 +86,14 @@ struct sk_buff *cfg_reply_alloc(int payload_size) return buf; } -int cfg_append_tlv(struct sk_buff *buf, int tlv_type, - void *tlv_data, int tlv_data_size) +int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, + void *tlv_data, int tlv_data_size) { struct tlv_desc *tlv = (struct tlv_desc *)buf->tail; int new_tlv_space = TLV_SPACE(tlv_data_size); if (skb_tailroom(buf) < new_tlv_space) { - dbg("cfg_append_tlv unable to append TLV\n"); + dbg("tipc_cfg_append_tlv unable to append TLV\n"); return 0; } skb_put(buf, new_tlv_space); @@ -104,28 +104,28 @@ int cfg_append_tlv(struct sk_buff *buf, int tlv_type, return 1; } -struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value) +struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) { struct sk_buff *buf; u32 value_net; - buf = cfg_reply_alloc(TLV_SPACE(sizeof(value))); + buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); if (buf) { value_net = htonl(value); - cfg_append_tlv(buf, tlv_type, &value_net, - sizeof(value_net)); + tipc_cfg_append_tlv(buf, tlv_type, &value_net, + sizeof(value_net)); } return buf; } -struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string) +struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) { struct sk_buff *buf; int string_len = strlen(string) + 1; - buf = cfg_reply_alloc(TLV_SPACE(string_len)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); if (buf) - cfg_append_tlv(buf, tlv_type, string, string_len); + tipc_cfg_append_tlv(buf, tlv_type, string, string_len); return buf; } @@ -246,7 +246,7 @@ static void cfg_cmd_event(struct tipc_cmd_msg *msg, exit: rmsg.result_len = htonl(msg_sect[1].iov_len); rmsg.retval = htonl(rv); - cfg_respond(msg_sect, 2u, orig); + tipc_cfg_respond(msg_sect, 2u, orig); } #endif @@ -255,26 +255,26 @@ static struct sk_buff *cfg_enable_bearer(void) struct tipc_bearer_config *args; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); if (tipc_enable_bearer(args->name, ntohl(args->detect_scope), ntohl(args->priority))) - return cfg_reply_error_string("unable to enable bearer"); + return tipc_cfg_reply_error_string("unable to enable bearer"); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_disable_bearer(void) { if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) - return cfg_reply_error_string("unable to disable bearer"); + return tipc_cfg_reply_error_string("unable to disable bearer"); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_own_addr(void) @@ -282,25 +282,25 @@ static struct sk_buff *cfg_set_own_addr(void) u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = *(u32 *)TLV_DATA(req_tlv_area); addr = ntohl(addr); if (addr == tipc_own_addr) - return cfg_reply_none(); - if (!addr_node_valid(addr)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (node address)"); + return tipc_cfg_reply_none(); + if (!tipc_addr_node_valid(addr)) + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (node address)"); if (tipc_own_addr) - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change node address once assigned)"); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change node address once assigned)"); spin_unlock_bh(&config_lock); - stop_net(); + tipc_core_stop_net(); tipc_own_addr = addr; - start_net(); + tipc_core_start_net(); spin_lock_bh(&config_lock); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_remote_mng(void) @@ -308,12 +308,12 @@ static struct sk_buff *cfg_set_remote_mng(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); tipc_remote_management = (value != 0); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_max_publications(void) @@ -321,15 +321,15 @@ static struct sk_buff *cfg_set_max_publications(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 1, 65535)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max publications must be 1-65535)"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max publications must be 1-65535)"); tipc_max_publications = value; - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_max_subscriptions(void) @@ -337,15 +337,15 @@ static struct sk_buff *cfg_set_max_subscriptions(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 1, 65535)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max subscriptions must be 1-65535"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max subscriptions must be 1-65535"); tipc_max_subscriptions = value; - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_max_ports(void) @@ -354,31 +354,31 @@ static struct sk_buff *cfg_set_max_ports(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 127, 65535)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max ports must be 127-65535)"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max ports must be 127-65535)"); if (value == tipc_max_ports) - return cfg_reply_none(); + return tipc_cfg_reply_none(); if (atomic_read(&tipc_user_count) > 2) - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max ports while TIPC users exist)"); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change max ports while TIPC users exist)"); spin_unlock_bh(&config_lock); orig_mode = tipc_get_mode(); if (orig_mode == TIPC_NET_MODE) - stop_net(); - stop_core(); + tipc_core_stop_net(); + tipc_core_stop(); tipc_max_ports = value; - start_core(); + tipc_core_start(); if (orig_mode == TIPC_NET_MODE) - start_net(); + tipc_core_start_net(); spin_lock_bh(&config_lock); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *set_net_max(int value, int *parameter) @@ -388,13 +388,13 @@ static struct sk_buff *set_net_max(int value, int *parameter) if (value != *parameter) { orig_mode = tipc_get_mode(); if (orig_mode == TIPC_NET_MODE) - stop_net(); + tipc_core_stop_net(); *parameter = value; if (orig_mode == TIPC_NET_MODE) - start_net(); + tipc_core_start_net(); } - return cfg_reply_none(); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_max_zones(void) @@ -402,12 +402,12 @@ static struct sk_buff *cfg_set_max_zones(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 1, 255)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max zones must be 1-255)"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max zones must be 1-255)"); return set_net_max(value, &tipc_max_zones); } @@ -416,13 +416,13 @@ static struct sk_buff *cfg_set_max_clusters(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != 1) - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (max clusters fixed at 1)"); - return cfg_reply_none(); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (max clusters fixed at 1)"); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_max_nodes(void) @@ -430,12 +430,12 @@ static struct sk_buff *cfg_set_max_nodes(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 8, 2047)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max nodes must be 8-2047)"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max nodes must be 8-2047)"); return set_net_max(value, &tipc_max_nodes); } @@ -444,13 +444,13 @@ static struct sk_buff *cfg_set_max_slaves(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != 0) - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (max secondary nodes fixed at 0)"); - return cfg_reply_none(); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (max secondary nodes fixed at 0)"); + return tipc_cfg_reply_none(); } static struct sk_buff *cfg_set_netid(void) @@ -458,22 +458,22 @@ static struct sk_buff *cfg_set_netid(void) u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 1, 9999)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network id must be 1-9999)"); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network id must be 1-9999)"); if (tipc_own_addr) - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change network id once part of network)"); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change network id once part of network)"); return set_net_max(value, &tipc_net_id); } -struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, - int request_space, int reply_headroom) +struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, + int request_space, int reply_headroom) { struct sk_buff *rep_tlv_buf; @@ -490,19 +490,19 @@ struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, if (likely(orig_node == tipc_own_addr)) { /* command is permitted */ } else if (cmd >= 0x8000) { - rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot be done remotely)"); + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot be done remotely)"); goto exit; } else if (!tipc_remote_management) { - rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE); + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); goto exit; } else if (cmd >= 0x4000) { u32 domain = 0; - if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || + if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || (domain != orig_node)) { - rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); goto exit; } } @@ -511,50 +511,50 @@ struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, switch (cmd) { case TIPC_CMD_NOOP: - rep_tlv_buf = cfg_reply_none(); + rep_tlv_buf = tipc_cfg_reply_none(); break; case TIPC_CMD_GET_NODES: - rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); break; case TIPC_CMD_GET_LINKS: - rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); break; case TIPC_CMD_SHOW_LINK_STATS: - rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); break; case TIPC_CMD_RESET_LINK_STATS: - rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); break; case TIPC_CMD_SHOW_NAME_TABLE: - rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); break; case TIPC_CMD_GET_BEARER_NAMES: - rep_tlv_buf = bearer_get_names(); + rep_tlv_buf = tipc_bearer_get_names(); break; case TIPC_CMD_GET_MEDIA_NAMES: - rep_tlv_buf = media_get_names(); + rep_tlv_buf = tipc_media_get_names(); break; case TIPC_CMD_SHOW_PORTS: - rep_tlv_buf = port_get_ports(); + rep_tlv_buf = tipc_port_get_ports(); break; #if 0 case TIPC_CMD_SHOW_PORT_STATS: rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); break; case TIPC_CMD_RESET_PORT_STATS: - rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); + rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); break; #endif case TIPC_CMD_SET_LOG_SIZE: - rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space); break; case TIPC_CMD_DUMP_LOG: - rep_tlv_buf = log_dump(); + rep_tlv_buf = tipc_log_dump(); break; case TIPC_CMD_SET_LINK_TOL: case TIPC_CMD_SET_LINK_PRI: case TIPC_CMD_SET_LINK_WINDOW: - rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd); + rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); break; case TIPC_CMD_ENABLE_BEARER: rep_tlv_buf = cfg_enable_bearer(); @@ -593,31 +593,31 @@ struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, rep_tlv_buf = cfg_set_netid(); break; case TIPC_CMD_GET_REMOTE_MNG: - rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); break; case TIPC_CMD_GET_MAX_PORTS: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); break; case TIPC_CMD_GET_MAX_PUBL: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); break; case TIPC_CMD_GET_MAX_SUBSCR: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); break; case TIPC_CMD_GET_MAX_ZONES: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones); break; case TIPC_CMD_GET_MAX_CLUSTERS: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters); break; case TIPC_CMD_GET_MAX_NODES: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); break; case TIPC_CMD_GET_MAX_SLAVES: - rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves); break; case TIPC_CMD_GET_NETID: - rep_tlv_buf = cfg_reply_unsigned(tipc_net_id); + rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); break; default: rep_tlv_buf = NULL; @@ -655,11 +655,11 @@ static void cfg_named_msg_event(void *userdata, /* Generate reply for request (if can't, return request) */ - rep_buf = cfg_do_cmd(orig->node, - ntohs(req_hdr->tcm_type), - msg + sizeof(*req_hdr), - size - sizeof(*req_hdr), - BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); + rep_buf = tipc_cfg_do_cmd(orig->node, + ntohs(req_hdr->tcm_type), + msg + sizeof(*req_hdr), + size - sizeof(*req_hdr), + BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); if (rep_buf) { skb_push(rep_buf, sizeof(*rep_hdr)); rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; @@ -675,7 +675,7 @@ static void cfg_named_msg_event(void *userdata, tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); } -int cfg_init(void) +int tipc_cfg_init(void) { struct tipc_name_seq seq; int res; @@ -696,7 +696,7 @@ int cfg_init(void) seq.type = TIPC_CFG_SRV; seq.lower = seq.upper = tipc_own_addr; - res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); + res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); if (res) goto failed; @@ -709,7 +709,7 @@ failed: return res; } -void cfg_stop(void) +void tipc_cfg_stop(void) { if (mng.user_ref) { tipc_detach(mng.user_ref); diff --git a/net/tipc/config.h b/net/tipc/config.h index 646377d40454..7a728f954d84 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -39,42 +39,41 @@ /* ---------------------------------------------------------------------- */ -#include <linux/tipc.h> -#include <linux/tipc_config.h> +#include "core.h" #include "link.h" -struct sk_buff *cfg_reply_alloc(int payload_size); -int cfg_append_tlv(struct sk_buff *buf, int tlv_type, - void *tlv_data, int tlv_data_size); -struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value); -struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string); +struct sk_buff *tipc_cfg_reply_alloc(int payload_size); +int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, + void *tlv_data, int tlv_data_size); +struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value); +struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string); -static inline struct sk_buff *cfg_reply_none(void) +static inline struct sk_buff *tipc_cfg_reply_none(void) { - return cfg_reply_alloc(0); + return tipc_cfg_reply_alloc(0); } -static inline struct sk_buff *cfg_reply_unsigned(u32 value) +static inline struct sk_buff *tipc_cfg_reply_unsigned(u32 value) { - return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); + return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); } -static inline struct sk_buff *cfg_reply_error_string(char *string) +static inline struct sk_buff *tipc_cfg_reply_error_string(char *string) { - return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); + return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); } -static inline struct sk_buff *cfg_reply_ultra_string(char *string) +static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string) { - return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); + return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); } -struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, - const void *req_tlv_area, int req_tlv_space, - int headroom); +struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, + const void *req_tlv_area, int req_tlv_space, + int headroom); -void cfg_link_event(u32 addr, char *name, int up); -int cfg_init(void); -void cfg_stop(void); +void tipc_cfg_link_event(u32 addr, char *name, int up); +int tipc_cfg_init(void); +void tipc_cfg_stop(void); #endif diff --git a/net/tipc/core.c b/net/tipc/core.c index e83ac06e31ba..3d0a8ee4e1d3 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -37,7 +37,6 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/random.h> #include "core.h" @@ -49,14 +48,14 @@ #include "subscr.h" #include "config.h" -int eth_media_start(void); -void eth_media_stop(void); -int handler_start(void); -void handler_stop(void); -int socket_init(void); -void socket_stop(void); -int netlink_start(void); -void netlink_stop(void); +int tipc_eth_media_start(void); +void tipc_eth_media_stop(void); +int tipc_handler_start(void); +void tipc_handler_stop(void); +int tipc_socket_init(void); +void tipc_socket_stop(void); +int tipc_netlink_start(void); +void tipc_netlink_stop(void); #define MOD_NAME "tipc_start: " @@ -113,56 +112,56 @@ int tipc_get_mode(void) } /** - * stop_net - shut down TIPC networking sub-systems + * tipc_core_stop_net - shut down TIPC networking sub-systems */ -void stop_net(void) +void tipc_core_stop_net(void) { - eth_media_stop(); - tipc_stop_net(); + tipc_eth_media_stop(); + tipc_net_stop(); } /** * start_net - start TIPC networking sub-systems */ -int start_net(void) +int tipc_core_start_net(void) { int res; - if ((res = tipc_start_net()) || - (res = eth_media_start())) { - stop_net(); + if ((res = tipc_net_start()) || + (res = tipc_eth_media_start())) { + tipc_core_stop_net(); } return res; } /** - * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode + * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode */ -void stop_core(void) +void tipc_core_stop(void) { if (tipc_mode != TIPC_NODE_MODE) return; tipc_mode = TIPC_NOT_RUNNING; - netlink_stop(); - handler_stop(); - cfg_stop(); - subscr_stop(); - reg_stop(); - nametbl_stop(); - ref_table_stop(); - socket_stop(); + tipc_netlink_stop(); + tipc_handler_stop(); + tipc_cfg_stop(); + tipc_subscr_stop(); + tipc_reg_stop(); + tipc_nametbl_stop(); + tipc_ref_table_stop(); + tipc_socket_stop(); } /** - * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode + * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode */ -int start_core(void) +int tipc_core_start(void) { int res; @@ -172,16 +171,16 @@ int start_core(void) get_random_bytes(&tipc_random, sizeof(tipc_random)); tipc_mode = TIPC_NODE_MODE; - if ((res = handler_start()) || - (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions, - tipc_random)) || - (res = reg_start()) || - (res = nametbl_init()) || - (res = k_signal((Handler)subscr_start, 0)) || - (res = k_signal((Handler)cfg_init, 0)) || - (res = netlink_start()) || - (res = socket_init())) { - stop_core(); + if ((res = tipc_handler_start()) || + (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions, + tipc_random)) || + (res = tipc_reg_start()) || + (res = tipc_nametbl_init()) || + (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || + (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || + (res = tipc_netlink_start()) || + (res = tipc_socket_init())) { + tipc_core_stop(); } return res; } @@ -191,7 +190,7 @@ static int __init tipc_init(void) { int res; - log_reinit(CONFIG_TIPC_LOG); + tipc_log_reinit(CONFIG_TIPC_LOG); info("Activated (compiled " __DATE__ " " __TIME__ ")\n"); tipc_own_addr = 0; @@ -205,7 +204,7 @@ static int __init tipc_init(void) tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); tipc_net_id = 4711; - if ((res = start_core())) + if ((res = tipc_core_start())) err("Unable to start in single node mode\n"); else info("Started in single node mode\n"); @@ -214,10 +213,10 @@ static int __init tipc_init(void) static void __exit tipc_exit(void) { - stop_net(); - stop_core(); + tipc_core_stop_net(); + tipc_core_stop(); info("Deactivated\n"); - log_stop(); + tipc_log_stop(); } module_init(tipc_init); diff --git a/net/tipc/core.h b/net/tipc/core.h index b69b60b2cc86..1f2e8b27a13f 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -37,6 +37,11 @@ #ifndef _TIPC_CORE_H #define _TIPC_CORE_H +#include <linux/tipc.h> +#include <linux/tipc_config.h> +#include <net/tipc/tipc_msg.h> +#include <net/tipc/tipc_port.h> +#include <net/tipc/tipc_bearer.h> #include <net/tipc/tipc.h> #include <linux/types.h> #include <linux/kernel.h> @@ -60,9 +65,9 @@ #define assert(i) BUG_ON(!(i)) struct tipc_msg; -extern struct print_buf *CONS, *LOG; -extern struct print_buf *TEE(struct print_buf *, struct print_buf *); -void msg_print(struct print_buf*,struct tipc_msg *,const char*); +extern struct print_buf *TIPC_CONS, *TIPC_LOG; +extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *); +void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*); void tipc_printf(struct print_buf *, const char *fmt, ...); void tipc_dump(struct print_buf*,const char *fmt, ...); @@ -79,7 +84,7 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) #define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) -#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0) +#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0) #define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) @@ -89,15 +94,15 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); * here, or on a per .c file basis, by redefining these symbols. The following * print buffer options are available: * - * NULL : Output to null print buffer (i.e. print nowhere) - * CONS : Output to system console - * LOG : Output to TIPC log buffer - * &buf : Output to user-defined buffer (struct print_buf *) - * TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) ) + * NULL : Output to null print buffer (i.e. print nowhere) + * TIPC_CONS : Output to system console + * TIPC_LOG : Output to TIPC log buffer + * &buf : Output to user-defined buffer (struct print_buf *) + * TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) ) */ #ifndef TIPC_OUTPUT -#define TIPC_OUTPUT TEE(CONS,LOG) +#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG) #endif #ifndef DBG_OUTPUT @@ -162,10 +167,10 @@ extern atomic_t tipc_user_count; * Routines available to privileged subsystems */ -extern int start_core(void); -extern void stop_core(void); -extern int start_net(void); -extern void stop_net(void); +extern int tipc_core_start(void); +extern void tipc_core_stop(void); +extern int tipc_core_start_net(void); +extern void tipc_core_stop_net(void); static inline int delimit(int val, int min, int max) { @@ -183,7 +188,7 @@ static inline int delimit(int val, int min, int max) typedef void (*Handler) (unsigned long); -u32 k_signal(Handler routine, unsigned long argument); +u32 tipc_k_signal(Handler routine, unsigned long argument); /** * k_init_timer - initialize a timer diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 7ed60a1cfbb8..4f4beefa7830 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -44,10 +44,10 @@ static char print_string[MAX_STRING]; static spinlock_t print_lock = SPIN_LOCK_UNLOCKED; static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; -struct print_buf *CONS = &cons_buf; +struct print_buf *TIPC_CONS = &cons_buf; static struct print_buf log_buf = { NULL, 0, NULL, NULL }; -struct print_buf *LOG = &log_buf; +struct print_buf *TIPC_LOG = &log_buf; #define FORMAT(PTR,LEN,FMT) \ @@ -66,15 +66,15 @@ struct print_buf *LOG = &log_buf; * simultaneous use of the print buffer(s) being manipulated. * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of * 'print_string' and to protect its print buffer(s). - * 3) TEE() uses 'print_lock' to protect its print buffer(s). - * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG. + * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s). + * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG. */ /** - * printbuf_init - initialize print buffer to empty + * tipc_printbuf_init - initialize print buffer to empty */ -void printbuf_init(struct print_buf *pb, char *raw, u32 sz) +void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz) { if (!pb || !raw || (sz < (MAX_STRING + 1))) return; @@ -87,26 +87,26 @@ void printbuf_init(struct print_buf *pb, char *raw, u32 sz) } /** - * printbuf_reset - reinitialize print buffer to empty state + * tipc_printbuf_reset - reinitialize print buffer to empty state */ -void printbuf_reset(struct print_buf *pb) +void tipc_printbuf_reset(struct print_buf *pb) { if (pb && pb->buf) - printbuf_init(pb, pb->buf, pb->size); + tipc_printbuf_init(pb, pb->buf, pb->size); } /** - * printbuf_empty - test if print buffer is in empty state + * tipc_printbuf_empty - test if print buffer is in empty state */ -int printbuf_empty(struct print_buf *pb) +int tipc_printbuf_empty(struct print_buf *pb) { return (!pb || !pb->buf || (pb->crs == pb->buf)); } /** - * printbuf_validate - check for print buffer overflow + * tipc_printbuf_validate - check for print buffer overflow * * Verifies that a print buffer has captured all data written to it. * If data has been lost, linearize buffer and prepend an error message @@ -114,7 +114,7 @@ int printbuf_empty(struct print_buf *pb) * Returns length of print buffer data string (including trailing NULL) */ -int printbuf_validate(struct print_buf *pb) +int tipc_printbuf_validate(struct print_buf *pb) { char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; char *cp_buf; @@ -126,13 +126,13 @@ int printbuf_validate(struct print_buf *pb) if (pb->buf[pb->size - 1] == '\0') { cp_buf = kmalloc(pb->size, GFP_ATOMIC); if (cp_buf != NULL){ - printbuf_init(&cb, cp_buf, pb->size); - printbuf_move(&cb, pb); - printbuf_move(pb, &cb); + tipc_printbuf_init(&cb, cp_buf, pb->size); + tipc_printbuf_move(&cb, pb); + tipc_printbuf_move(pb, &cb); kfree(cp_buf); memcpy(pb->buf, err, strlen(err)); } else { - printbuf_reset(pb); + tipc_printbuf_reset(pb); tipc_printf(pb, err); } } @@ -140,13 +140,13 @@ int printbuf_validate(struct print_buf *pb) } /** - * printbuf_move - move print buffer contents to another print buffer + * tipc_printbuf_move - move print buffer contents to another print buffer * * Current contents of destination print buffer (if any) are discarded. * Source print buffer becomes empty if a successful move occurs. */ -void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) +void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) { int len; @@ -156,12 +156,12 @@ void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) return; if (!pb_from || !pb_from->buf) { - printbuf_reset(pb_to); + tipc_printbuf_reset(pb_to); return; } if (pb_to->size < pb_from->size) { - printbuf_reset(pb_to); + tipc_printbuf_reset(pb_to); tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); return; } @@ -179,7 +179,7 @@ void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) strcpy(pb_to->crs, pb_from->buf); pb_to->crs += len; - printbuf_reset(pb_from); + tipc_printbuf_reset(pb_from); } /** @@ -199,7 +199,7 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) strcpy(print_string, "*** STRING TOO LONG ***"); while (pb) { - if (pb == CONS) + if (pb == TIPC_CONS) printk(print_string); else if (pb->buf) { chars_left = pb->buf + pb->size - pb->crs - 1; @@ -223,10 +223,10 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) } /** - * TEE - perform next output operation on both print buffers + * TIPC_TEE - perform next output operation on both print buffers */ -struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1) +struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1) { struct print_buf *pb = b0; @@ -294,96 +294,96 @@ void tipc_dump(struct print_buf *pb, const char *fmt, ...) int len; spin_lock_bh(&print_lock); - FORMAT(CONS->buf, len, fmt); - printk(CONS->buf); + FORMAT(TIPC_CONS->buf, len, fmt); + printk(TIPC_CONS->buf); for (; pb; pb = pb->next) { - if (pb == CONS) + if (pb == TIPC_CONS) continue; printk("\n---- Start of dump,%s log ----\n\n", - (pb == LOG) ? "global" : "local"); + (pb == TIPC_LOG) ? "global" : "local"); printbuf_dump(pb); - printbuf_reset(pb); + tipc_printbuf_reset(pb); printk("\n-------- End of dump --------\n"); } spin_unlock_bh(&print_lock); } /** - * log_stop - free up TIPC log print buffer + * tipc_log_stop - free up TIPC log print buffer */ -void log_stop(void) +void tipc_log_stop(void) { spin_lock_bh(&print_lock); - if (LOG->buf) { - kfree(LOG->buf); - LOG->buf = NULL; + if (TIPC_LOG->buf) { + kfree(TIPC_LOG->buf); + TIPC_LOG->buf = NULL; } spin_unlock_bh(&print_lock); } /** - * log_reinit - set TIPC log print buffer to specified size + * tipc_log_reinit - set TIPC log print buffer to specified size */ -void log_reinit(int log_size) +void tipc_log_reinit(int log_size) { - log_stop(); + tipc_log_stop(); if (log_size) { if (log_size <= MAX_STRING) log_size = MAX_STRING + 1; spin_lock_bh(&print_lock); - printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size); + tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size); spin_unlock_bh(&print_lock); } } /** - * log_resize - reconfigure size of TIPC log buffer + * tipc_log_resize - reconfigure size of TIPC log buffer */ -struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space) { u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); if (value != delimit(value, 0, 32768)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (log size must be 0-32768)"); - log_reinit(value); - return cfg_reply_none(); + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (log size must be 0-32768)"); + tipc_log_reinit(value); + return tipc_cfg_reply_none(); } /** - * log_dump - capture TIPC log buffer contents in configuration message + * tipc_log_dump - capture TIPC log buffer contents in configuration message */ -struct sk_buff *log_dump(void) +struct sk_buff *tipc_log_dump(void) { struct sk_buff *reply; spin_lock_bh(&print_lock); - if (!LOG->buf) - reply = cfg_reply_ultra_string("log not activated\n"); - else if (printbuf_empty(LOG)) - reply = cfg_reply_ultra_string("log is empty\n"); + if (!TIPC_LOG->buf) + reply = tipc_cfg_reply_ultra_string("log not activated\n"); + else if (tipc_printbuf_empty(TIPC_LOG)) + reply = tipc_cfg_reply_ultra_string("log is empty\n"); else { struct tlv_desc *rep_tlv; struct print_buf pb; int str_len; - str_len = min(LOG->size, 32768u); - reply = cfg_reply_alloc(TLV_SPACE(str_len)); + str_len = min(TIPC_LOG->size, 32768u); + reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len)); if (reply) { rep_tlv = (struct tlv_desc *)reply->data; - printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); - printbuf_move(&pb, LOG); + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); + tipc_printbuf_move(&pb, TIPC_LOG); str_len = strlen(TLV_DATA(rep_tlv)) + 1; skb_put(reply, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index c6b2a64c224f..227f050d2a52 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h @@ -44,16 +44,16 @@ struct print_buf { struct print_buf *next; }; -void printbuf_init(struct print_buf *pb, char *buf, u32 sz); -void printbuf_reset(struct print_buf *pb); -int printbuf_empty(struct print_buf *pb); -int printbuf_validate(struct print_buf *pb); -void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); +void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz); +void tipc_printbuf_reset(struct print_buf *pb); +int tipc_printbuf_empty(struct print_buf *pb); +int tipc_printbuf_validate(struct print_buf *pb); +void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); -void log_reinit(int log_size); -void log_stop(void); +void tipc_log_reinit(int log_size); +void tipc_log_stop(void); -struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space); -struct sk_buff *log_dump(void); +struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *tipc_log_dump(void); #endif diff --git a/net/tipc/discover.c b/net/tipc/discover.c index b106ef1621cc..53ba4630c10d 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -93,7 +93,7 @@ int disc_create_link(const struct tipc_link_create *argv) * disc_lost_link(): A link has lost contact */ -void disc_link_event(u32 addr, char *name, int up) +void tipc_disc_link_event(u32 addr, char *name, int up) { if (in_own_cluster(addr)) return; @@ -103,17 +103,17 @@ void disc_link_event(u32 addr, char *name, int up) } /** - * disc_init_msg - initialize a link setup message + * tipc_disc_init_msg - initialize a link setup message * @type: message type (request or response) * @req_links: number of links associated with message * @dest_domain: network domain of node(s) which should respond to message * @b_ptr: ptr to bearer issuing message */ -struct sk_buff *disc_init_msg(u32 type, - u32 req_links, - u32 dest_domain, - struct bearer *b_ptr) +struct sk_buff *tipc_disc_init_msg(u32 type, + u32 req_links, + u32 dest_domain, + struct bearer *b_ptr) { struct sk_buff *buf = buf_acquire(DSC_H_SIZE); struct tipc_msg *msg; @@ -132,11 +132,11 @@ struct sk_buff *disc_init_msg(u32 type, } /** - * disc_recv_msg - handle incoming link setup message (request or response) + * tipc_disc_recv_msg - handle incoming link setup message (request or response) * @buf: buffer containing message */ -void disc_recv_msg(struct sk_buff *buf) +void tipc_disc_recv_msg(struct sk_buff *buf) { struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle; struct link *link; @@ -153,9 +153,9 @@ void disc_recv_msg(struct sk_buff *buf) if (net_id != tipc_net_id) return; - if (!addr_domain_valid(dest)) + if (!tipc_addr_domain_valid(dest)) return; - if (!addr_node_valid(orig)) + if (!tipc_addr_node_valid(orig)) return; if (orig == tipc_own_addr) return; @@ -169,11 +169,11 @@ void disc_recv_msg(struct sk_buff *buf) /* Always accept link here */ struct sk_buff *rbuf; struct tipc_media_addr *addr; - struct node *n_ptr = node_find(orig); + struct node *n_ptr = tipc_node_find(orig); int link_up; dbg(" in own cluster\n"); if (n_ptr == NULL) { - n_ptr = node_create(orig); + n_ptr = tipc_node_create(orig); } if (n_ptr == NULL) { warn("Memory squeeze; Failed to create node\n"); @@ -183,7 +183,7 @@ void disc_recv_msg(struct sk_buff *buf) link = n_ptr->links[b_ptr->identity]; if (!link) { dbg("creating link\n"); - link = link_create(b_ptr, orig, &media_addr); + link = tipc_link_create(b_ptr, orig, &media_addr); if (!link) { spin_unlock_bh(&n_ptr->lock); return; @@ -196,13 +196,13 @@ void disc_recv_msg(struct sk_buff *buf) warn("New bearer address for %s\n", addr_string_fill(addr_string, orig)); memcpy(addr, &media_addr, sizeof(*addr)); - link_reset(link); + tipc_link_reset(link); } - link_up = link_is_up(link); + link_up = tipc_link_is_up(link); spin_unlock_bh(&n_ptr->lock); if ((type == DSC_RESP_MSG) || link_up) return; - rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); + rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); if (rbuf != NULL) { msg_dbg(buf_msg(rbuf),"SEND:"); b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); @@ -212,11 +212,11 @@ void disc_recv_msg(struct sk_buff *buf) } /** - * disc_stop_link_req - stop sending periodic link setup requests + * tipc_disc_stop_link_req - stop sending periodic link setup requests * @req: ptr to link request structure */ -void disc_stop_link_req(struct link_req *req) +void tipc_disc_stop_link_req(struct link_req *req) { if (!req) return; @@ -228,11 +228,11 @@ void disc_stop_link_req(struct link_req *req) } /** - * disc_update_link_req - update frequency of periodic link setup requests + * tipc_disc_update_link_req - update frequency of periodic link setup requests * @req: ptr to link request structure */ -void disc_update_link_req(struct link_req *req) +void tipc_disc_update_link_req(struct link_req *req) { if (!req) return; @@ -282,7 +282,7 @@ static void disc_timeout(struct link_req *req) } /** - * disc_init_link_req - start sending periodic link setup requests + * tipc_disc_init_link_req - start sending periodic link setup requests * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages * @dest_domain: network domain of node(s) which should respond to message @@ -291,10 +291,10 @@ static void disc_timeout(struct link_req *req) * Returns pointer to link request structure, or NULL if unable to create. */ -struct link_req *disc_init_link_req(struct bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain, - u32 req_links) +struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, + const struct tipc_media_addr *dest, + u32 dest_domain, + u32 req_links) { struct link_req *req; @@ -302,7 +302,7 @@ struct link_req *disc_init_link_req(struct bearer *b_ptr, if (!req) return NULL; - req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); + req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); if (!req->buf) { kfree(req); return NULL; diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 2a6114d91626..0454fd1ae7f3 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -37,20 +37,20 @@ #ifndef _TIPC_DISCOVER_H #define _TIPC_DISCOVER_H -#include <linux/tipc.h> +#include "core.h" struct link_req; -struct link_req *disc_init_link_req(struct bearer *b_ptr, - const struct tipc_media_addr *dest, - u32 dest_domain, - u32 req_links); -void disc_update_link_req(struct link_req *req); -void disc_stop_link_req(struct link_req *req); +struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr, + const struct tipc_media_addr *dest, + u32 dest_domain, + u32 req_links); +void tipc_disc_update_link_req(struct link_req *req); +void tipc_disc_stop_link_req(struct link_req *req); -void disc_recv_msg(struct sk_buff *buf); +void tipc_disc_recv_msg(struct sk_buff *buf); -void disc_link_event(u32 addr, char *name, int up); +void tipc_disc_link_event(u32 addr, char *name, int up); #if 0 int disc_create_link(const struct tipc_link_create *argv); #endif diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 34d0462db3aa..1f8d83b9c8b4 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -38,13 +38,11 @@ #include <net/tipc/tipc_bearer.h> #include <net/tipc/tipc_msg.h> #include <linux/netdevice.h> -#include <linux/version.h> #define MAX_ETH_BEARERS 2 -#define TIPC_PROTOCOL 0x88ca -#define ETH_LINK_PRIORITY 10 +#define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL - +#define ETH_LINK_WINDOW TIPC_DEF_LINK_WIN /** * struct eth_bearer - Ethernet bearer data structure @@ -78,7 +76,7 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, clone->nh.raw = clone->data; dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; clone->dev = dev; - dev->hard_header(clone, dev, TIPC_PROTOCOL, + dev->hard_header(clone, dev, ETH_P_TIPC, &dest->dev_addr.eth_addr, dev->dev_addr, clone->len); dev_queue_xmit(clone); @@ -141,7 +139,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) return -EDQUOT; if (!eb_ptr->dev) { eb_ptr->dev = dev; - eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL); + eb_ptr->tipc_packet_type.type = __constant_htons(ETH_P_TIPC); eb_ptr->tipc_packet_type.dev = dev; eb_ptr->tipc_packet_type.func = recv_msg; eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; @@ -240,13 +238,13 @@ static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size } /** - * eth_media_start - activate Ethernet bearer support + * tipc_eth_media_start - activate Ethernet bearer support * * Register Ethernet media type with TIPC bearer code. Also register * with OS for notifications about device state changes. */ -int eth_media_start(void) +int tipc_eth_media_start(void) { struct tipc_media_addr bcast_addr; int res; @@ -260,7 +258,7 @@ int eth_media_start(void) res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth", enable_bearer, disable_bearer, send_msg, eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, - ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN); + ETH_LINK_TOLERANCE, ETH_LINK_WINDOW); if (res) return res; @@ -273,10 +271,10 @@ int eth_media_start(void) } /** - * eth_media_stop - deactivate Ethernet bearer support + * tipc_eth_media_stop - deactivate Ethernet bearer support */ -void eth_media_stop(void) +void tipc_eth_media_stop(void) { int i; diff --git a/net/tipc/handler.c b/net/tipc/handler.c index f320010f8a65..966f70a1b608 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -52,7 +52,7 @@ static void process_signal_queue(unsigned long dummy); static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0); -unsigned int k_signal(Handler routine, unsigned long argument) +unsigned int tipc_k_signal(Handler routine, unsigned long argument) { struct queue_item *item; @@ -93,7 +93,7 @@ static void process_signal_queue(unsigned long dummy) spin_unlock_bh(&qitem_lock); } -int handler_start(void) +int tipc_handler_start(void) { tipc_queue_item_cache = kmem_cache_create("tipc_queue_items", sizeof(struct queue_item), @@ -107,7 +107,7 @@ int handler_start(void) return 0; } -void handler_stop(void) +void tipc_handler_stop(void) { struct list_head *l, *n; struct queue_item *item; diff --git a/net/tipc/link.c b/net/tipc/link.c index 7265f4be4766..511872afa459 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -148,12 +148,12 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, #define LINK_LOG_BUF_SIZE 0 #define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0) -#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0) +#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0) #define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0) #define dbg_link_dump() do { \ if (LINK_LOG_BUF_SIZE) { \ tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ - printbuf_move(LOG, &l_ptr->print_buf); \ + tipc_printbuf_move(LOG, &l_ptr->print_buf); \ } \ } while (0) @@ -252,14 +252,14 @@ static inline u32 link_last_sent(struct link *l_ptr) * Simple non-inlined link routines (i.e. referenced outside this file) */ -int link_is_up(struct link *l_ptr) +int tipc_link_is_up(struct link *l_ptr) { if (!l_ptr) return 0; return (link_working_working(l_ptr) || link_working_unknown(l_ptr)); } -int link_is_active(struct link *l_ptr) +int tipc_link_is_active(struct link *l_ptr) { return ((l_ptr->owner->active_links[0] == l_ptr) || (l_ptr->owner->active_links[1] == l_ptr)); @@ -338,15 +338,15 @@ static int link_name_validate(const char *name, struct link_name *name_parts) * link_timeout - handle expiration of link timer * @l_ptr: pointer to link * - * This routine must not grab "net_lock" to avoid a potential deadlock conflict - * with link_delete(). (There is no risk that the node will be deleted by - * another thread because link_delete() always cancels the link timer before - * node_delete() is called.) + * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict + * with tipc_link_delete(). (There is no risk that the node will be deleted by + * another thread because tipc_link_delete() always cancels the link timer before + * tipc_node_delete() is called.) */ static void link_timeout(struct link *l_ptr) { - node_lock(l_ptr->owner); + tipc_node_lock(l_ptr->owner); /* update counters used in statistical profiling of send traffic */ @@ -391,9 +391,9 @@ static void link_timeout(struct link *l_ptr) link_state_event(l_ptr, TIMEOUT_EVT); if (l_ptr->next_out) - link_push_queue(l_ptr); + tipc_link_push_queue(l_ptr); - node_unlock(l_ptr->owner); + tipc_node_unlock(l_ptr->owner); } static inline void link_set_timer(struct link *l_ptr, u32 time) @@ -402,7 +402,7 @@ static inline void link_set_timer(struct link *l_ptr, u32 time) } /** - * link_create - create a new link + * tipc_link_create - create a new link * @b_ptr: pointer to associated bearer * @peer: network address of node at other end of link * @media_addr: media address to use when sending messages over link @@ -410,8 +410,8 @@ static inline void link_set_timer(struct link *l_ptr, u32 time) * Returns pointer to link. */ -struct link *link_create(struct bearer *b_ptr, const u32 peer, - const struct tipc_media_addr *media_addr) +struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, + const struct tipc_media_addr *media_addr) { struct link *l_ptr; struct tipc_msg *msg; @@ -449,7 +449,7 @@ struct link *link_create(struct bearer *b_ptr, const u32 peer, strcpy((char *)msg_data(msg), if_name); l_ptr->priority = b_ptr->priority; - link_set_queue_limits(l_ptr, b_ptr->media->window); + tipc_link_set_queue_limits(l_ptr, b_ptr->media->window); link_init_max_pkt(l_ptr); @@ -458,7 +458,7 @@ struct link *link_create(struct bearer *b_ptr, const u32 peer, link_reset_statistics(l_ptr); - l_ptr->owner = node_attach_link(l_ptr); + l_ptr->owner = tipc_node_attach_link(l_ptr); if (!l_ptr->owner) { kfree(l_ptr); return NULL; @@ -472,52 +472,52 @@ struct link *link_create(struct bearer *b_ptr, const u32 peer, warn("Memory squeeze; Failed to create link\n"); return NULL; } - printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); + tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); } - k_signal((Handler)link_start, (unsigned long)l_ptr); + tipc_k_signal((Handler)tipc_link_start, (unsigned long)l_ptr); - dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", + dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); return l_ptr; } /** - * link_delete - delete a link + * tipc_link_delete - delete a link * @l_ptr: pointer to link * - * Note: 'net_lock' is write_locked, bearer is locked. + * Note: 'tipc_net_lock' is write_locked, bearer is locked. * This routine must not grab the node lock until after link timer cancellation * to avoid a potential deadlock situation. */ -void link_delete(struct link *l_ptr) +void tipc_link_delete(struct link *l_ptr) { if (!l_ptr) { err("Attempt to delete non-existent link\n"); return; } - dbg("link_delete()\n"); + dbg("tipc_link_delete()\n"); k_cancel_timer(&l_ptr->timer); - node_lock(l_ptr->owner); - link_reset(l_ptr); - node_detach_link(l_ptr->owner, l_ptr); - link_stop(l_ptr); + tipc_node_lock(l_ptr->owner); + tipc_link_reset(l_ptr); + tipc_node_detach_link(l_ptr->owner, l_ptr); + tipc_link_stop(l_ptr); list_del_init(&l_ptr->link_list); if (LINK_LOG_BUF_SIZE) kfree(l_ptr->print_buf.buf); - node_unlock(l_ptr->owner); + tipc_node_unlock(l_ptr->owner); k_term_timer(&l_ptr->timer); kfree(l_ptr); } -void link_start(struct link *l_ptr) +void tipc_link_start(struct link *l_ptr) { - dbg("link_start %x\n", l_ptr); + dbg("tipc_link_start %x\n", l_ptr); link_state_event(l_ptr, STARTING_EVT); } @@ -535,8 +535,8 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) { struct port *p_ptr; - spin_lock_bh(&port_list_lock); - p_ptr = port_lock(origport); + spin_lock_bh(&tipc_port_list_lock); + p_ptr = tipc_port_lock(origport); if (p_ptr) { if (!p_ptr->wakeup) goto exit; @@ -548,13 +548,13 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); l_ptr->stats.link_congs++; exit: - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); } - spin_unlock_bh(&port_list_lock); + spin_unlock_bh(&tipc_port_list_lock); return -ELINKCONG; } -void link_wakeup_ports(struct link *l_ptr, int all) +void tipc_link_wakeup_ports(struct link *l_ptr, int all) { struct port *p_ptr; struct port *temp_p_ptr; @@ -564,7 +564,7 @@ void link_wakeup_ports(struct link *l_ptr, int all) win = 100000; if (win <= 0) return; - if (!spin_trylock_bh(&port_list_lock)) + if (!spin_trylock_bh(&tipc_port_list_lock)) return; if (link_congested(l_ptr)) goto exit; @@ -583,7 +583,7 @@ void link_wakeup_ports(struct link *l_ptr, int all) } exit: - spin_unlock_bh(&port_list_lock); + spin_unlock_bh(&tipc_port_list_lock); } /** @@ -606,11 +606,11 @@ static void link_release_outqueue(struct link *l_ptr) } /** - * link_reset_fragments - purge link's inbound message fragments queue + * tipc_link_reset_fragments - purge link's inbound message fragments queue * @l_ptr: pointer to link */ -void link_reset_fragments(struct link *l_ptr) +void tipc_link_reset_fragments(struct link *l_ptr) { struct sk_buff *buf = l_ptr->defragm_buf; struct sk_buff *next; @@ -624,11 +624,11 @@ void link_reset_fragments(struct link *l_ptr) } /** - * link_stop - purge all inbound and outbound messages associated with link + * tipc_link_stop - purge all inbound and outbound messages associated with link * @l_ptr: pointer to link */ -void link_stop(struct link *l_ptr) +void tipc_link_stop(struct link *l_ptr) { struct sk_buff *buf; struct sk_buff *next; @@ -647,7 +647,7 @@ void link_stop(struct link *l_ptr) buf = next; } - link_reset_fragments(l_ptr); + tipc_link_reset_fragments(l_ptr); buf_discard(l_ptr->proto_msg_queue); l_ptr->proto_msg_queue = NULL; @@ -677,7 +677,7 @@ static void link_send_event(void (*fcn)(u32 a, char *n, int up), ev->up = up; ev->fcn = fcn; memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME); - k_signal((Handler)link_recv_event, (unsigned long)ev); + tipc_k_signal((Handler)link_recv_event, (unsigned long)ev); } #else @@ -686,7 +686,7 @@ static void link_send_event(void (*fcn)(u32 a, char *n, int up), #endif -void link_reset(struct link *l_ptr) +void tipc_link_reset(struct link *l_ptr) { struct sk_buff *buf; u32 prev_state = l_ptr->state; @@ -706,13 +706,13 @@ void link_reset(struct link *l_ptr) if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) return; - node_link_down(l_ptr->owner, l_ptr); - bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); + tipc_node_link_down(l_ptr->owner, l_ptr); + tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); #if 0 - tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name); + tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); dbg_link_dump(); #endif - if (node_has_active_links(l_ptr->owner) && + if (tipc_node_has_active_links(l_ptr->owner) && l_ptr->owner->permit_changeover) { l_ptr->reset_checkpoint = checkpoint; l_ptr->exp_msg_count = START_CHANGEOVER; @@ -730,7 +730,7 @@ void link_reset(struct link *l_ptr) buf = next; } if (!list_empty(&l_ptr->waiting_ports)) - link_wakeup_ports(l_ptr, 1); + tipc_link_wakeup_ports(l_ptr, 1); l_ptr->retransm_queue_head = 0; l_ptr->retransm_queue_size = 0; @@ -747,20 +747,20 @@ void link_reset(struct link *l_ptr) l_ptr->stale_count = 0; link_reset_statistics(l_ptr); - link_send_event(cfg_link_event, l_ptr, 0); + link_send_event(tipc_cfg_link_event, l_ptr, 0); if (!in_own_cluster(l_ptr->addr)) - link_send_event(disc_link_event, l_ptr, 0); + link_send_event(tipc_disc_link_event, l_ptr, 0); } static void link_activate(struct link *l_ptr) { l_ptr->next_in_no = 1; - node_link_up(l_ptr->owner, l_ptr); - bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); - link_send_event(cfg_link_event, l_ptr, 1); + tipc_node_link_up(l_ptr->owner, l_ptr); + tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); + link_send_event(tipc_cfg_link_event, l_ptr, 1); if (!in_own_cluster(l_ptr->addr)) - link_send_event(disc_link_event, l_ptr, 1); + link_send_event(tipc_disc_link_event, l_ptr, 1); } /** @@ -799,13 +799,13 @@ static void link_state_event(struct link *l_ptr, unsigned event) dbg_link("TIM "); if (l_ptr->next_in_no != l_ptr->checkpoint) { l_ptr->checkpoint = l_ptr->next_in_no; - if (bclink_acks_missing(l_ptr->owner)) { - link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, 0, 0, 0); + if (tipc_bclink_acks_missing(l_ptr->owner)) { + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { - link_send_proto_msg(l_ptr, STATE_MSG, - 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } link_set_timer(l_ptr, cont_intv); @@ -814,16 +814,16 @@ static void link_state_event(struct link *l_ptr, unsigned event) dbg_link(" -> WU\n"); l_ptr->state = WORKING_UNKNOWN; l_ptr->fsm_msg_cnt = 0; - link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); break; case RESET_MSG: dbg_link("RES -> RR\n"); - link_reset(l_ptr); + tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -844,10 +844,10 @@ static void link_state_event(struct link *l_ptr, unsigned event) break; case RESET_MSG: dbg_link("RES -> RR\n"); - link_reset(l_ptr); + tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -858,9 +858,9 @@ static void link_state_event(struct link *l_ptr, unsigned event) l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; l_ptr->checkpoint = l_ptr->next_in_no; - if (bclink_acks_missing(l_ptr->owner)) { - link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, 0, 0, 0); + if (tipc_bclink_acks_missing(l_ptr->owner)) { + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; } link_set_timer(l_ptr, cont_intv); @@ -868,18 +868,18 @@ static void link_state_event(struct link *l_ptr, unsigned event) dbg_link("Probing %u/%u,timer = %u ms)\n", l_ptr->fsm_msg_cnt, l_ptr->abort_limit, cont_intv / 4); - link_send_proto_msg(l_ptr, STATE_MSG, - 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv / 4); } else { /* Link has failed */ dbg_link("-> RU (%u probes unanswered)\n", l_ptr->fsm_msg_cnt); - link_reset(l_ptr); + tipc_link_reset(l_ptr); l_ptr->state = RESET_UNKNOWN; l_ptr->fsm_msg_cnt = 0; - link_send_proto_msg(l_ptr, RESET_MSG, - 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, RESET_MSG, + 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); } @@ -904,7 +904,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); - link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -913,7 +913,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) dbg_link(" -> RR\n"); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; - link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -923,7 +923,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) /* fall through */ case TIMEOUT_EVT: dbg_link("TIM \n"); - link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -947,7 +947,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) l_ptr->state = WORKING_WORKING; l_ptr->fsm_msg_cnt = 0; link_activate(l_ptr); - link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); break; @@ -956,7 +956,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) break; case TIMEOUT_EVT: dbg_link("TIM\n"); - link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); l_ptr->fsm_msg_cnt++; link_set_timer(l_ptr, cont_intv); dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt); @@ -1023,12 +1023,12 @@ static inline void link_add_to_outqueue(struct link *l_ptr, } /* - * link_send_buf() is the 'full path' for messages, called from + * tipc_link_send_buf() is the 'full path' for messages, called from * inside TIPC when the 'fast path' in tipc_send_buf * has failed, and from link_send() */ -int link_send_buf(struct link *l_ptr, struct sk_buff *buf) +int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); u32 size = msg_size(msg); @@ -1051,7 +1051,7 @@ int link_send_buf(struct link *l_ptr, struct sk_buff *buf) buf_discard(buf); if (imp > CONN_MANAGER) { warn("Resetting <%s>, send queue full", l_ptr->name); - link_reset(l_ptr); + tipc_link_reset(l_ptr); } return dsz; } @@ -1059,21 +1059,21 @@ int link_send_buf(struct link *l_ptr, struct sk_buff *buf) /* Fragmentation needed ? */ if (size > max_packet) - return link_send_long_buf(l_ptr, buf); + return tipc_link_send_long_buf(l_ptr, buf); /* Packet can be queued or sent: */ if (queue_size > l_ptr->stats.max_queue_sz) l_ptr->stats.max_queue_sz = queue_size; - if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) && + if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && !link_congested(l_ptr))) { link_add_to_outqueue(l_ptr, buf, msg); - if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { + if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { l_ptr->unacked_window = 0; } else { - bearer_schedule(l_ptr->b_ptr, l_ptr); + tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); l_ptr->stats.bearer_congs++; l_ptr->next_out = buf; } @@ -1088,7 +1088,7 @@ int link_send_buf(struct link *l_ptr, struct sk_buff *buf) if (l_ptr->next_out && link_bundle_buf(l_ptr, l_ptr->last_out, buf)) { - bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); + tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); return dsz; } @@ -1114,38 +1114,38 @@ int link_send_buf(struct link *l_ptr, struct sk_buff *buf) if (!l_ptr->next_out) l_ptr->next_out = buf; link_add_to_outqueue(l_ptr, buf, msg); - bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); + tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); return dsz; } /* - * link_send(): same as link_send_buf(), but the link to use has + * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has * not been selected yet, and the the owner node is not locked * Called by TIPC internal users, e.g. the name distributor */ -int link_send(struct sk_buff *buf, u32 dest, u32 selector) +int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) { struct link *l_ptr; struct node *n_ptr; int res = -ELINKCONG; - read_lock_bh(&net_lock); - n_ptr = node_select(dest, selector); + read_lock_bh(&tipc_net_lock); + n_ptr = tipc_node_select(dest, selector); if (n_ptr) { - node_lock(n_ptr); + tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; - dbg("link_send: found link %x for dest %x\n", l_ptr, dest); + dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); if (l_ptr) { - res = link_send_buf(l_ptr, buf); + res = tipc_link_send_buf(l_ptr, buf); } - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); } else { dbg("Attempt to send msg to unknown node:\n"); msg_dbg(buf_msg(buf),">>>"); buf_discard(buf); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return res; } @@ -1166,14 +1166,14 @@ static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { link_add_to_outqueue(l_ptr, buf, msg); - if (likely(bearer_send(l_ptr->b_ptr, buf, - &l_ptr->media_addr))) { + if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, + &l_ptr->media_addr))) { l_ptr->unacked_window = 0; msg_dbg(msg,"SENT_FAST:"); return res; } dbg("failed sent fast...\n"); - bearer_schedule(l_ptr->b_ptr, l_ptr); + tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); l_ptr->stats.bearer_congs++; l_ptr->next_out = buf; return res; @@ -1182,7 +1182,7 @@ static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, else *used_max_pkt = link_max_pkt(l_ptr); } - return link_send_buf(l_ptr, buf); /* All other cases */ + return tipc_link_send_buf(l_ptr, buf); /* All other cases */ } /* @@ -1200,24 +1200,24 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) u32 dummy; if (destnode == tipc_own_addr) - return port_recv_msg(buf); + return tipc_port_recv_msg(buf); - read_lock_bh(&net_lock); - n_ptr = node_select(destnode, selector); + read_lock_bh(&tipc_net_lock); + n_ptr = tipc_node_select(destnode, selector); if (likely(n_ptr)) { - node_lock(n_ptr); + tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector]; dbg("send_fast: buf %x selected %x, destnode = %x\n", buf, l_ptr, destnode); if (likely(l_ptr)) { res = link_send_buf_fast(l_ptr, buf, &dummy); - node_unlock(n_ptr); - read_unlock_bh(&net_lock); + tipc_node_unlock(n_ptr); + read_unlock_bh(&tipc_net_lock); return res; } - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); res = msg_data_sz(buf_msg(buf)); tipc_reject_msg(buf, TIPC_ERR_NO_NODE); return res; @@ -1225,15 +1225,15 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) /* - * link_send_sections_fast: Entry for messages where the + * tipc_link_send_sections_fast: Entry for messages where the * destination processor is known and the header is complete, * except for total message length. * Returns user data length or errno. */ -int link_send_sections_fast(struct port *sender, - struct iovec const *msg_sect, - const u32 num_sect, - u32 destaddr) +int tipc_link_send_sections_fast(struct port *sender, + struct iovec const *msg_sect, + const u32 num_sect, + u32 destaddr) { struct tipc_msg *hdr = &sender->publ.phdr; struct link *l_ptr; @@ -1253,10 +1253,10 @@ again: res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, !sender->user_port, &buf); - read_lock_bh(&net_lock); - node = node_select(destaddr, selector); + read_lock_bh(&tipc_net_lock); + node = tipc_node_select(destaddr, selector); if (likely(node)) { - node_lock(node); + tipc_node_lock(node); l_ptr = node->active_links[selector]; if (likely(l_ptr)) { if (likely(buf)) { @@ -1265,8 +1265,8 @@ again: if (unlikely(res < 0)) buf_discard(buf); exit: - node_unlock(node); - read_unlock_bh(&net_lock); + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); return res; } @@ -1290,8 +1290,8 @@ exit: */ sender->max_pkt = link_max_pkt(l_ptr); - node_unlock(node); - read_unlock_bh(&net_lock); + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) @@ -1300,17 +1300,17 @@ exit: return link_send_sections_long(sender, msg_sect, num_sect, destaddr); } - node_unlock(node); + tipc_node_unlock(node); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); /* Couldn't find a link to the destination node */ if (buf) return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); if (res >= 0) - return port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, + TIPC_ERR_NO_NODE); return res; } @@ -1444,17 +1444,17 @@ error: * Now we have a buffer chain. Select a link and check * that packet size is still OK */ - node = node_select(destaddr, sender->publ.ref & 1); + node = tipc_node_select(destaddr, sender->publ.ref & 1); if (likely(node)) { - node_lock(node); + tipc_node_lock(node); l_ptr = node->active_links[sender->publ.ref & 1]; if (!l_ptr) { - node_unlock(node); + tipc_node_unlock(node); goto reject; } if (link_max_pkt(l_ptr) < max_pkt) { sender->max_pkt = link_max_pkt(l_ptr); - node_unlock(node); + tipc_node_unlock(node); for (; buf_chain; buf_chain = buf) { buf = buf_chain->next; buf_discard(buf_chain); @@ -1467,8 +1467,8 @@ reject: buf = buf_chain->next; buf_discard(buf_chain); } - return port_reject_sections(sender, hdr, msg_sect, num_sect, - TIPC_ERR_NO_NODE); + return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, + TIPC_ERR_NO_NODE); } /* Append whole chain to send queue: */ @@ -1491,15 +1491,15 @@ reject: /* Send it, if possible: */ - link_push_queue(l_ptr); - node_unlock(node); + tipc_link_push_queue(l_ptr); + tipc_node_unlock(node); return dsz; } /* - * link_push_packet: Push one unsent packet to the media + * tipc_link_push_packet: Push one unsent packet to the media */ -u32 link_push_packet(struct link *l_ptr) +u32 tipc_link_push_packet(struct link *l_ptr) { struct sk_buff *buf = l_ptr->first_out; u32 r_q_size = l_ptr->retransm_queue_size; @@ -1526,7 +1526,7 @@ u32 link_push_packet(struct link *l_ptr) if (r_q_size && buf && !skb_cloned(buf)) { msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); - if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { msg_dbg(buf_msg(buf), ">DEF-RETR>"); l_ptr->retransm_queue_head = mod(++r_q_head); l_ptr->retransm_queue_size = --r_q_size; @@ -1545,7 +1545,7 @@ u32 link_push_packet(struct link *l_ptr) if (buf) { msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); - if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { msg_dbg(buf_msg(buf), ">DEF-PROT>"); l_ptr->unacked_window = 0; buf_discard(buf); @@ -1569,7 +1569,7 @@ u32 link_push_packet(struct link *l_ptr) if (mod(next - first) < l_ptr->queue_limit[0]) { msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); - if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { if (msg_user(msg) == MSG_BUNDLER) msg_set_type(msg, CLOSED_MSG); msg_dbg(msg, ">PUSH-DATA>"); @@ -1589,29 +1589,29 @@ u32 link_push_packet(struct link *l_ptr) * push_queue(): push out the unsent messages of a link where * congestion has abated. Node is locked */ -void link_push_queue(struct link *l_ptr) +void tipc_link_push_queue(struct link *l_ptr) { u32 res; - if (bearer_congested(l_ptr->b_ptr, l_ptr)) + if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) return; do { - res = link_push_packet(l_ptr); + res = tipc_link_push_packet(l_ptr); } while (res == TIPC_OK); if (res == PUSH_FAILED) - bearer_schedule(l_ptr->b_ptr, l_ptr); + tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); } -void link_retransmit(struct link *l_ptr, struct sk_buff *buf, - u32 retransmits) +void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, + u32 retransmits) { struct tipc_msg *msg; dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); - if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { + if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); dbg_print_link(l_ptr, " "); l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); @@ -1622,15 +1622,15 @@ void link_retransmit(struct link *l_ptr, struct sk_buff *buf, msg = buf_msg(buf); msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); - if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { /* Catch if retransmissions fail repeatedly: */ if (l_ptr->last_retransmitted == msg_seqno(msg)) { if (++l_ptr->stale_count > 100) { - msg_print(CONS, buf_msg(buf), ">RETR>"); + tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>"); info("...Retransmitted %u times\n", l_ptr->stale_count); - link_print(l_ptr, CONS, "Resetting Link\n");; - link_reset(l_ptr); + link_print(l_ptr, TIPC_CONS, "Resetting Link\n");; + tipc_link_reset(l_ptr); break; } } else { @@ -1643,7 +1643,7 @@ void link_retransmit(struct link *l_ptr, struct sk_buff *buf, retransmits--; l_ptr->stats.retransmitted++; } else { - bearer_schedule(l_ptr->b_ptr, l_ptr); + tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); l_ptr->stats.bearer_congs++; l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); l_ptr->retransm_queue_size = retransmits; @@ -1663,9 +1663,9 @@ static void link_recv_non_seq(struct sk_buff *buf) struct tipc_msg *msg = buf_msg(buf); if (msg_user(msg) == LINK_CONFIG) - disc_recv_msg(buf); + tipc_disc_recv_msg(buf); else - bclink_recv_pkt(buf); + tipc_bclink_recv_pkt(buf); } /** @@ -1692,7 +1692,7 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) { - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); while (head) { struct bearer *b_ptr; struct node *n_ptr; @@ -1720,22 +1720,22 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) link_recv_non_seq(buf); continue; } - n_ptr = node_find(msg_prevnode(msg)); + n_ptr = tipc_node_find(msg_prevnode(msg)); if (unlikely(!n_ptr)) goto cont; - node_lock(n_ptr); + tipc_node_lock(n_ptr); l_ptr = n_ptr->links[b_ptr->identity]; if (unlikely(!l_ptr)) { - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); goto cont; } /* * Release acked messages */ if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { - if (node_is_up(n_ptr) && n_ptr->bclink.supported) - bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); + if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported) + tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); } crs = l_ptr->first_out; @@ -1752,12 +1752,12 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) l_ptr->out_queue_size -= released; } if (unlikely(l_ptr->next_out)) - link_push_queue(l_ptr); + tipc_link_push_queue(l_ptr); if (unlikely(!list_empty(&l_ptr->waiting_ports))) - link_wakeup_ports(l_ptr, 0); + tipc_link_wakeup_ports(l_ptr, 0); if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { l_ptr->stats.sent_acks++; - link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } protocol_check: @@ -1770,8 +1770,8 @@ protocol_check: if (likely(msg_is_dest(msg, tipc_own_addr))) { deliver: if (likely(msg_isdata(msg))) { - node_unlock(n_ptr); - port_recv_msg(buf); + tipc_node_unlock(n_ptr); + tipc_port_recv_msg(buf); continue; } switch (msg_user(msg)) { @@ -1779,34 +1779,32 @@ deliver: l_ptr->stats.recv_bundles++; l_ptr->stats.recv_bundled += msg_msgcnt(msg); - node_unlock(n_ptr); - link_recv_bundle(buf); + tipc_node_unlock(n_ptr); + tipc_link_recv_bundle(buf); continue; case ROUTE_DISTRIBUTOR: - node_unlock(n_ptr); - cluster_recv_routing_table(buf); + tipc_node_unlock(n_ptr); + tipc_cltr_recv_routing_table(buf); continue; case NAME_DISTRIBUTOR: - node_unlock(n_ptr); - named_recv(buf); + tipc_node_unlock(n_ptr); + tipc_named_recv(buf); continue; case CONN_MANAGER: - node_unlock(n_ptr); - port_recv_proto_msg(buf); + tipc_node_unlock(n_ptr); + tipc_port_recv_proto_msg(buf); continue; case MSG_FRAGMENTER: l_ptr->stats.recv_fragments++; - if (link_recv_fragment( - &l_ptr->defragm_buf, - &buf, &msg)) { + if (tipc_link_recv_fragment(&l_ptr->defragm_buf, + &buf, &msg)) { l_ptr->stats.recv_fragmented++; goto deliver; } break; case CHANGEOVER_PROTOCOL: type = msg_type(msg); - if (link_recv_changeover_msg( - &l_ptr, &buf)) { + if (link_recv_changeover_msg(&l_ptr, &buf)) { msg = buf_msg(buf); seq_no = msg_seqno(msg); TIPC_SKB_CB(buf)->handle @@ -1818,20 +1816,20 @@ deliver: break; } } - node_unlock(n_ptr); - net_route_msg(buf); + tipc_node_unlock(n_ptr); + tipc_net_route_msg(buf); continue; } link_handle_out_of_seq_msg(l_ptr, buf); head = link_insert_deferred_queue(l_ptr, head); - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); continue; } if (msg_user(msg) == LINK_PROTOCOL) { link_recv_proto_msg(l_ptr, buf); head = link_insert_deferred_queue(l_ptr, head); - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); continue; } msg_dbg(msg,"NSEQ<REC<"); @@ -1842,14 +1840,14 @@ deliver: msg_dbg(msg,"RECV-REINS:"); buf->next = head; head = buf; - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); continue; } - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); cont: buf_discard(buf); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); } /* @@ -1858,9 +1856,9 @@ cont: * Returns the increase of the queue length,i.e. 0 or 1 */ -u32 link_defer_pkt(struct sk_buff **head, - struct sk_buff **tail, - struct sk_buff *buf) +u32 tipc_link_defer_pkt(struct sk_buff **head, + struct sk_buff **tail, + struct sk_buff *buf) { struct sk_buff *prev = 0; struct sk_buff *crs = *head; @@ -1939,12 +1937,12 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr, return; } - if (link_defer_pkt(&l_ptr->oldest_deferred_in, - &l_ptr->newest_deferred_in, buf)) { + if (tipc_link_defer_pkt(&l_ptr->oldest_deferred_in, + &l_ptr->newest_deferred_in, buf)) { l_ptr->deferred_inqueue_sz++; l_ptr->stats.deferred_recv++; if ((l_ptr->deferred_inqueue_sz % 16) == 1) - link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } else l_ptr->stats.duplicates++; } @@ -1952,8 +1950,8 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr, /* * Send protocol message to the other endpoint. */ -void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, - u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) +void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, + u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) { struct sk_buff *buf = 0; struct tipc_msg *msg = l_ptr->pmsg; @@ -1964,12 +1962,12 @@ void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, msg_set_type(msg, msg_typ); msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); - msg_set_last_bcast(msg, bclink_get_last_sent()); + msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); if (msg_typ == STATE_MSG) { u32 next_sent = mod(l_ptr->next_out_no); - if (!link_is_up(l_ptr)) + if (!tipc_link_is_up(l_ptr)) return; if (l_ptr->next_out) next_sent = msg_seqno(buf_msg(l_ptr->next_out)); @@ -2013,7 +2011,7 @@ void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, msg_set_max_pkt(msg, l_ptr->max_pkt_target); } - if (node_has_redundant_links(l_ptr->owner)) { + if (tipc_node_has_redundant_links(l_ptr->owner)) { msg_set_redundant_link(msg); } else { msg_clear_redundant_link(msg); @@ -2026,7 +2024,7 @@ void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, /* Congestion? */ - if (bearer_congested(l_ptr->b_ptr, l_ptr)) { + if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { if (!l_ptr->proto_msg_queue) { l_ptr->proto_msg_queue = buf_acquire(sizeof(l_ptr->proto_msg)); @@ -2050,14 +2048,14 @@ void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); msg_set_size(buf_msg(buf), msg_size); - if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { l_ptr->unacked_window = 0; buf_discard(buf); return; } /* New congestion */ - bearer_schedule(l_ptr->b_ptr, l_ptr); + tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); l_ptr->proto_msg_queue = buf; l_ptr->stats.bearer_congs++; } @@ -2131,7 +2129,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) l_ptr->peer_bearer_id = msg_bearer_id(msg); /* Synchronize broadcast sequence numbers */ - if (!node_has_redundant_links(l_ptr->owner)) { + if (!tipc_node_has_redundant_links(l_ptr->owner)) { l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); } break; @@ -2145,7 +2143,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) warn("Changing prio <%s>: %u->%u\n", l_ptr->name, l_ptr->priority, msg_linkprio(msg)); l_ptr->priority = msg_linkprio(msg); - link_reset(l_ptr); /* Enforce change to take effect */ + tipc_link_reset(l_ptr); /* Enforce change to take effect */ break; } link_state_event(l_ptr, TRAFFIC_MSG_EVT); @@ -2176,17 +2174,17 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) /* Protocol message before retransmits, reduce loss risk */ - bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); + tipc_bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); if (rec_gap || (msg_probe(msg))) { - link_send_proto_msg(l_ptr, STATE_MSG, - 0, rec_gap, 0, 0, max_pkt_ack); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, rec_gap, 0, 0, max_pkt_ack); } if (msg_seq_gap(msg)) { msg_dbg(msg, "With Gap:"); l_ptr->stats.recv_nacks++; - link_retransmit(l_ptr, l_ptr->first_out, - msg_seq_gap(msg)); + tipc_link_retransmit(l_ptr, l_ptr->first_out, + msg_seq_gap(msg)); } break; default: @@ -2198,20 +2196,20 @@ exit: /* - * link_tunnel(): Send one message via a link belonging to + * tipc_link_tunnel(): Send one message via a link belonging to * another bearer. Owner node is locked. */ -void link_tunnel(struct link *l_ptr, - struct tipc_msg *tunnel_hdr, - struct tipc_msg *msg, - u32 selector) +void tipc_link_tunnel(struct link *l_ptr, + struct tipc_msg *tunnel_hdr, + struct tipc_msg *msg, + u32 selector) { struct link *tunnel; struct sk_buff *buf; u32 length = msg_size(msg); tunnel = l_ptr->owner->active_links[selector & 1]; - if (!link_is_up(tunnel)) + if (!tipc_link_is_up(tunnel)) return; msg_set_size(tunnel_hdr, length + INT_H_SIZE); buf = buf_acquire(length + INT_H_SIZE); @@ -2222,7 +2220,7 @@ void link_tunnel(struct link *l_ptr, dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); msg_dbg(buf_msg(buf), ">SEND>"); assert(tunnel); - link_send_buf(tunnel, buf); + tipc_link_send_buf(tunnel, buf); } @@ -2232,12 +2230,12 @@ void link_tunnel(struct link *l_ptr, * Owner node is locked. */ -void link_changeover(struct link *l_ptr) +void tipc_link_changeover(struct link *l_ptr) { u32 msgcount = l_ptr->out_queue_size; struct sk_buff *crs = l_ptr->first_out; struct link *tunnel = l_ptr->owner->active_links[0]; - int split_bundles = node_has_redundant_links(l_ptr->owner); + int split_bundles = tipc_node_has_redundant_links(l_ptr->owner); struct tipc_msg tunnel_hdr; if (!tunnel) @@ -2261,7 +2259,7 @@ void link_changeover(struct link *l_ptr) dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); - link_send_buf(tunnel, buf); + tipc_link_send_buf(tunnel, buf); } else { warn("Memory squeeze; link changeover failed\n"); } @@ -2277,20 +2275,20 @@ void link_changeover(struct link *l_ptr) while (msgcount--) { msg_set_seqno(m,msg_seqno(msg)); - link_tunnel(l_ptr, &tunnel_hdr, m, - msg_link_selector(m)); + tipc_link_tunnel(l_ptr, &tunnel_hdr, m, + msg_link_selector(m)); pos += align(msg_size(m)); m = (struct tipc_msg *)pos; } } else { - link_tunnel(l_ptr, &tunnel_hdr, msg, - msg_link_selector(msg)); + tipc_link_tunnel(l_ptr, &tunnel_hdr, msg, + msg_link_selector(msg)); } crs = crs->next; } } -void link_send_duplicate(struct link *l_ptr, struct link *tunnel) +void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) { struct sk_buff *iter; struct tipc_msg tunnel_hdr; @@ -2320,8 +2318,8 @@ void link_send_duplicate(struct link *l_ptr, struct link *tunnel) dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); msg_dbg(buf_msg(outbuf), ">SEND>"); - link_send_buf(tunnel, outbuf); - if (!link_is_up(l_ptr)) + tipc_link_send_buf(tunnel, outbuf); + if (!tipc_link_is_up(l_ptr)) return; iter = iter->next; } @@ -2393,9 +2391,9 @@ static int link_recv_changeover_msg(struct link **l_ptr, /* First original message ?: */ - if (link_is_up(dest_link)) { + if (tipc_link_is_up(dest_link)) { msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); - link_reset(dest_link); + tipc_link_reset(dest_link); dest_link->exp_msg_count = msg_count; if (!msg_count) goto exit; @@ -2436,7 +2434,7 @@ exit: /* * Bundler functionality: */ -void link_recv_bundle(struct sk_buff *buf) +void tipc_link_recv_bundle(struct sk_buff *buf) { u32 msgcount = msg_msgcnt(buf_msg(buf)); u32 pos = INT_H_SIZE; @@ -2456,7 +2454,7 @@ void link_recv_bundle(struct sk_buff *buf) }; pos += align(msg_size(buf_msg(obuf))); msg_dbg(buf_msg(obuf), " /"); - net_route_msg(obuf); + tipc_net_route_msg(obuf); } buf_discard(buf); } @@ -2467,11 +2465,11 @@ void link_recv_bundle(struct sk_buff *buf) /* - * link_send_long_buf: Entry for buffers needing fragmentation. + * tipc_link_send_long_buf: Entry for buffers needing fragmentation. * The buffer is complete, inclusive total message length. * Returns user data length. */ -int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) +int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) { struct tipc_msg *inmsg = buf_msg(buf); struct tipc_msg fragm_hdr; @@ -2521,8 +2519,8 @@ int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) /* Send queued messages first, if any: */ l_ptr->stats.sent_fragments++; - link_send_buf(l_ptr, fragm); - if (!link_is_up(l_ptr)) + tipc_link_send_buf(l_ptr, fragm); + if (!tipc_link_is_up(l_ptr)) return dsz; msg_set_fragm_no(&fragm_hdr, ++fragm_no); rest -= fragm_sz; @@ -2582,11 +2580,11 @@ static inline void incr_timer_cnt(struct sk_buff *buf) } /* - * link_recv_fragment(): Called with node lock on. Returns + * tipc_link_recv_fragment(): Called with node lock on. Returns * the reassembled buffer if message is complete. */ -int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, - struct tipc_msg **m) +int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, + struct tipc_msg **m) { struct sk_buff *prev = 0; struct sk_buff *fbuf = *fb; @@ -2714,7 +2712,7 @@ static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) } -void link_set_queue_limits(struct link *l_ptr, u32 window) +void tipc_link_set_queue_limits(struct link *l_ptr, u32 window) { /* Data messages from this node, inclusive FIRST_FRAGM */ l_ptr->queue_limit[DATA_LOW] = window; @@ -2739,7 +2737,7 @@ void link_set_queue_limits(struct link *l_ptr, u32 window) * @name - ptr to link name string * @node - ptr to area to be filled with ptr to associated node * - * Caller must hold 'net_lock' to ensure node and bearer are not deleted; + * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; * this also prevents link deletion. * * Returns pointer to link (or 0 if invalid link name). @@ -2754,11 +2752,11 @@ static struct link *link_find_link(const char *name, struct node **node) if (!link_name_validate(name, &link_name_parts)) return 0; - b_ptr = bearer_find_interface(link_name_parts.if_local); + b_ptr = tipc_bearer_find_interface(link_name_parts.if_local); if (!b_ptr) return 0; - *node = node_find(link_name_parts.addr_peer); + *node = tipc_node_find(link_name_parts.addr_peer); if (!*node) return 0; @@ -2769,8 +2767,8 @@ static struct link *link_find_link(const char *name, struct node **node) return l_ptr; } -struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, - u16 cmd) +struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, + u16 cmd) { struct tipc_link_config *args; u32 new_value; @@ -2779,61 +2777,62 @@ struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, int res; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); args = (struct tipc_link_config *)TLV_DATA(req_tlv_area); new_value = ntohl(args->value); - if (!strcmp(args->name, bc_link_name)) { + if (!strcmp(args->name, tipc_bclink_name)) { if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && - (bclink_set_queue_limits(new_value) == 0)) - return cfg_reply_none(); - return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change setting on broadcast link)"); + (tipc_bclink_set_queue_limits(new_value) == 0)) + return tipc_cfg_reply_none(); + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change setting on broadcast link)"); } - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); l_ptr = link_find_link(args->name, &node); if (!l_ptr) { - read_unlock_bh(&net_lock); - return cfg_reply_error_string("link not found"); + read_unlock_bh(&tipc_net_lock); + return tipc_cfg_reply_error_string("link not found"); } - node_lock(node); + tipc_node_lock(node); res = -EINVAL; switch (cmd) { case TIPC_CMD_SET_LINK_TOL: if ((new_value >= TIPC_MIN_LINK_TOL) && (new_value <= TIPC_MAX_LINK_TOL)) { link_set_supervision_props(l_ptr, new_value); - link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, new_value, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, new_value, 0, 0); res = TIPC_OK; } break; case TIPC_CMD_SET_LINK_PRI: - if (new_value < TIPC_NUM_LINK_PRI) { + if ((new_value >= TIPC_MIN_LINK_PRI) && + (new_value <= TIPC_MAX_LINK_PRI)) { l_ptr->priority = new_value; - link_send_proto_msg(l_ptr, STATE_MSG, - 0, 0, 0, new_value, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, new_value, 0); res = TIPC_OK; } break; case TIPC_CMD_SET_LINK_WINDOW: if ((new_value >= TIPC_MIN_LINK_WIN) && (new_value <= TIPC_MAX_LINK_WIN)) { - link_set_queue_limits(l_ptr, new_value); + tipc_link_set_queue_limits(l_ptr, new_value); res = TIPC_OK; } break; } - node_unlock(node); + tipc_node_unlock(node); - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); if (res) - return cfg_reply_error_string("cannot change link setting"); + return tipc_cfg_reply_error_string("cannot change link setting"); - return cfg_reply_none(); + return tipc_cfg_reply_none(); } /** @@ -2848,34 +2847,34 @@ static void link_reset_statistics(struct link *l_ptr) l_ptr->stats.recv_info = l_ptr->next_in_no; } -struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) { char *link_name; struct link *l_ptr; struct node *node; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); link_name = (char *)TLV_DATA(req_tlv_area); - if (!strcmp(link_name, bc_link_name)) { - if (bclink_reset_stats()) - return cfg_reply_error_string("link not found"); - return cfg_reply_none(); + if (!strcmp(link_name, tipc_bclink_name)) { + if (tipc_bclink_reset_stats()) + return tipc_cfg_reply_error_string("link not found"); + return tipc_cfg_reply_none(); } - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); l_ptr = link_find_link(link_name, &node); if (!l_ptr) { - read_unlock_bh(&net_lock); - return cfg_reply_error_string("link not found"); + read_unlock_bh(&tipc_net_lock); + return tipc_cfg_reply_error_string("link not found"); } - node_lock(node); + tipc_node_lock(node); link_reset_statistics(l_ptr); - node_unlock(node); - read_unlock_bh(&net_lock); - return cfg_reply_none(); + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); + return tipc_cfg_reply_none(); } /** @@ -2888,7 +2887,7 @@ static u32 percent(u32 count, u32 total) } /** - * link_stats - print link statistics + * tipc_link_stats - print link statistics * @name: link name * @buf: print buffer area * @buf_size: size of print buffer area @@ -2896,7 +2895,7 @@ static u32 percent(u32 count, u32 total) * Returns length of print buffer data string (or 0 if error) */ -static int link_stats(const char *name, char *buf, const u32 buf_size) +static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) { struct print_buf pb; struct link *l_ptr; @@ -2904,22 +2903,22 @@ static int link_stats(const char *name, char *buf, const u32 buf_size) char *status; u32 profile_total = 0; - if (!strcmp(name, bc_link_name)) - return bclink_stats(buf, buf_size); + if (!strcmp(name, tipc_bclink_name)) + return tipc_bclink_stats(buf, buf_size); - printbuf_init(&pb, buf, buf_size); + tipc_printbuf_init(&pb, buf, buf_size); - read_lock_bh(&net_lock); + read_lock_bh(&tipc_net_lock); l_ptr = link_find_link(name, &node); if (!l_ptr) { - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return 0; } - node_lock(node); + tipc_node_lock(node); - if (link_is_active(l_ptr)) + if (tipc_link_is_active(l_ptr)) status = "ACTIVE"; - else if (link_is_up(l_ptr)) + else if (tipc_link_is_up(l_ptr)) status = "STANDBY"; else status = "DEFUNCT"; @@ -2975,33 +2974,33 @@ static int link_stats(const char *name, char *buf, const u32 buf_size) ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) : 0); - node_unlock(node); - read_unlock_bh(&net_lock); - return printbuf_validate(&pb); + tipc_node_unlock(node); + read_unlock_bh(&tipc_net_lock); + return tipc_printbuf_validate(&pb); } #define MAX_LINK_STATS_INFO 2000 -struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) { struct sk_buff *buf; struct tlv_desc *rep_tlv; int str_len; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - str_len = link_stats((char *)TLV_DATA(req_tlv_area), - (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); + str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), + (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); if (!str_len) { buf_discard(buf); - return cfg_reply_error_string("link not found"); + return tipc_cfg_reply_error_string("link not found"); } skb_put(buf, TLV_SPACE(str_len)); @@ -3020,20 +3019,20 @@ int link_control(const char *name, u32 op, u32 val) u32 a; a = link_name2addr(name, &bearer_id); - read_lock_bh(&net_lock); - node = node_find(a); + read_lock_bh(&tipc_net_lock); + node = tipc_node_find(a); if (node) { - node_lock(node); + tipc_node_lock(node); l_ptr = node->links[bearer_id]; if (l_ptr) { if (op == TIPC_REMOVE_LINK) { struct bearer *b_ptr = l_ptr->b_ptr; spin_lock_bh(&b_ptr->publ.lock); - link_delete(l_ptr); + tipc_link_delete(l_ptr); spin_unlock_bh(&b_ptr->publ.lock); } if (op == TIPC_CMD_BLOCK_LINK) { - link_reset(l_ptr); + tipc_link_reset(l_ptr); l_ptr->blocked = 1; } if (op == TIPC_CMD_UNBLOCK_LINK) { @@ -3041,22 +3040,22 @@ int link_control(const char *name, u32 op, u32 val) } res = TIPC_OK; } - node_unlock(node); + tipc_node_unlock(node); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return res; } #endif /** - * link_get_max_pkt - get maximum packet size to use when sending to destination + * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination * @dest: network address of destination node * @selector: used to select from set of active links * * If no active link can be found, uses default maximum packet size. */ -u32 link_get_max_pkt(u32 dest, u32 selector) +u32 tipc_link_get_max_pkt(u32 dest, u32 selector) { struct node *n_ptr; struct link *l_ptr; @@ -3065,16 +3064,16 @@ u32 link_get_max_pkt(u32 dest, u32 selector) if (dest == tipc_own_addr) return MAX_MSG_SIZE; - read_lock_bh(&net_lock); - n_ptr = node_select(dest, selector); + read_lock_bh(&tipc_net_lock); + n_ptr = tipc_node_select(dest, selector); if (n_ptr) { - node_lock(n_ptr); + tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; if (l_ptr) res = link_max_pkt(l_ptr); - node_unlock(n_ptr); + tipc_node_unlock(n_ptr); } - read_unlock_bh(&net_lock); + read_unlock_bh(&tipc_net_lock); return res; } diff --git a/net/tipc/link.h b/net/tipc/link.h index c2553f073757..2d3c157f707d 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -221,44 +221,43 @@ struct link { struct port; -struct link *link_create(struct bearer *b_ptr, const u32 peer, - const struct tipc_media_addr *media_addr); -void link_delete(struct link *l_ptr); -void link_changeover(struct link *l_ptr); -void link_send_duplicate(struct link *l_ptr, struct link *dest); -void link_reset_fragments(struct link *l_ptr); -int link_is_up(struct link *l_ptr); -int link_is_active(struct link *l_ptr); -void link_start(struct link *l_ptr); -u32 link_push_packet(struct link *l_ptr); -void link_stop(struct link *l_ptr); -struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); -struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space); -struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); -void link_reset(struct link *l_ptr); -int link_send(struct sk_buff *buf, u32 dest, u32 selector); -int link_send_buf(struct link *l_ptr, struct sk_buff *buf); -u32 link_get_max_pkt(u32 dest,u32 selector); -int link_send_sections_fast(struct port* sender, - struct iovec const *msg_sect, - const u32 num_sect, - u32 destnode); - -int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); -void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, - struct tipc_msg *msg, u32 selector); -void link_recv_bundle(struct sk_buff *buf); -int link_recv_fragment(struct sk_buff **pending, - struct sk_buff **fb, - struct tipc_msg **msg); -void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, - u32 tolerance, u32 priority, u32 acked_mtu); -void link_push_queue(struct link *l_ptr); -u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, +struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, + const struct tipc_media_addr *media_addr); +void tipc_link_delete(struct link *l_ptr); +void tipc_link_changeover(struct link *l_ptr); +void tipc_link_send_duplicate(struct link *l_ptr, struct link *dest); +void tipc_link_reset_fragments(struct link *l_ptr); +int tipc_link_is_up(struct link *l_ptr); +int tipc_link_is_active(struct link *l_ptr); +void tipc_link_start(struct link *l_ptr); +u32 tipc_link_push_packet(struct link *l_ptr); +void tipc_link_stop(struct link *l_ptr); +struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); +struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); +void tipc_link_reset(struct link *l_ptr); +int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); +int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf); +u32 tipc_link_get_max_pkt(u32 dest,u32 selector); +int tipc_link_send_sections_fast(struct port* sender, + struct iovec const *msg_sect, + const u32 num_sect, + u32 destnode); +int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); +void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, + struct tipc_msg *msg, u32 selector); +void tipc_link_recv_bundle(struct sk_buff *buf); +int tipc_link_recv_fragment(struct sk_buff **pending, + struct sk_buff **fb, + struct tipc_msg **msg); +void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, + u32 tolerance, u32 priority, u32 acked_mtu); +void tipc_link_push_queue(struct link *l_ptr); +u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, struct sk_buff *buf); -void link_wakeup_ports(struct link *l_ptr, int all); -void link_set_queue_limits(struct link *l_ptr, u32 window); -void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits); +void tipc_link_wakeup_ports(struct link *l_ptr, int all); +void tipc_link_set_queue_limits(struct link *l_ptr, u32 window); +void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits); /* * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 03dbc55cb04c..3bd345a344e5 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -41,18 +41,7 @@ #include "bearer.h" -void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) -{ - memcpy(&((int *)m)[5], a, sizeof(*a)); -} - -void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) -{ - memcpy(a, &((int*)m)[5], sizeof(*a)); -} - - -void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) +void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) { u32 usr = msg_user(msg); tipc_printf(buf, str); @@ -318,7 +307,7 @@ void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); - media_addr_printf(buf, orig); + tipc_media_addr_printf(buf, orig); } if (msg_user(msg) == BCAST_PROTOCOL) { tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); @@ -326,9 +315,9 @@ void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) } tipc_printf(buf, "\n"); if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { - msg_print(buf,msg_get_wrapped(msg)," /"); + tipc_msg_print(buf,msg_get_wrapped(msg)," /"); } if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { - msg_print(buf,msg_get_wrapped(msg)," /"); + tipc_msg_print(buf,msg_get_wrapped(msg)," /"); } } diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 662c81862a0c..6699aaf7bd4c 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -37,7 +37,7 @@ #ifndef _TIPC_MSG_H #define _TIPC_MSG_H -#include <net/tipc/tipc_msg.h> +#include "core.h" #define TIPC_VERSION 2 #define DATA_LOW TIPC_LOW_IMPORTANCE @@ -805,14 +805,14 @@ static inline int msg_build(struct tipc_msg *hdr, return -EFAULT; } +static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) +{ + memcpy(&((int *)m)[5], a, sizeof(*a)); +} -struct tipc_media_addr; - -extern void msg_set_media_addr(struct tipc_msg *m, - struct tipc_media_addr *a); - -extern void msg_get_media_addr(struct tipc_msg *m, - struct tipc_media_addr *a); - +static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) +{ + memcpy(a, &((int*)m)[5], sizeof(*a)); +} #endif diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 41cbaf1a4a73..830f90999041 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -114,10 +114,10 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) } /** - * named_publish - tell other nodes about a new publication by this node + * tipc_named_publish - tell other nodes about a new publication by this node */ -void named_publish(struct publication *publ) +void tipc_named_publish(struct publication *publ) { struct sk_buff *buf; struct distr_item *item; @@ -133,15 +133,15 @@ void named_publish(struct publication *publ) item = (struct distr_item *)msg_data(buf_msg(buf)); publ_to_item(item, publ); - dbg("named_withdraw: broadcasting publish msg\n"); - cluster_broadcast(buf); + dbg("tipc_named_withdraw: broadcasting publish msg\n"); + tipc_cltr_broadcast(buf); } /** - * named_withdraw - tell other nodes about a withdrawn publication by this node + * tipc_named_withdraw - tell other nodes about a withdrawn publication by this node */ -void named_withdraw(struct publication *publ) +void tipc_named_withdraw(struct publication *publ) { struct sk_buff *buf; struct distr_item *item; @@ -157,15 +157,15 @@ void named_withdraw(struct publication *publ) item = (struct distr_item *)msg_data(buf_msg(buf)); publ_to_item(item, publ); - dbg("named_withdraw: broadcasting withdraw msg\n"); - cluster_broadcast(buf); + dbg("tipc_named_withdraw: broadcasting withdraw msg\n"); + tipc_cltr_broadcast(buf); } /** - * named_node_up - tell specified node about all publications by this node + * tipc_named_node_up - tell specified node about all publications by this node */ -void named_node_up(unsigned long node) +void tipc_named_node_up(unsigned long node) { struct publication *publ; struct distr_item *item = 0; @@ -175,7 +175,7 @@ void named_node_up(unsigned long node) u32 max_item_buf; assert(in_own_cluster(node)); - read_lock_bh(&nametbl_lock); + read_lock_bh(&tipc_nametbl_lock); max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE; max_item_buf *= ITEM_SIZE; rest = publ_cnt * ITEM_SIZE; @@ -196,15 +196,15 @@ void named_node_up(unsigned long node) left -= ITEM_SIZE; if (!left) { msg_set_link_selector(buf_msg(buf), node); - dbg("named_node_up: sending publish msg to " + dbg("tipc_named_node_up: sending publish msg to " "<%u.%u.%u>\n", tipc_zone(node), tipc_cluster(node), tipc_node(node)); - link_send(buf, node, node); + tipc_link_send(buf, node, node); buf = 0; } } exit: - read_unlock_bh(&nametbl_lock); + read_unlock_bh(&tipc_nametbl_lock); } /** @@ -221,73 +221,73 @@ exit: static void node_is_down(struct publication *publ) { struct publication *p; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); dbg("node_is_down: withdrawing %u, %u, %u\n", publ->type, publ->lower, publ->upper); publ->key += 1222345; - p = nametbl_remove_publ(publ->type, publ->lower, - publ->node, publ->ref, publ->key); + p = tipc_nametbl_remove_publ(publ->type, publ->lower, + publ->node, publ->ref, publ->key); assert(p == publ); - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); if (publ) kfree(publ); } /** - * named_recv - process name table update message sent by another node + * tipc_named_recv - process name table update message sent by another node */ -void named_recv(struct sk_buff *buf) +void tipc_named_recv(struct sk_buff *buf) { struct publication *publ; struct tipc_msg *msg = buf_msg(buf); struct distr_item *item = (struct distr_item *)msg_data(msg); u32 count = msg_data_sz(msg) / ITEM_SIZE; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); while (count--) { if (msg_type(msg) == PUBLICATION) { - dbg("named_recv: got publication for %u, %u, %u\n", + dbg("tipc_named_recv: got publication for %u, %u, %u\n", ntohl(item->type), ntohl(item->lower), ntohl(item->upper)); - publ = nametbl_insert_publ(ntohl(item->type), - ntohl(item->lower), - ntohl(item->upper), - TIPC_CLUSTER_SCOPE, - msg_orignode(msg), - ntohl(item->ref), - ntohl(item->key)); + publ = tipc_nametbl_insert_publ(ntohl(item->type), + ntohl(item->lower), + ntohl(item->upper), + TIPC_CLUSTER_SCOPE, + msg_orignode(msg), + ntohl(item->ref), + ntohl(item->key)); if (publ) { - nodesub_subscribe(&publ->subscr, - msg_orignode(msg), - publ, - (net_ev_handler)node_is_down); + tipc_nodesub_subscribe(&publ->subscr, + msg_orignode(msg), + publ, + (net_ev_handler)node_is_down); } } else if (msg_type(msg) == WITHDRAWAL) { - dbg("named_recv: got withdrawl for %u, %u, %u\n", + dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n", ntohl(item->type), ntohl(item->lower), ntohl(item->upper)); - publ = nametbl_remove_publ(ntohl(item->type), - ntohl(item->lower), - msg_orignode(msg), - ntohl(item->ref), - ntohl(item->key)); + publ = tipc_nametbl_remove_publ(ntohl(item->type), + ntohl(item->lower), + msg_orignode(msg), + ntohl(item->ref), + ntohl(item->key)); if (publ) { - nodesub_unsubscribe(&publ->subscr); + tipc_nodesub_unsubscribe(&publ->subscr); kfree(publ); } } else { - warn("named_recv: unknown msg\n"); + warn("tipc_named_recv: unknown msg\n"); } item++; } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); buf_discard(buf); } /** - * named_reinit - re-initialize local publication list + * tipc_named_reinit - re-initialize local publication list * * This routine is called whenever TIPC networking is (re)enabled. * All existing publications by this node that have "cluster" or "zone" scope @@ -295,15 +295,15 @@ void named_recv(struct sk_buff *buf) * (If the node's address is unchanged, the update loop terminates immediately.) */ -void named_reinit(void) +void tipc_named_reinit(void) { struct publication *publ; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); list_for_each_entry(publ, &publ_root, local_list) { if (publ->node == tipc_own_addr) break; publ->node = tipc_own_addr; } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); } diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index a04bdeac84ea..843da0172f4e 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -39,10 +39,10 @@ #include "name_table.h" -void named_publish(struct publication *publ); -void named_withdraw(struct publication *publ); -void named_node_up(unsigned long node); -void named_recv(struct sk_buff *buf); -void named_reinit(void); +void tipc_named_publish(struct publication *publ); +void tipc_named_withdraw(struct publication *publ); +void tipc_named_node_up(unsigned long node); +void tipc_named_recv(struct sk_buff *buf); +void tipc_named_reinit(void); #endif diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 972c83eb83b4..3f4b23bd08f7 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -99,9 +99,9 @@ struct name_table { u32 local_publ_count; }; -struct name_table table = { NULL } ; +static struct name_table table = { NULL } ; static atomic_t rsv_publ_ok = ATOMIC_INIT(0); -rwlock_t nametbl_lock = RW_LOCK_UNLOCKED; +rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; static inline int hash(int x) @@ -139,10 +139,10 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, } /** - * subseq_alloc - allocate a specified number of sub-sequence structures + * tipc_subseq_alloc - allocate a specified number of sub-sequence structures */ -struct sub_seq *subseq_alloc(u32 cnt) +struct sub_seq *tipc_subseq_alloc(u32 cnt) { u32 sz = cnt * sizeof(struct sub_seq); struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); @@ -153,16 +153,16 @@ struct sub_seq *subseq_alloc(u32 cnt) } /** - * nameseq_create - create a name sequence structure for the specified 'type' + * tipc_nameseq_create - create a name sequence structure for the specified 'type' * * Allocates a single sub-sequence structure and sets it to all 0's. */ -struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) +struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head) { struct name_seq *nseq = (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); - struct sub_seq *sseq = subseq_alloc(1); + struct sub_seq *sseq = tipc_subseq_alloc(1); if (!nseq || !sseq) { warn("Memory squeeze; failed to create name sequence\n"); @@ -175,7 +175,7 @@ struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) nseq->lock = SPIN_LOCK_UNLOCKED; nseq->type = type; nseq->sseqs = sseq; - dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", + dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", nseq, type, nseq->sseqs, nseq->first_free); nseq->alloc = 1; INIT_HLIST_NODE(&nseq->ns_list); @@ -240,10 +240,10 @@ static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) } /** - * nameseq_insert_publ - + * tipc_nameseq_insert_publ - */ -struct publication *nameseq_insert_publ(struct name_seq *nseq, +struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, u32 type, u32 lower, u32 upper, u32 scope, u32 node, u32 port, u32 key) { @@ -285,7 +285,7 @@ struct publication *nameseq_insert_publ(struct name_seq *nseq, if (nseq->first_free == nseq->alloc) { struct sub_seq *sseqs = nseq->sseqs; - nseq->sseqs = subseq_alloc(nseq->alloc * 2); + nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2); if (nseq->sseqs != NULL) { memcpy(nseq->sseqs, sseqs, nseq->alloc * sizeof (struct sub_seq)); @@ -354,23 +354,23 @@ struct publication *nameseq_insert_publ(struct name_seq *nseq, */ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { dbg("calling report_overlap()\n"); - subscr_report_overlap(s, - publ->lower, - publ->upper, - TIPC_PUBLISHED, - publ->ref, - publ->node, - created_subseq); + tipc_subscr_report_overlap(s, + publ->lower, + publ->upper, + TIPC_PUBLISHED, + publ->ref, + publ->node, + created_subseq); } return publ; } /** - * nameseq_remove_publ - + * tipc_nameseq_remove_publ - */ -struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, - u32 node, u32 ref, u32 key) +struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, + u32 node, u32 ref, u32 key) { struct publication *publ; struct publication *prev; @@ -470,24 +470,24 @@ struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, * Any subscriptions waiting ? */ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { - subscr_report_overlap(s, - publ->lower, - publ->upper, - TIPC_WITHDRAWN, - publ->ref, - publ->node, - removed_subseq); + tipc_subscr_report_overlap(s, + publ->lower, + publ->upper, + TIPC_WITHDRAWN, + publ->ref, + publ->node, + removed_subseq); } return publ; } /** - * nameseq_subscribe: attach a subscription, and issue + * tipc_nameseq_subscribe: attach a subscription, and issue * the prescribed number of events if there is any sub- * sequence overlapping with the requested sequence */ -void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) +void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s) { struct sub_seq *sseq = nseq->sseqs; @@ -498,18 +498,18 @@ void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) while (sseq != &nseq->sseqs[nseq->first_free]) { struct publication *zl = sseq->zone_list; - if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) { + if (zl && tipc_subscr_overlap(s,sseq->lower,sseq->upper)) { struct publication *crs = zl; int must_report = 1; do { - subscr_report_overlap(s, - sseq->lower, - sseq->upper, - TIPC_PUBLISHED, - crs->ref, - crs->node, - must_report); + tipc_subscr_report_overlap(s, + sseq->lower, + sseq->upper, + TIPC_PUBLISHED, + crs->ref, + crs->node, + must_report); must_report = 0; crs = crs->zone_list_next; } while (crs != zl); @@ -538,8 +538,8 @@ static struct name_seq *nametbl_find_seq(u32 type) return 0; }; -struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, - u32 scope, u32 node, u32 port, u32 key) +struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, + u32 scope, u32 node, u32 port, u32 key) { struct name_seq *seq = nametbl_find_seq(type); @@ -552,19 +552,19 @@ struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); if (!seq) { - seq = nameseq_create(type, &table.types[hash(type)]); - dbg("nametbl_insert_publ: created %x\n", seq); + seq = tipc_nameseq_create(type, &table.types[hash(type)]); + dbg("tipc_nametbl_insert_publ: created %x\n", seq); } if (!seq) return 0; assert(seq->type == type); - return nameseq_insert_publ(seq, type, lower, upper, - scope, node, port, key); + return tipc_nameseq_insert_publ(seq, type, lower, upper, + scope, node, port, key); } -struct publication *nametbl_remove_publ(u32 type, u32 lower, - u32 node, u32 ref, u32 key) +struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, + u32 node, u32 ref, u32 key) { struct publication *publ; struct name_seq *seq = nametbl_find_seq(type); @@ -573,7 +573,7 @@ struct publication *nametbl_remove_publ(u32 type, u32 lower, return 0; dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); - publ = nameseq_remove_publ(seq, lower, node, ref, key); + publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); if (!seq->first_free && list_empty(&seq->subscriptions)) { hlist_del_init(&seq->ns_list); @@ -584,14 +584,14 @@ struct publication *nametbl_remove_publ(u32 type, u32 lower, } /* - * nametbl_translate(): Translate tipc_name -> tipc_portid. + * tipc_nametbl_translate(): Translate tipc_name -> tipc_portid. * Very time-critical. * * Note: on entry 'destnode' is the search domain used during translation; * on exit it passes back the node address of the matching port (if any) */ -u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) +u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) { struct sub_seq *sseq; struct publication *publ = 0; @@ -601,7 +601,7 @@ u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) if (!in_scope(*destnode, tipc_own_addr)) return 0; - read_lock_bh(&nametbl_lock); + read_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(type); if (unlikely(!seq)) goto not_found; @@ -619,7 +619,7 @@ found: ref = publ->ref; *destnode = publ->node; spin_unlock_bh(&seq->lock); - read_unlock_bh(&nametbl_lock); + read_unlock_bh(&tipc_nametbl_lock); return ref; } publ = sseq->cluster_list; @@ -657,12 +657,12 @@ found: spin_unlock_bh(&seq->lock); not_found: *destnode = 0; - read_unlock_bh(&nametbl_lock); + read_unlock_bh(&tipc_nametbl_lock); return 0; } /** - * nametbl_mc_translate - find multicast destinations + * tipc_nametbl_mc_translate - find multicast destinations * * Creates list of all local ports that overlap the given multicast address; * also determines if any off-node ports overlap. @@ -674,15 +674,15 @@ not_found: * Returns non-zero if any off-node ports overlap */ -int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, - struct port_list *dports) +int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, + struct port_list *dports) { struct name_seq *seq; struct sub_seq *sseq; struct sub_seq *sseq_stop; int res = 0; - read_lock_bh(&nametbl_lock); + read_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(type); if (!seq) goto exit; @@ -700,7 +700,7 @@ int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, if (publ && (publ->scope <= limit)) do { if (publ->node == tipc_own_addr) - port_list_add(dports, publ->ref); + tipc_port_list_add(dports, publ->ref); else res = 1; publ = publ->cluster_list_next; @@ -709,15 +709,15 @@ int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, spin_unlock_bh(&seq->lock); exit: - read_unlock_bh(&nametbl_lock); + read_unlock_bh(&tipc_nametbl_lock); return res; } /** - * nametbl_publish_rsv - publish port name using a reserved name type + * tipc_nametbl_publish_rsv - publish port name using a reserved name type */ -int nametbl_publish_rsv(u32 ref, unsigned int scope, +int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) { int res; @@ -729,10 +729,10 @@ int nametbl_publish_rsv(u32 ref, unsigned int scope, } /** - * nametbl_publish - add name publication to network name tables + * tipc_nametbl_publish - add name publication to network name tables */ -struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, +struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, u32 scope, u32 port_ref, u32 key) { struct publication *publ; @@ -748,77 +748,77 @@ struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, return 0; } - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); table.local_publ_count++; - publ = nametbl_insert_publ(type, lower, upper, scope, + publ = tipc_nametbl_insert_publ(type, lower, upper, scope, tipc_own_addr, port_ref, key); if (publ && (scope != TIPC_NODE_SCOPE)) { - named_publish(publ); + tipc_named_publish(publ); } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); return publ; } /** - * nametbl_withdraw - withdraw name publication from network name tables + * tipc_nametbl_withdraw - withdraw name publication from network name tables */ -int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) +int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) { struct publication *publ; - dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); - write_lock_bh(&nametbl_lock); - publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); + dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); + write_lock_bh(&tipc_nametbl_lock); + publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); if (publ) { table.local_publ_count--; if (publ->scope != TIPC_NODE_SCOPE) - named_withdraw(publ); - write_unlock_bh(&nametbl_lock); + tipc_named_withdraw(publ); + write_unlock_bh(&tipc_nametbl_lock); list_del_init(&publ->pport_list); kfree(publ); return 1; } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); return 0; } /** - * nametbl_subscribe - add a subscription object to the name table + * tipc_nametbl_subscribe - add a subscription object to the name table */ void -nametbl_subscribe(struct subscription *s) +tipc_nametbl_subscribe(struct subscription *s) { u32 type = s->seq.type; struct name_seq *seq; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(type); if (!seq) { - seq = nameseq_create(type, &table.types[hash(type)]); + seq = tipc_nameseq_create(type, &table.types[hash(type)]); } if (seq){ spin_lock_bh(&seq->lock); - dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n", + dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n", seq, type, s->seq.lower, s->seq.upper); assert(seq->type == type); - nameseq_subscribe(seq, s); + tipc_nameseq_subscribe(seq, s); spin_unlock_bh(&seq->lock); } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); } /** - * nametbl_unsubscribe - remove a subscription object from name table + * tipc_nametbl_unsubscribe - remove a subscription object from name table */ void -nametbl_unsubscribe(struct subscription *s) +tipc_nametbl_unsubscribe(struct subscription *s) { struct name_seq *seq; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); seq = nametbl_find_seq(s->seq.type); if (seq != NULL){ spin_lock_bh(&seq->lock); @@ -830,7 +830,7 @@ nametbl_unsubscribe(struct subscription *s) kfree(seq); } } - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); } @@ -983,17 +983,17 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info, } } -void nametbl_print(struct print_buf *buf, const char *str) +void tipc_nametbl_print(struct print_buf *buf, const char *str) { tipc_printf(buf, str); - read_lock_bh(&nametbl_lock); + read_lock_bh(&tipc_nametbl_lock); nametbl_list(buf, 0, 0, 0, 0); - read_unlock_bh(&nametbl_lock); + read_unlock_bh(&tipc_nametbl_lock); } #define MAX_NAME_TBL_QUERY 32768 -struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) { struct sk_buff *buf; struct tipc_name_table_query *argv; @@ -1002,20 +1002,20 @@ struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) int str_len; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); + tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); - read_lock_bh(&nametbl_lock); + read_lock_bh(&tipc_nametbl_lock); nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), ntohl(argv->lowbound), ntohl(argv->upbound)); - read_unlock_bh(&nametbl_lock); - str_len = printbuf_validate(&b); + read_unlock_bh(&tipc_nametbl_lock); + str_len = tipc_printbuf_validate(&b); skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -1023,12 +1023,12 @@ struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) return buf; } -void nametbl_dump(void) +void tipc_nametbl_dump(void) { - nametbl_list(CONS, 0, 0, 0, 0); + nametbl_list(TIPC_CONS, 0, 0, 0, 0); } -int nametbl_init(void) +int tipc_nametbl_init(void) { int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; @@ -1036,14 +1036,14 @@ int nametbl_init(void) if (!table.types) return -ENOMEM; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); memset(table.types, 0, array_size); table.local_publ_count = 0; - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); return 0; } -void nametbl_stop(void) +void tipc_nametbl_stop(void) { struct hlist_head *seq_head; struct hlist_node *seq_node; @@ -1054,7 +1054,7 @@ void nametbl_stop(void) if (!table.types) return; - write_lock_bh(&nametbl_lock); + write_lock_bh(&tipc_nametbl_lock); for (i = 0; i < tipc_nametbl_size; i++) { seq_head = &table.types[i]; hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { @@ -1075,5 +1075,5 @@ void nametbl_stop(void) } kfree(table.types); table.types = NULL; - write_unlock_bh(&nametbl_lock); + write_unlock_bh(&tipc_nametbl_lock); } diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index f82693384f60..e8a3d71763ce 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -85,24 +85,24 @@ struct publication { }; -extern rwlock_t nametbl_lock; +extern rwlock_t tipc_nametbl_lock; -struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space); -u32 nametbl_translate(u32 type, u32 instance, u32 *node); -int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, +struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); +u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); +int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, struct port_list *dports); -int nametbl_publish_rsv(u32 ref, unsigned int scope, +int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, struct tipc_name_seq const *seq); -struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, +struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, u32 scope, u32 port_ref, u32 key); -int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); -struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, +int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); +struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, u32 scope, u32 node, u32 ref, u32 key); -struct publication *nametbl_remove_publ(u32 type, u32 lower, +struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, u32 node, u32 ref, u32 key); -void nametbl_subscribe(struct subscription *s); -void nametbl_unsubscribe(struct subscription *s); -int nametbl_init(void); -void nametbl_stop(void); +void tipc_nametbl_subscribe(struct subscription *s); +void tipc_nametbl_unsubscribe(struct subscription *s); +int tipc_nametbl_init(void); +void tipc_nametbl_stop(void); #endif diff --git a/net/tipc/net.c b/net/tipc/net.c index 6826b493c1d6..074891ad4f09 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -58,25 +58,25 @@ * 1: The routing hierarchy. * Comprises the structures 'zone', 'cluster', 'node', 'link' * and 'bearer'. The whole hierarchy is protected by a big - * read/write lock, net_lock, to enssure that nothing is added + * read/write lock, tipc_net_lock, to enssure that nothing is added * or removed while code is accessing any of these structures. * This layer must not be called from the two others while they * hold any of their own locks. * Neither must it itself do any upcalls to the other two before - * it has released net_lock and other protective locks. + * it has released tipc_net_lock and other protective locks. * - * Within the net_lock domain there are two sub-domains;'node' and + * Within the tipc_net_lock domain there are two sub-domains;'node' and * 'bearer', where local write operations are permitted, * provided that those are protected by individual spin_locks - * per instance. Code holding net_lock(read) and a node spin_lock + * per instance. Code holding tipc_net_lock(read) and a node spin_lock * is permitted to poke around in both the node itself and its * subordinate links. I.e, it can update link counters and queues, * change link state, send protocol messages, and alter the * "active_links" array in the node; but it can _not_ remove a link * or a node from the overall structure. * Correspondingly, individual bearers may change status within a - * net_lock(read), protected by an individual spin_lock ber bearer - * instance, but it needs net_lock(write) to remove/add any bearers. + * tipc_net_lock(read), protected by an individual spin_lock ber bearer + * instance, but it needs tipc_net_lock(write) to remove/add any bearers. * * * 2: The transport level of the protocol. @@ -97,91 +97,91 @@ * (Nobody is using read-only access to this, so it can just as * well be changed to a spin_lock) * - A spin lock to protect the registry of kernel/driver users (reg.c) - * - A global spin_lock (port_lock), which only task is to ensure + * - A global spin_lock (tipc_port_lock), which only task is to ensure * consistency where more than one port is involved in an operation, * i.e., whe a port is part of a linked list of ports. * There are two such lists; 'port_list', which is used for management, * and 'wait_list', which is used to queue ports during congestion. * * 3: The name table (name_table.c, name_distr.c, subscription.c) - * - There is one big read/write-lock (nametbl_lock) protecting the + * - There is one big read/write-lock (tipc_nametbl_lock) protecting the * overall name table structure. Nothing must be added/removed to * this structure without holding write access to it. * - There is one local spin_lock per sub_sequence, which can be seen - * as a sub-domain to the nametbl_lock domain. It is used only + * as a sub-domain to the tipc_nametbl_lock domain. It is used only * for translation operations, and is needed because a translation * steps the root of the 'publication' linked list between each lookup. - * This is always used within the scope of a nametbl_lock(read). + * This is always used within the scope of a tipc_nametbl_lock(read). * - A local spin_lock protecting the queue of subscriber events. */ -rwlock_t net_lock = RW_LOCK_UNLOCKED; -struct network net = { 0 }; +rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED; +struct network tipc_net = { 0 }; -struct node *net_select_remote_node(u32 addr, u32 ref) +struct node *tipc_net_select_remote_node(u32 addr, u32 ref) { - return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref); + return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref); } -u32 net_select_router(u32 addr, u32 ref) +u32 tipc_net_select_router(u32 addr, u32 ref) { - return zone_select_router(net.zones[tipc_zone(addr)], addr, ref); + return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref); } -u32 net_next_node(u32 a) +u32 tipc_net_next_node(u32 a) { - if (net.zones[tipc_zone(a)]) - return zone_next_node(a); + if (tipc_net.zones[tipc_zone(a)]) + return tipc_zone_next_node(a); return 0; } -void net_remove_as_router(u32 router) +void tipc_net_remove_as_router(u32 router) { u32 z_num; for (z_num = 1; z_num <= tipc_max_zones; z_num++) { - if (!net.zones[z_num]) + if (!tipc_net.zones[z_num]) continue; - zone_remove_as_router(net.zones[z_num], router); + tipc_zone_remove_as_router(tipc_net.zones[z_num], router); } } -void net_send_external_routes(u32 dest) +void tipc_net_send_external_routes(u32 dest) { u32 z_num; for (z_num = 1; z_num <= tipc_max_zones; z_num++) { - if (net.zones[z_num]) - zone_send_external_routes(net.zones[z_num], dest); + if (tipc_net.zones[z_num]) + tipc_zone_send_external_routes(tipc_net.zones[z_num], dest); } } -int net_init(void) +static int net_init(void) { u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1); - memset(&net, 0, sizeof(net)); - net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC); - if (!net.zones) { + memset(&tipc_net, 0, sizeof(tipc_net)); + tipc_net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC); + if (!tipc_net.zones) { return -ENOMEM; } - memset(net.zones, 0, sz); + memset(tipc_net.zones, 0, sz); return TIPC_OK; } -void net_stop(void) +static void net_stop(void) { u32 z_num; - if (!net.zones) + if (!tipc_net.zones) return; for (z_num = 1; z_num <= tipc_max_zones; z_num++) { - zone_delete(net.zones[z_num]); + tipc_zone_delete(tipc_net.zones[z_num]); } - kfree(net.zones); - net.zones = 0; + kfree(tipc_net.zones); + tipc_net.zones = 0; } static void net_route_named_msg(struct sk_buff *buf) @@ -191,26 +191,26 @@ static void net_route_named_msg(struct sk_buff *buf) u32 dport; if (!msg_named(msg)) { - msg_dbg(msg, "net->drop_nam:"); + msg_dbg(msg, "tipc_net->drop_nam:"); buf_discard(buf); return; } dnode = addr_domain(msg_lookup_scope(msg)); - dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); - dbg("net->lookup<%u,%u>-><%u,%x>\n", + dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); + dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n", msg_nametype(msg), msg_nameinst(msg), dport, dnode); if (dport) { msg_set_destnode(msg, dnode); msg_set_destport(msg, dport); - net_route_msg(buf); + tipc_net_route_msg(buf); return; } - msg_dbg(msg, "net->rej:NO NAME: "); + msg_dbg(msg, "tipc_net->rej:NO NAME: "); tipc_reject_msg(buf, TIPC_ERR_NO_NAME); } -void net_route_msg(struct sk_buff *buf) +void tipc_net_route_msg(struct sk_buff *buf) { struct tipc_msg *msg; u32 dnode; @@ -232,29 +232,29 @@ void net_route_msg(struct sk_buff *buf) return; } - msg_dbg(msg, "net->rout: "); + msg_dbg(msg, "tipc_net->rout: "); /* Handle message for this node */ dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); if (in_scope(dnode, tipc_own_addr)) { if (msg_isdata(msg)) { if (msg_mcast(msg)) - port_recv_mcast(buf, NULL); + tipc_port_recv_mcast(buf, NULL); else if (msg_destport(msg)) - port_recv_msg(buf); + tipc_port_recv_msg(buf); else net_route_named_msg(buf); return; } switch (msg_user(msg)) { case ROUTE_DISTRIBUTOR: - cluster_recv_routing_table(buf); + tipc_cltr_recv_routing_table(buf); break; case NAME_DISTRIBUTOR: - named_recv(buf); + tipc_named_recv(buf); break; case CONN_MANAGER: - port_recv_proto_msg(buf); + tipc_port_recv_proto_msg(buf); break; default: msg_dbg(msg,"DROP/NET/<REC<"); @@ -265,10 +265,10 @@ void net_route_msg(struct sk_buff *buf) /* Handle message for another node */ msg_dbg(msg, "NET>SEND>: "); - link_send(buf, dnode, msg_link_selector(msg)); + tipc_link_send(buf, dnode, msg_link_selector(msg)); } -int tipc_start_net(void) +int tipc_net_start(void) { char addr_string[16]; int res; @@ -277,35 +277,35 @@ int tipc_start_net(void) return -ENOPROTOOPT; tipc_mode = TIPC_NET_MODE; - named_reinit(); - port_reinit(); + tipc_named_reinit(); + tipc_port_reinit(); - if ((res = bearer_init()) || + if ((res = tipc_bearer_init()) || (res = net_init()) || - (res = cluster_init()) || - (res = bclink_init())) { + (res = tipc_cltr_init()) || + (res = tipc_bclink_init())) { return res; } - subscr_stop(); - cfg_stop(); - k_signal((Handler)subscr_start, 0); - k_signal((Handler)cfg_init, 0); + tipc_subscr_stop(); + tipc_cfg_stop(); + tipc_k_signal((Handler)tipc_subscr_start, 0); + tipc_k_signal((Handler)tipc_cfg_init, 0); info("Started in network mode\n"); info("Own node address %s, network identity %u\n", addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); return TIPC_OK; } -void tipc_stop_net(void) +void tipc_net_stop(void) { if (tipc_mode != TIPC_NET_MODE) return; - write_lock_bh(&net_lock); - bearer_stop(); + write_lock_bh(&tipc_net_lock); + tipc_bearer_stop(); tipc_mode = TIPC_NODE_MODE; - bclink_stop(); + tipc_bclink_stop(); net_stop(); - write_unlock_bh(&net_lock); + write_unlock_bh(&tipc_net_lock); info("Left network mode \n"); } diff --git a/net/tipc/net.h b/net/tipc/net.h index 948c6d42102c..f3e0b85e6475 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -49,18 +49,16 @@ struct network { }; -extern struct network net; -extern rwlock_t net_lock; +extern struct network tipc_net; +extern rwlock_t tipc_net_lock; -int net_init(void); -void net_stop(void); -void net_remove_as_router(u32 router); -void net_send_external_routes(u32 dest); -void net_route_msg(struct sk_buff *buf); -struct node *net_select_remote_node(u32 addr, u32 ref); -u32 net_select_router(u32 addr, u32 ref); +void tipc_net_remove_as_router(u32 router); +void tipc_net_send_external_routes(u32 dest); +void tipc_net_route_msg(struct sk_buff *buf); +struct node *tipc_net_select_remote_node(u32 addr, u32 ref); +u32 tipc_net_select_router(u32 addr, u32 ref); -int tipc_start_net(void); -void tipc_stop_net(void); +int tipc_net_start(void); +void tipc_net_stop(void); #endif diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 19b3f4022532..eb1bb4dce7af 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -47,13 +47,13 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) - rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); + rep_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); else - rep_buf = cfg_do_cmd(req_userhdr->dest, - req_userhdr->cmd, - NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, - NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), - hdr_space); + rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, + req_userhdr->cmd, + NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, + NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), + hdr_space); if (rep_buf) { skb_push(rep_buf, hdr_space); @@ -81,7 +81,7 @@ static struct genl_ops ops = { static int family_registered = 0; -int netlink_start(void) +int tipc_netlink_start(void) { @@ -103,7 +103,7 @@ int netlink_start(void) return -EFAULT; } -void netlink_stop(void) +void tipc_netlink_stop(void) { if (family_registered) { genl_unregister_family(&family); diff --git a/net/tipc/node.c b/net/tipc/node.c index 05688d01138b..6d65010e5fa1 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -45,17 +45,16 @@ #include "port.h" #include "bearer.h" #include "name_distr.h" -#include "net.h" void node_print(struct print_buf *buf, struct node *n_ptr, char *str); static void node_lost_contact(struct node *n_ptr); static void node_established_contact(struct node *n_ptr); -struct node *nodes = NULL; /* sorted list of nodes within cluster */ +struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ u32 tipc_own_tag = 0; -struct node *node_create(u32 addr) +struct node *tipc_node_create(u32 addr) { struct cluster *c_ptr; struct node *n_ptr; @@ -68,16 +67,16 @@ struct node *node_create(u32 addr) n_ptr->lock = SPIN_LOCK_UNLOCKED; INIT_LIST_HEAD(&n_ptr->nsub); - c_ptr = cluster_find(addr); + c_ptr = tipc_cltr_find(addr); if (c_ptr == NULL) - c_ptr = cluster_create(addr); + c_ptr = tipc_cltr_create(addr); if (c_ptr != NULL) { n_ptr->owner = c_ptr; - cluster_attach_node(c_ptr, n_ptr); + tipc_cltr_attach_node(c_ptr, n_ptr); n_ptr->last_router = -1; /* Insert node into ordered list */ - for (curr_node = &nodes; *curr_node; + for (curr_node = &tipc_nodes; *curr_node; curr_node = &(*curr_node)->next) { if (addr < (*curr_node)->addr) { n_ptr->next = *curr_node; @@ -93,13 +92,13 @@ struct node *node_create(u32 addr) return n_ptr; } -void node_delete(struct node *n_ptr) +void tipc_node_delete(struct node *n_ptr) { if (!n_ptr) return; #if 0 - /* Not needed because links are already deleted via bearer_stop() */ + /* Not needed because links are already deleted via tipc_bearer_stop() */ u32 l_num; @@ -114,12 +113,12 @@ void node_delete(struct node *n_ptr) /** - * node_link_up - handle addition of link + * tipc_node_link_up - handle addition of link * * Link becomes active (alone or shared) or standby, depending on its priority. */ -void node_link_up(struct node *n_ptr, struct link *l_ptr) +void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) { struct link **active = &n_ptr->active_links[0]; @@ -136,7 +135,7 @@ void node_link_up(struct node *n_ptr, struct link *l_ptr) info("Link is standby\n"); return; } - link_send_duplicate(active[0], l_ptr); + tipc_link_send_duplicate(active[0], l_ptr); if (l_ptr->priority == active[0]->priority) { active[0] = l_ptr; return; @@ -161,7 +160,7 @@ static void node_select_active_links(struct node *n_ptr) for (i = 0; i < MAX_BEARERS; i++) { struct link *l_ptr = n_ptr->links[i]; - if (!l_ptr || !link_is_up(l_ptr) || + if (!l_ptr || !tipc_link_is_up(l_ptr) || (l_ptr->priority < highest_prio)) continue; @@ -175,14 +174,14 @@ static void node_select_active_links(struct node *n_ptr) } /** - * node_link_down - handle loss of link + * tipc_node_link_down - handle loss of link */ -void node_link_down(struct node *n_ptr, struct link *l_ptr) +void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr) { struct link **active; - if (!link_is_active(l_ptr)) { + if (!tipc_link_is_active(l_ptr)) { info("Lost standby link <%s> on network plane %c\n", l_ptr->name, l_ptr->b_ptr->net_plane); return; @@ -197,40 +196,40 @@ void node_link_down(struct node *n_ptr, struct link *l_ptr) active[1] = active[0]; if (active[0] == l_ptr) node_select_active_links(n_ptr); - if (node_is_up(n_ptr)) - link_changeover(l_ptr); + if (tipc_node_is_up(n_ptr)) + tipc_link_changeover(l_ptr); else node_lost_contact(n_ptr); } -int node_has_active_links(struct node *n_ptr) +int tipc_node_has_active_links(struct node *n_ptr) { return (n_ptr && ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); } -int node_has_redundant_links(struct node *n_ptr) +int tipc_node_has_redundant_links(struct node *n_ptr) { - return (node_has_active_links(n_ptr) && + return (tipc_node_has_active_links(n_ptr) && (n_ptr->active_links[0] != n_ptr->active_links[1])); } -int node_has_active_routes(struct node *n_ptr) +int tipc_node_has_active_routes(struct node *n_ptr) { return (n_ptr && (n_ptr->last_router >= 0)); } -int node_is_up(struct node *n_ptr) +int tipc_node_is_up(struct node *n_ptr) { - return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr)); + return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr)); } -struct node *node_attach_link(struct link *l_ptr) +struct node *tipc_node_attach_link(struct link *l_ptr) { - struct node *n_ptr = node_find(l_ptr->addr); + struct node *n_ptr = tipc_node_find(l_ptr->addr); if (!n_ptr) - n_ptr = node_create(l_ptr->addr); + n_ptr = tipc_node_create(l_ptr->addr); if (n_ptr) { u32 bearer_id = l_ptr->b_ptr->identity; char addr_string[16]; @@ -246,7 +245,7 @@ struct node *node_attach_link(struct link *l_ptr) if (!n_ptr->links[bearer_id]) { n_ptr->links[bearer_id] = l_ptr; - net.zones[tipc_zone(l_ptr->addr)]->links++; + tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; n_ptr->link_cnt++; return n_ptr; } @@ -257,10 +256,10 @@ struct node *node_attach_link(struct link *l_ptr) return 0; } -void node_detach_link(struct node *n_ptr, struct link *l_ptr) +void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr) { n_ptr->links[l_ptr->b_ptr->identity] = 0; - net.zones[tipc_zone(l_ptr->addr)]->links--; + tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; n_ptr->link_cnt--; } @@ -315,45 +314,45 @@ static void node_established_contact(struct node *n_ptr) struct cluster *c_ptr; dbg("node_established_contact:-> %x\n", n_ptr->addr); - if (!node_has_active_routes(n_ptr)) { - k_signal((Handler)named_node_up, n_ptr->addr); + if (!tipc_node_has_active_routes(n_ptr)) { + tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); } /* Syncronize broadcast acks */ - n_ptr->bclink.acked = bclink_get_last_sent(); + n_ptr->bclink.acked = tipc_bclink_get_last_sent(); if (is_slave(tipc_own_addr)) return; if (!in_own_cluster(n_ptr->addr)) { /* Usage case 1 (see above) */ - c_ptr = cluster_find(tipc_own_addr); + c_ptr = tipc_cltr_find(tipc_own_addr); if (!c_ptr) - c_ptr = cluster_create(tipc_own_addr); + c_ptr = tipc_cltr_create(tipc_own_addr); if (c_ptr) - cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); + tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); return; } c_ptr = n_ptr->owner; if (is_slave(n_ptr->addr)) { /* Usage case 2 (see above) */ - cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); - cluster_send_local_routes(c_ptr, n_ptr->addr); + tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); + tipc_cltr_send_local_routes(c_ptr, n_ptr->addr); return; } if (n_ptr->bclink.supported) { - nmap_add(&cluster_bcast_nodes, n_ptr->addr); + tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); if (n_ptr->addr < tipc_own_addr) tipc_own_tag++; } /* Case 3 (see above) */ - net_send_external_routes(n_ptr->addr); - cluster_send_slave_routes(c_ptr, n_ptr->addr); - cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, - highest_allowed_slave); + tipc_net_send_external_routes(n_ptr->addr); + tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); + tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, + tipc_highest_allowed_slave); } static void node_lost_contact(struct node *n_ptr) @@ -375,39 +374,39 @@ static void node_lost_contact(struct node *n_ptr) n_ptr->bclink.defragm = NULL; } if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { - bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); + tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); } /* Update routing tables */ if (is_slave(tipc_own_addr)) { - net_remove_as_router(n_ptr->addr); + tipc_net_remove_as_router(n_ptr->addr); } else { if (!in_own_cluster(n_ptr->addr)) { /* Case 4 (see above) */ - c_ptr = cluster_find(tipc_own_addr); - cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); + c_ptr = tipc_cltr_find(tipc_own_addr); + tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); } else { /* Case 5 (see above) */ - c_ptr = cluster_find(n_ptr->addr); + c_ptr = tipc_cltr_find(n_ptr->addr); if (is_slave(n_ptr->addr)) { - cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, - tipc_max_nodes); + tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); } else { if (n_ptr->bclink.supported) { - nmap_remove(&cluster_bcast_nodes, - n_ptr->addr); + tipc_nmap_remove(&tipc_cltr_bcast_nodes, + n_ptr->addr); if (n_ptr->addr < tipc_own_addr) tipc_own_tag--; } - net_remove_as_router(n_ptr->addr); - cluster_bcast_lost_route(c_ptr, n_ptr->addr, - LOWEST_SLAVE, - highest_allowed_slave); + tipc_net_remove_as_router(n_ptr->addr); + tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, + LOWEST_SLAVE, + tipc_highest_allowed_slave); } } } - if (node_has_active_routes(n_ptr)) + if (tipc_node_has_active_routes(n_ptr)) return; info("Lost contact with %s\n", @@ -420,35 +419,35 @@ static void node_lost_contact(struct node *n_ptr) continue; l_ptr->reset_checkpoint = l_ptr->next_in_no; l_ptr->exp_msg_count = 0; - link_reset_fragments(l_ptr); + tipc_link_reset_fragments(l_ptr); } /* Notify subscribers */ list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { ns->node = 0; list_del_init(&ns->nodesub_list); - k_signal((Handler)ns->handle_node_down, - (unsigned long)ns->usr_handle); + tipc_k_signal((Handler)ns->handle_node_down, + (unsigned long)ns->usr_handle); } } /** - * node_select_next_hop - find the next-hop node for a message + * tipc_node_select_next_hop - find the next-hop node for a message * * Called by when cluster local lookup has failed. */ -struct node *node_select_next_hop(u32 addr, u32 selector) +struct node *tipc_node_select_next_hop(u32 addr, u32 selector) { struct node *n_ptr; u32 router_addr; - if (!addr_domain_valid(addr)) + if (!tipc_addr_domain_valid(addr)) return 0; /* Look for direct link to destination processsor */ - n_ptr = node_find(addr); - if (n_ptr && node_has_active_links(n_ptr)) + n_ptr = tipc_node_find(addr); + if (n_ptr && tipc_node_has_active_links(n_ptr)) return n_ptr; /* Cluster local system nodes *must* have direct links */ @@ -456,9 +455,9 @@ struct node *node_select_next_hop(u32 addr, u32 selector) return 0; /* Look for cluster local router with direct link to node */ - router_addr = node_select_router(n_ptr, selector); + router_addr = tipc_node_select_router(n_ptr, selector); if (router_addr) - return node_select(router_addr, selector); + return tipc_node_select(router_addr, selector); /* Slave nodes can only be accessed within own cluster via a known router with direct link -- if no router was found,give up */ @@ -467,25 +466,25 @@ struct node *node_select_next_hop(u32 addr, u32 selector) /* Inter zone/cluster -- find any direct link to remote cluster */ addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); - n_ptr = net_select_remote_node(addr, selector); - if (n_ptr && node_has_active_links(n_ptr)) + n_ptr = tipc_net_select_remote_node(addr, selector); + if (n_ptr && tipc_node_has_active_links(n_ptr)) return n_ptr; /* Last resort -- look for any router to anywhere in remote zone */ - router_addr = net_select_router(addr, selector); + router_addr = tipc_net_select_router(addr, selector); if (router_addr) - return node_select(router_addr, selector); + return tipc_node_select(router_addr, selector); return 0; } /** - * node_select_router - select router to reach specified node + * tipc_node_select_router - select router to reach specified node * * Uses a deterministic and fair algorithm for selecting router node. */ -u32 node_select_router(struct node *n_ptr, u32 ref) +u32 tipc_node_select_router(struct node *n_ptr, u32 ref) { u32 ulim; u32 mask; @@ -523,7 +522,7 @@ u32 node_select_router(struct node *n_ptr, u32 ref) return tipc_addr(own_zone(), own_cluster(), r); } -void node_add_router(struct node *n_ptr, u32 router) +void tipc_node_add_router(struct node *n_ptr, u32 router) { u32 r_num = tipc_node(router); @@ -534,7 +533,7 @@ void node_add_router(struct node *n_ptr, u32 router) !n_ptr->routers[n_ptr->last_router]); } -void node_remove_router(struct node *n_ptr, u32 router) +void tipc_node_remove_router(struct node *n_ptr, u32 router) { u32 r_num = tipc_node(router); @@ -547,7 +546,7 @@ void node_remove_router(struct node *n_ptr, u32 router) while ((--n_ptr->last_router >= 0) && !n_ptr->routers[n_ptr->last_router]); - if (!node_is_up(n_ptr)) + if (!tipc_node_is_up(n_ptr)) node_lost_contact(n_ptr); } @@ -572,16 +571,16 @@ u32 tipc_available_nodes(const u32 domain) struct node *n_ptr; u32 cnt = 0; - for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { if (!in_scope(domain, n_ptr->addr)) continue; - if (node_is_up(n_ptr)) + if (tipc_node_is_up(n_ptr)) cnt++; } return cnt; } -struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) { u32 domain; struct sk_buff *buf; @@ -589,40 +588,40 @@ struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space) struct tipc_node_info node_info; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); domain = *(u32 *)TLV_DATA(req_tlv_area); domain = ntohl(domain); - if (!addr_domain_valid(domain)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network address)"); + if (!tipc_addr_domain_valid(domain)) + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network address)"); - if (!nodes) - return cfg_reply_none(); + if (!tipc_nodes) + return tipc_cfg_reply_none(); /* For now, get space for all other nodes (will need to modify this when slave nodes are supported */ - buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * - (tipc_max_nodes - 1)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * + (tipc_max_nodes - 1)); if (!buf) return NULL; /* Add TLVs for all nodes in scope */ - for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { if (!in_scope(domain, n_ptr->addr)) continue; node_info.addr = htonl(n_ptr->addr); - node_info.up = htonl(node_is_up(n_ptr)); - cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, - &node_info, sizeof(node_info)); + node_info.up = htonl(tipc_node_is_up(n_ptr)); + tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, + &node_info, sizeof(node_info)); } return buf; } -struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) { u32 domain; struct sk_buff *buf; @@ -630,22 +629,22 @@ struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) struct tipc_link_info link_info; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); domain = *(u32 *)TLV_DATA(req_tlv_area); domain = ntohl(domain); - if (!addr_domain_valid(domain)) - return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network address)"); + if (!tipc_addr_domain_valid(domain)) + return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network address)"); - if (!nodes) - return cfg_reply_none(); + if (!tipc_nodes) + return tipc_cfg_reply_none(); /* For now, get space for 2 links to all other nodes + bcast link (will need to modify this when slave nodes are supported */ - buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * - (2 * (tipc_max_nodes - 1) + 1)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * + (2 * (tipc_max_nodes - 1) + 1)); if (!buf) return NULL; @@ -654,12 +653,12 @@ struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) link_info.dest = tipc_own_addr & 0xfffff00; link_info.dest = htonl(link_info.dest); link_info.up = htonl(1); - sprintf(link_info.str, bc_link_name); - cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); + sprintf(link_info.str, tipc_bclink_name); + tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); /* Add TLVs for any other links in scope */ - for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { u32 i; if (!in_scope(domain, n_ptr->addr)) @@ -668,10 +667,10 @@ struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) if (!n_ptr->links[i]) continue; link_info.dest = htonl(n_ptr->addr); - link_info.up = htonl(link_is_up(n_ptr->links[i])); + link_info.up = htonl(tipc_link_is_up(n_ptr->links[i])); strcpy(link_info.str, n_ptr->links[i]->name); - cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, - &link_info, sizeof(link_info)); + tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, + &link_info, sizeof(link_info)); } } diff --git a/net/tipc/node.h b/net/tipc/node.h index b39442badccf..29f7ae6992d4 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -92,31 +92,31 @@ struct node { } bclink; }; -extern struct node *nodes; +extern struct node *tipc_nodes; extern u32 tipc_own_tag; -struct node *node_create(u32 addr); -void node_delete(struct node *n_ptr); -struct node *node_attach_link(struct link *l_ptr); -void node_detach_link(struct node *n_ptr, struct link *l_ptr); -void node_link_down(struct node *n_ptr, struct link *l_ptr); -void node_link_up(struct node *n_ptr, struct link *l_ptr); -int node_has_active_links(struct node *n_ptr); -int node_has_redundant_links(struct node *n_ptr); -u32 node_select_router(struct node *n_ptr, u32 ref); -struct node *node_select_next_hop(u32 addr, u32 selector); -int node_is_up(struct node *n_ptr); -void node_add_router(struct node *n_ptr, u32 router); -void node_remove_router(struct node *n_ptr, u32 router); -struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space); -struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space); +struct node *tipc_node_create(u32 addr); +void tipc_node_delete(struct node *n_ptr); +struct node *tipc_node_attach_link(struct link *l_ptr); +void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr); +void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr); +void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr); +int tipc_node_has_active_links(struct node *n_ptr); +int tipc_node_has_redundant_links(struct node *n_ptr); +u32 tipc_node_select_router(struct node *n_ptr, u32 ref); +struct node *tipc_node_select_next_hop(u32 addr, u32 selector); +int tipc_node_is_up(struct node *n_ptr); +void tipc_node_add_router(struct node *n_ptr, u32 router); +void tipc_node_remove_router(struct node *n_ptr, u32 router); +struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); -static inline struct node *node_find(u32 addr) +static inline struct node *tipc_node_find(u32 addr) { if (likely(in_own_cluster(addr))) - return local_nodes[tipc_node(addr)]; - else if (addr_domain_valid(addr)) { - struct cluster *c_ptr = cluster_find(addr); + return tipc_local_nodes[tipc_node(addr)]; + else if (tipc_addr_domain_valid(addr)) { + struct cluster *c_ptr = tipc_cltr_find(addr); if (c_ptr) return c_ptr->nodes[tipc_node(addr)]; @@ -124,19 +124,19 @@ static inline struct node *node_find(u32 addr) return 0; } -static inline struct node *node_select(u32 addr, u32 selector) +static inline struct node *tipc_node_select(u32 addr, u32 selector) { if (likely(in_own_cluster(addr))) - return local_nodes[tipc_node(addr)]; - return node_select_next_hop(addr, selector); + return tipc_local_nodes[tipc_node(addr)]; + return tipc_node_select_next_hop(addr, selector); } -static inline void node_lock(struct node *n_ptr) +static inline void tipc_node_lock(struct node *n_ptr) { spin_lock_bh(&n_ptr->lock); } -static inline void node_unlock(struct node *n_ptr) +static inline void tipc_node_unlock(struct node *n_ptr) { spin_unlock_bh(&n_ptr->lock); } diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index 79375927916f..afeea121d8be 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -41,39 +41,39 @@ #include "addr.h" /** - * nodesub_subscribe - create "node down" subscription for specified node + * tipc_nodesub_subscribe - create "node down" subscription for specified node */ -void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, +void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, void *usr_handle, net_ev_handler handle_down) { node_sub->node = 0; if (addr == tipc_own_addr) return; - if (!addr_node_valid(addr)) { + if (!tipc_addr_node_valid(addr)) { warn("node_subscr with illegal %x\n", addr); return; } node_sub->handle_node_down = handle_down; node_sub->usr_handle = usr_handle; - node_sub->node = node_find(addr); + node_sub->node = tipc_node_find(addr); assert(node_sub->node); - node_lock(node_sub->node); + tipc_node_lock(node_sub->node); list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub); - node_unlock(node_sub->node); + tipc_node_unlock(node_sub->node); } /** - * nodesub_unsubscribe - cancel "node down" subscription (if any) + * tipc_nodesub_unsubscribe - cancel "node down" subscription (if any) */ -void nodesub_unsubscribe(struct node_subscr *node_sub) +void tipc_nodesub_unsubscribe(struct node_subscr *node_sub) { if (!node_sub->node) return; - node_lock(node_sub->node); + tipc_node_lock(node_sub->node); list_del_init(&node_sub->nodesub_list); - node_unlock(node_sub->node); + tipc_node_unlock(node_sub->node); } diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index a3b87ac4859b..01751c4fbb43 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -56,8 +56,8 @@ struct node_subscr { struct list_head nodesub_list; }; -void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, - void *usr_handle, net_ev_handler handle_down); -void nodesub_unsubscribe(struct node_subscr *node_sub); +void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, + void *usr_handle, net_ev_handler handle_down); +void tipc_nodesub_unsubscribe(struct node_subscr *node_sub); #endif diff --git a/net/tipc/port.c b/net/tipc/port.c index 66caca7abe92..72aae52bfec1 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -57,10 +57,10 @@ static struct sk_buff *msg_queue_head = 0; static struct sk_buff *msg_queue_tail = 0; -spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED; +spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED; static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; -LIST_HEAD(ports); +static LIST_HEAD(ports); static void port_handle_node_down(unsigned long ref); static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); @@ -107,7 +107,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, struct sk_buff *buf; struct sk_buff *ibuf = NULL; struct port_list dports = {0, NULL, }; - struct port *oport = port_deref(ref); + struct port *oport = tipc_port_deref(ref); int ext_targets; int res; @@ -129,8 +129,8 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, /* Figure out where to send multicast message */ - ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper, - TIPC_NODE_SCOPE, &dports); + ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper, + TIPC_NODE_SCOPE, &dports); /* Send message to destinations (duplicate it only if necessary) */ @@ -138,12 +138,12 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, if (dports.count != 0) { ibuf = skb_copy(buf, GFP_ATOMIC); if (ibuf == NULL) { - port_list_free(&dports); + tipc_port_list_free(&dports); buf_discard(buf); return -ENOMEM; } } - res = bclink_send_msg(buf); + res = tipc_bclink_send_msg(buf); if ((res < 0) && (dports.count != 0)) { buf_discard(ibuf); } @@ -153,20 +153,20 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, if (res >= 0) { if (ibuf) - port_recv_mcast(ibuf, &dports); + tipc_port_recv_mcast(ibuf, &dports); } else { - port_list_free(&dports); + tipc_port_list_free(&dports); } return res; } /** - * port_recv_mcast - deliver multicast message to all destination ports + * tipc_port_recv_mcast - deliver multicast message to all destination ports * * If there is no port list, perform a lookup to create one */ -void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) +void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) { struct tipc_msg* msg; struct port_list dports = {0, NULL, }; @@ -179,7 +179,7 @@ void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) /* Create destination port list, if one wasn't supplied */ if (dp == NULL) { - nametbl_mc_translate(msg_nametype(msg), + tipc_nametbl_mc_translate(msg_nametype(msg), msg_namelower(msg), msg_nameupper(msg), TIPC_CLUSTER_SCOPE, @@ -192,8 +192,8 @@ void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) if (dp->count != 0) { if (dp->count == 1) { msg_set_destport(msg, dp->ports[0]); - port_recv_msg(buf); - port_list_free(dp); + tipc_port_recv_msg(buf); + tipc_port_list_free(dp); return; } for (; cnt < dp->count; cnt++) { @@ -209,12 +209,12 @@ void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) item = item->next; } msg_set_destport(buf_msg(b),item->ports[index]); - port_recv_msg(b); + tipc_port_recv_msg(b); } } exit: buf_discard(buf); - port_list_free(dp); + tipc_port_list_free(dp); } /** @@ -238,14 +238,14 @@ u32 tipc_createport_raw(void *usr_handle, return 0; } memset(p_ptr, 0, sizeof(*p_ptr)); - ref = ref_acquire(p_ptr, &p_ptr->publ.lock); + ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock); if (!ref) { warn("Reference Table Exhausted\n"); kfree(p_ptr); return 0; } - port_lock(ref); + tipc_port_lock(ref); p_ptr->publ.ref = ref; msg = &p_ptr->publ.phdr; msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); @@ -264,12 +264,12 @@ u32 tipc_createport_raw(void *usr_handle, p_ptr->wakeup = wakeup; p_ptr->user_port = 0; k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); - spin_lock_bh(&port_list_lock); + spin_lock_bh(&tipc_port_list_lock); INIT_LIST_HEAD(&p_ptr->publications); INIT_LIST_HEAD(&p_ptr->port_list); list_add_tail(&p_ptr->port_list, &ports); - spin_unlock_bh(&port_list_lock); - port_unlock(p_ptr); + spin_unlock_bh(&tipc_port_list_lock); + tipc_port_unlock(p_ptr); return ref; } @@ -279,31 +279,31 @@ int tipc_deleteport(u32 ref) struct sk_buff *buf = 0; tipc_withdraw(ref, 0, 0); - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; - ref_discard(ref); - port_unlock(p_ptr); + tipc_ref_discard(ref); + tipc_port_unlock(p_ptr); k_cancel_timer(&p_ptr->timer); if (p_ptr->publ.connected) { buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); - nodesub_unsubscribe(&p_ptr->subscription); + tipc_nodesub_unsubscribe(&p_ptr->subscription); } if (p_ptr->user_port) { - reg_remove_port(p_ptr->user_port); + tipc_reg_remove_port(p_ptr->user_port); kfree(p_ptr->user_port); } - spin_lock_bh(&port_list_lock); + spin_lock_bh(&tipc_port_list_lock); list_del(&p_ptr->port_list); list_del(&p_ptr->wait_list); - spin_unlock_bh(&port_list_lock); + spin_unlock_bh(&tipc_port_list_lock); k_term_timer(&p_ptr->timer); kfree(p_ptr); dbg("Deleted port %u\n", ref); - net_route_msg(buf); + tipc_net_route_msg(buf); return TIPC_OK; } @@ -315,7 +315,7 @@ int tipc_deleteport(u32 ref) struct tipc_port *tipc_get_port(const u32 ref) { - return (struct tipc_port *)ref_deref(ref); + return (struct tipc_port *)tipc_ref_deref(ref); } /** @@ -327,11 +327,11 @@ void *tipc_get_handle(const u32 ref) struct port *p_ptr; void * handle; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return 0; handle = p_ptr->publ.usr_handle; - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return handle; } @@ -344,7 +344,7 @@ int tipc_portunreliable(u32 ref, unsigned int *isunreliable) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; *isunreliable = port_unreliable(p_ptr); @@ -356,11 +356,11 @@ int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return TIPC_OK; } @@ -373,7 +373,7 @@ int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; *isunrejectable = port_unreturnable(p_ptr); @@ -385,11 +385,11 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return TIPC_OK; } @@ -476,25 +476,25 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) /* send self-abort message when rejecting on a connected port */ if (msg_connected(msg)) { struct sk_buff *abuf = 0; - struct port *p_ptr = port_lock(msg_destport(msg)); + struct port *p_ptr = tipc_port_lock(msg_destport(msg)); if (p_ptr) { if (p_ptr->publ.connected) abuf = port_build_self_abort_msg(p_ptr, err); - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); } - net_route_msg(abuf); + tipc_net_route_msg(abuf); } /* send rejected message */ buf_discard(buf); - net_route_msg(rbuf); + tipc_net_route_msg(rbuf); return data_sz; } -int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, - int err) +int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, + struct iovec const *msg_sect, u32 num_sect, + int err) { struct sk_buff *buf; int res; @@ -509,7 +509,7 @@ int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, static void port_timeout(unsigned long ref) { - struct port *p_ptr = port_lock(ref); + struct port *p_ptr = tipc_port_lock(ref); struct sk_buff *buf = 0; if (!p_ptr || !p_ptr->publ.connected) @@ -532,21 +532,21 @@ static void port_timeout(unsigned long ref) p_ptr->probing_state = PROBING; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); } - port_unlock(p_ptr); - net_route_msg(buf); + tipc_port_unlock(p_ptr); + tipc_net_route_msg(buf); } static void port_handle_node_down(unsigned long ref) { - struct port *p_ptr = port_lock(ref); + struct port *p_ptr = tipc_port_lock(ref); struct sk_buff* buf = 0; if (!p_ptr) return; buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); - port_unlock(p_ptr); - net_route_msg(buf); + tipc_port_unlock(p_ptr); + tipc_net_route_msg(buf); } @@ -589,10 +589,10 @@ static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) 0); } -void port_recv_proto_msg(struct sk_buff *buf) +void tipc_port_recv_proto_msg(struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); - struct port *p_ptr = port_lock(msg_destport(msg)); + struct port *p_ptr = tipc_port_lock(msg_destport(msg)); u32 err = TIPC_OK; struct sk_buff *r_buf = 0; struct sk_buff *abort_buf = 0; @@ -615,11 +615,11 @@ void port_recv_proto_msg(struct sk_buff *buf) } } if (msg_type(msg) == CONN_ACK) { - int wakeup = port_congested(p_ptr) && + int wakeup = tipc_port_congested(p_ptr) && p_ptr->publ.congested && p_ptr->wakeup; p_ptr->acked += msg_msgcnt(msg); - if (port_congested(p_ptr)) + if (tipc_port_congested(p_ptr)) goto exit; p_ptr->publ.congested = 0; if (!wakeup) @@ -659,9 +659,9 @@ void port_recv_proto_msg(struct sk_buff *buf) port_incr_out_seqno(p_ptr); exit: if (p_ptr) - port_unlock(p_ptr); - net_route_msg(r_buf); - net_route_msg(abort_buf); + tipc_port_unlock(p_ptr); + tipc_net_route_msg(r_buf); + tipc_net_route_msg(abort_buf); buf_discard(buf); } @@ -704,7 +704,7 @@ static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) #define MAX_PORT_QUERY 32768 -struct sk_buff *port_get_ports(void) +struct sk_buff *tipc_port_get_ports(void) { struct sk_buff *buf; struct tlv_desc *rep_tlv; @@ -712,20 +712,20 @@ struct sk_buff *port_get_ports(void) struct port *p_ptr; int str_len; - buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); if (!buf) return NULL; rep_tlv = (struct tlv_desc *)buf->data; - printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); - spin_lock_bh(&port_list_lock); + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); + spin_lock_bh(&tipc_port_list_lock); list_for_each_entry(p_ptr, &ports, port_list) { spin_lock_bh(p_ptr->publ.lock); port_print(p_ptr, &pb, 0); spin_unlock_bh(p_ptr->publ.lock); } - spin_unlock_bh(&port_list_lock); - str_len = printbuf_validate(&pb); + spin_unlock_bh(&tipc_port_list_lock); + str_len = tipc_printbuf_validate(&pb); skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -752,22 +752,22 @@ struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) ref = *(u32 *)TLV_DATA(req_tlv_area); ref = ntohl(ref); - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return cfg_reply_error_string("port not found"); - buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); + buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); if (!buf) { - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return NULL; } rep_tlv = (struct tlv_desc *)buf->data; - printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); + tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); port_print(p_ptr, &pb, 1); /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */ - port_unlock(p_ptr); - str_len = printbuf_validate(&pb); + tipc_port_unlock(p_ptr); + str_len = tipc_printbuf_validate(&pb); skb_put(buf, TLV_SPACE(str_len)); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -777,19 +777,19 @@ struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) #endif -void port_reinit(void) +void tipc_port_reinit(void) { struct port *p_ptr; struct tipc_msg *msg; - spin_lock_bh(&port_list_lock); + spin_lock_bh(&tipc_port_list_lock); list_for_each_entry(p_ptr, &ports, port_list) { msg = &p_ptr->publ.phdr; if (msg_orignode(msg) == tipc_own_addr) break; msg_set_orignode(msg, tipc_own_addr); } - spin_unlock_bh(&port_list_lock); + spin_unlock_bh(&tipc_port_list_lock); } @@ -820,7 +820,7 @@ static void port_dispatcher_sigh(void *dummy) struct tipc_msg *msg = buf_msg(buf); u32 dref = msg_destport(msg); - p_ptr = port_lock(dref); + p_ptr = tipc_port_lock(dref); if (!p_ptr) { /* Port deleted while msg in queue */ tipc_reject_msg(buf, TIPC_ERR_NO_PORT); @@ -976,7 +976,7 @@ static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) msg_queue_tail = buf; } else { msg_queue_tail = msg_queue_head = buf; - k_signal((Handler)port_dispatcher_sigh, 0); + tipc_k_signal((Handler)port_dispatcher_sigh, 0); } spin_unlock_bh(&queue_lock); return TIPC_OK; @@ -994,14 +994,14 @@ static void port_wakeup_sh(unsigned long ref) tipc_continue_event cb = 0; void *uh = 0; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (p_ptr) { up_ptr = p_ptr->user_port; if (up_ptr) { cb = up_ptr->continue_event_cb; uh = up_ptr->usr_handle; } - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); } if (cb) cb(uh, ref); @@ -1010,7 +1010,7 @@ static void port_wakeup_sh(unsigned long ref) static void port_wakeup(struct tipc_port *p_ptr) { - k_signal((Handler)port_wakeup_sh, p_ptr->ref); + tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref); } void tipc_acknowledge(u32 ref, u32 ack) @@ -1018,7 +1018,7 @@ void tipc_acknowledge(u32 ref, u32 ack) struct port *p_ptr; struct sk_buff *buf = 0; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return; if (p_ptr->publ.connected) { @@ -1033,8 +1033,8 @@ void tipc_acknowledge(u32 ref, u32 ack) port_out_seqno(p_ptr), ack); } - port_unlock(p_ptr); - net_route_msg(buf); + tipc_port_unlock(p_ptr); + tipc_net_route_msg(buf); } /* @@ -1063,7 +1063,7 @@ int tipc_createport(u32 user_ref, return -ENOMEM; } ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance); - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) { kfree(up_ptr); return -ENOMEM; @@ -1081,10 +1081,10 @@ int tipc_createport(u32 user_ref, up_ptr->conn_msg_cb = conn_msg_cb; up_ptr->continue_event_cb = continue_event_cb; INIT_LIST_HEAD(&up_ptr->uport_list); - reg_add_port(up_ptr); + tipc_reg_add_port(up_ptr); *portref = p_ptr->publ.ref; dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref); - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return TIPC_OK; } @@ -1099,7 +1099,7 @@ int tipc_portimportance(u32 ref, unsigned int *importance) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); @@ -1114,7 +1114,7 @@ int tipc_set_portimportance(u32 ref, unsigned int imp) if (imp > TIPC_CRITICAL_IMPORTANCE) return -EINVAL; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; msg_set_importance(&p_ptr->publ.phdr, (u32)imp); @@ -1130,7 +1130,7 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) u32 key; int res = -EINVAL; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " "lower = %u, upper = %u\n", ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); @@ -1147,8 +1147,8 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) res = -EADDRINUSE; goto exit; } - publ = nametbl_publish(seq->type, seq->lower, seq->upper, - scope, p_ptr->publ.ref, key); + publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, + scope, p_ptr->publ.ref, key); if (publ) { list_add(&publ->pport_list, &p_ptr->publications); p_ptr->pub_count++; @@ -1156,7 +1156,7 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) res = TIPC_OK; } exit: - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return res; } @@ -1167,7 +1167,7 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) struct publication *tpubl; int res = -EINVAL; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; if (!p_ptr->publ.published) @@ -1175,8 +1175,8 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) if (!seq) { list_for_each_entry_safe(publ, tpubl, &p_ptr->publications, pport_list) { - nametbl_withdraw(publ->type, publ->lower, - publ->ref, publ->key); + tipc_nametbl_withdraw(publ->type, publ->lower, + publ->ref, publ->key); } res = TIPC_OK; } else { @@ -1190,8 +1190,8 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) continue; if (publ->upper != seq->upper) break; - nametbl_withdraw(publ->type, publ->lower, - publ->ref, publ->key); + tipc_nametbl_withdraw(publ->type, publ->lower, + publ->ref, publ->key); res = TIPC_OK; break; } @@ -1199,7 +1199,7 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) if (list_empty(&p_ptr->publications)) p_ptr->publ.published = 0; exit: - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return res; } @@ -1209,7 +1209,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) struct tipc_msg *msg; int res = -EINVAL; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; if (p_ptr->publ.published || p_ptr->publ.connected) @@ -1234,13 +1234,13 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) p_ptr->publ.connected = 1; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); - nodesub_subscribe(&p_ptr->subscription,peer->node, + tipc_nodesub_subscribe(&p_ptr->subscription,peer->node, (void *)(unsigned long)ref, (net_ev_handler)port_handle_node_down); res = TIPC_OK; exit: - port_unlock(p_ptr); - p_ptr->max_pkt = link_get_max_pkt(peer->node, ref); + tipc_port_unlock(p_ptr); + p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); return res; } @@ -1254,16 +1254,16 @@ int tipc_disconnect(u32 ref) struct port *p_ptr; int res = -ENOTCONN; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; if (p_ptr->publ.connected) { p_ptr->publ.connected = 0; /* let timer expire on it's own to avoid deadlock! */ - nodesub_unsubscribe(&p_ptr->subscription); + tipc_nodesub_unsubscribe(&p_ptr->subscription); res = TIPC_OK; } - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return res; } @@ -1275,7 +1275,7 @@ int tipc_shutdown(u32 ref) struct port *p_ptr; struct sk_buff *buf = 0; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; @@ -1293,8 +1293,8 @@ int tipc_shutdown(u32 ref) port_out_seqno(p_ptr), 0); } - port_unlock(p_ptr); - net_route_msg(buf); + tipc_port_unlock(p_ptr); + tipc_net_route_msg(buf); return tipc_disconnect(ref); } @@ -1302,11 +1302,11 @@ int tipc_isconnected(u32 ref, int *isconnected) { struct port *p_ptr; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; *isconnected = p_ptr->publ.connected; - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return TIPC_OK; } @@ -1315,7 +1315,7 @@ int tipc_peer(u32 ref, struct tipc_portid *peer) struct port *p_ptr; int res; - p_ptr = port_lock(ref); + p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; if (p_ptr->publ.connected) { @@ -1324,23 +1324,23 @@ int tipc_peer(u32 ref, struct tipc_portid *peer) res = TIPC_OK; } else res = -ENOTCONN; - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); return res; } int tipc_ref_valid(u32 ref) { /* Works irrespective of type */ - return !!ref_deref(ref); + return !!tipc_ref_deref(ref); } /* - * port_recv_sections(): Concatenate and deliver sectioned + * tipc_port_recv_sections(): Concatenate and deliver sectioned * message for this node. */ -int port_recv_sections(struct port *sender, unsigned int num_sect, +int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, struct iovec const *msg_sect) { struct sk_buff *buf; @@ -1349,7 +1349,7 @@ int port_recv_sections(struct port *sender, unsigned int num_sect, res = msg_build(&sender->publ.phdr, msg_sect, num_sect, MAX_MSG_SIZE, !sender->user_port, &buf); if (likely(buf)) - port_recv_msg(buf); + tipc_port_recv_msg(buf); return res; } @@ -1363,18 +1363,18 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) u32 destnode; int res; - p_ptr = port_deref(ref); + p_ptr = tipc_port_deref(ref); if (!p_ptr || !p_ptr->publ.connected) return -EINVAL; p_ptr->publ.congested = 1; - if (!port_congested(p_ptr)) { + if (!tipc_port_congested(p_ptr)) { destnode = port_peernode(p_ptr); if (likely(destnode != tipc_own_addr)) - res = link_send_sections_fast(p_ptr, msg_sect, num_sect, - destnode); + res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, + destnode); else - res = port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); if (likely(res != -ELINKCONG)) { port_incr_out_seqno(p_ptr); @@ -1404,7 +1404,7 @@ int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) u32 sz; u32 res; - p_ptr = port_deref(ref); + p_ptr = tipc_port_deref(ref); if (!p_ptr || !p_ptr->publ.connected) return -EINVAL; @@ -1419,11 +1419,11 @@ int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) memcpy(buf->data, (unchar *)msg, hsz); destnode = msg_destnode(msg); p_ptr->publ.congested = 1; - if (!port_congested(p_ptr)) { + if (!tipc_port_congested(p_ptr)) { if (likely(destnode != tipc_own_addr)) res = tipc_send_buf_fast(buf, destnode); else { - port_recv_msg(buf); + tipc_port_recv_msg(buf); res = sz; } if (likely(res != -ELINKCONG)) { @@ -1458,7 +1458,7 @@ int tipc_forward2name(u32 ref, u32 destport = 0; int res; - p_ptr = port_deref(ref); + p_ptr = tipc_port_deref(ref); if (!p_ptr || p_ptr->publ.connected) return -EINVAL; @@ -1472,16 +1472,16 @@ int tipc_forward2name(u32 ref, msg_set_lookup_scope(msg, addr_scope(domain)); if (importance <= TIPC_CRITICAL_IMPORTANCE) msg_set_importance(msg,importance); - destport = nametbl_translate(name->type, name->instance, &destnode); + destport = tipc_nametbl_translate(name->type, name->instance, &destnode); msg_set_destnode(msg, destnode); msg_set_destport(msg, destport); if (likely(destport || destnode)) { p_ptr->sent++; if (likely(destnode == tipc_own_addr)) - return port_recv_sections(p_ptr, num_sect, msg_sect); - res = link_send_sections_fast(p_ptr, msg_sect, num_sect, - destnode); + return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, + destnode); if (likely(res != -ELINKCONG)) return res; if (port_unreliable(p_ptr)) { @@ -1490,8 +1490,8 @@ int tipc_forward2name(u32 ref, } return -ELINKCONG; } - return port_reject_sections(p_ptr, msg, msg_sect, num_sect, - TIPC_ERR_NO_NAME); + return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, + TIPC_ERR_NO_NAME); } /** @@ -1530,7 +1530,7 @@ int tipc_forward_buf2name(u32 ref, u32 destport = 0; int res; - p_ptr = (struct port *)ref_deref(ref); + p_ptr = (struct port *)tipc_ref_deref(ref); if (!p_ptr || p_ptr->publ.connected) return -EINVAL; @@ -1545,7 +1545,7 @@ int tipc_forward_buf2name(u32 ref, msg_set_lookup_scope(msg, addr_scope(domain)); msg_set_hdr_sz(msg, LONG_H_SIZE); msg_set_size(msg, LONG_H_SIZE + dsz); - destport = nametbl_translate(name->type, name->instance, &destnode); + destport = tipc_nametbl_translate(name->type, name->instance, &destnode); msg_set_destnode(msg, destnode); msg_set_destport(msg, destport); msg_dbg(msg, "forw2name ==> "); @@ -1557,7 +1557,7 @@ int tipc_forward_buf2name(u32 ref, if (likely(destport || destnode)) { p_ptr->sent++; if (destnode == tipc_own_addr) - return port_recv_msg(buf); + return tipc_port_recv_msg(buf); res = tipc_send_buf_fast(buf, destnode); if (likely(res != -ELINKCONG)) return res; @@ -1601,7 +1601,7 @@ int tipc_forward2port(u32 ref, struct tipc_msg *msg; int res; - p_ptr = port_deref(ref); + p_ptr = tipc_port_deref(ref); if (!p_ptr || p_ptr->publ.connected) return -EINVAL; @@ -1616,8 +1616,8 @@ int tipc_forward2port(u32 ref, msg_set_importance(msg, importance); p_ptr->sent++; if (dest->node == tipc_own_addr) - return port_recv_sections(p_ptr, num_sect, msg_sect); - res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); + return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); + res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); if (likely(res != -ELINKCONG)) return res; if (port_unreliable(p_ptr)) { @@ -1658,7 +1658,7 @@ int tipc_forward_buf2port(u32 ref, struct tipc_msg *msg; int res; - p_ptr = (struct port *)ref_deref(ref); + p_ptr = (struct port *)tipc_ref_deref(ref); if (!p_ptr || p_ptr->publ.connected) return -EINVAL; @@ -1680,7 +1680,7 @@ int tipc_forward_buf2port(u32 ref, msg_dbg(msg, "buf2port: "); p_ptr->sent++; if (dest->node == tipc_own_addr) - return port_recv_msg(buf); + return tipc_port_recv_msg(buf); res = tipc_send_buf_fast(buf, dest->node); if (likely(res != -ELINKCONG)) return res; diff --git a/net/tipc/port.h b/net/tipc/port.h index e829a99d3b7f..839f100da646 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -37,7 +37,7 @@ #ifndef _TIPC_PORT_H #define _TIPC_PORT_H -#include <net/tipc/tipc_port.h> +#include "core.h" #include "ref.h" #include "net.h" #include "msg.h" @@ -110,65 +110,65 @@ struct port { struct node_subscr subscription; }; -extern spinlock_t port_list_lock; +extern spinlock_t tipc_port_list_lock; struct port_list; -int port_recv_sections(struct port *p_ptr, u32 num_sect, - struct iovec const *msg_sect); -int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, - struct iovec const *msg_sect, u32 num_sect, - int err); -struct sk_buff *port_get_ports(void); +int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect, + struct iovec const *msg_sect); +int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, + struct iovec const *msg_sect, u32 num_sect, + int err); +struct sk_buff *tipc_port_get_ports(void); struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space); -void port_recv_proto_msg(struct sk_buff *buf); -void port_recv_mcast(struct sk_buff *buf, struct port_list *dp); -void port_reinit(void); +void tipc_port_recv_proto_msg(struct sk_buff *buf); +void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); +void tipc_port_reinit(void); /** - * port_lock - lock port instance referred to and return its pointer + * tipc_port_lock - lock port instance referred to and return its pointer */ -static inline struct port *port_lock(u32 ref) +static inline struct port *tipc_port_lock(u32 ref) { - return (struct port *)ref_lock(ref); + return (struct port *)tipc_ref_lock(ref); } /** - * port_unlock - unlock a port instance + * tipc_port_unlock - unlock a port instance * - * Can use pointer instead of ref_unlock() since port is already locked. + * Can use pointer instead of tipc_ref_unlock() since port is already locked. */ -static inline void port_unlock(struct port *p_ptr) +static inline void tipc_port_unlock(struct port *p_ptr) { spin_unlock_bh(p_ptr->publ.lock); } -static inline struct port* port_deref(u32 ref) +static inline struct port* tipc_port_deref(u32 ref) { - return (struct port *)ref_deref(ref); + return (struct port *)tipc_ref_deref(ref); } -static inline u32 peer_port(struct port *p_ptr) +static inline u32 tipc_peer_port(struct port *p_ptr) { return msg_destport(&p_ptr->publ.phdr); } -static inline u32 peer_node(struct port *p_ptr) +static inline u32 tipc_peer_node(struct port *p_ptr) { return msg_destnode(&p_ptr->publ.phdr); } -static inline int port_congested(struct port *p_ptr) +static inline int tipc_port_congested(struct port *p_ptr) { return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2)); } /** - * port_recv_msg - receive message from lower layer and deliver to port user + * tipc_port_recv_msg - receive message from lower layer and deliver to port user */ -static inline int port_recv_msg(struct sk_buff *buf) +static inline int tipc_port_recv_msg(struct sk_buff *buf) { struct port *p_ptr; struct tipc_msg *msg = buf_msg(buf); @@ -178,24 +178,24 @@ static inline int port_recv_msg(struct sk_buff *buf) /* forward unresolved named message */ if (unlikely(!destport)) { - net_route_msg(buf); + tipc_net_route_msg(buf); return dsz; } /* validate destination & pass to port, otherwise reject message */ - p_ptr = port_lock(destport); + p_ptr = tipc_port_lock(destport); if (likely(p_ptr)) { if (likely(p_ptr->publ.connected)) { - if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) || - (unlikely(msg_orignode(msg) != peer_node(p_ptr))) || + if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) || + (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) || (unlikely(!msg_connected(msg)))) { err = TIPC_ERR_NO_PORT; - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); goto reject; } } err = p_ptr->dispatcher(&p_ptr->publ, buf); - port_unlock(p_ptr); + tipc_port_unlock(p_ptr); if (likely(!err)) return dsz; } else { diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 944093fe246f..5a13c2defe4a 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -61,15 +61,15 @@ * because entry 0's reference field has the form XXXX|1--1. */ -struct ref_table ref_table = { 0 }; +struct ref_table tipc_ref_table = { 0 }; -rwlock_t reftbl_lock = RW_LOCK_UNLOCKED; +static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED; /** - * ref_table_init - create reference table for objects + * tipc_ref_table_init - create reference table for objects */ -int ref_table_init(u32 requested_size, u32 start) +int tipc_ref_table_init(u32 requested_size, u32 start) { struct reference *table; u32 sz = 1 << 4; @@ -83,43 +83,43 @@ int ref_table_init(u32 requested_size, u32 start) if (table == NULL) return -ENOMEM; - write_lock_bh(&reftbl_lock); + write_lock_bh(&ref_table_lock); index_mask = sz - 1; for (i = sz - 1; i >= 0; i--) { table[i].object = 0; table[i].lock = SPIN_LOCK_UNLOCKED; table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; } - ref_table.entries = table; - ref_table.index_mask = index_mask; - ref_table.first_free = sz - 1; - ref_table.last_free = 1; - write_unlock_bh(&reftbl_lock); + tipc_ref_table.entries = table; + tipc_ref_table.index_mask = index_mask; + tipc_ref_table.first_free = sz - 1; + tipc_ref_table.last_free = 1; + write_unlock_bh(&ref_table_lock); return TIPC_OK; } /** - * ref_table_stop - destroy reference table for objects + * tipc_ref_table_stop - destroy reference table for objects */ -void ref_table_stop(void) +void tipc_ref_table_stop(void) { - if (!ref_table.entries) + if (!tipc_ref_table.entries) return; - vfree(ref_table.entries); - ref_table.entries = 0; + vfree(tipc_ref_table.entries); + tipc_ref_table.entries = 0; } /** - * ref_acquire - create reference to an object + * tipc_ref_acquire - create reference to an object * * Return a unique reference value which can be translated back to the pointer * 'object' at a later time. Also, pass back a pointer to the lock protecting * the object, but without locking it. */ -u32 ref_acquire(void *object, spinlock_t **lock) +u32 tipc_ref_acquire(void *object, spinlock_t **lock) { struct reference *entry; u32 index; @@ -127,17 +127,17 @@ u32 ref_acquire(void *object, spinlock_t **lock) u32 next_plus_upper; u32 reference = 0; - assert(ref_table.entries && object); + assert(tipc_ref_table.entries && object); - write_lock_bh(&reftbl_lock); - if (ref_table.first_free) { - index = ref_table.first_free; - entry = &(ref_table.entries[index]); - index_mask = ref_table.index_mask; + write_lock_bh(&ref_table_lock); + if (tipc_ref_table.first_free) { + index = tipc_ref_table.first_free; + entry = &(tipc_ref_table.entries[index]); + index_mask = tipc_ref_table.index_mask; /* take lock in case a previous user of entry still holds it */ spin_lock_bh(&entry->lock); next_plus_upper = entry->data.next_plus_upper; - ref_table.first_free = next_plus_upper & index_mask; + tipc_ref_table.first_free = next_plus_upper & index_mask; reference = (next_plus_upper & ~index_mask) + index; entry->data.reference = reference; entry->object = object; @@ -145,45 +145,45 @@ u32 ref_acquire(void *object, spinlock_t **lock) *lock = &entry->lock; spin_unlock_bh(&entry->lock); } - write_unlock_bh(&reftbl_lock); + write_unlock_bh(&ref_table_lock); return reference; } /** - * ref_discard - invalidate references to an object + * tipc_ref_discard - invalidate references to an object * * Disallow future references to an object and free up the entry for re-use. * Note: The entry's spin_lock may still be busy after discard */ -void ref_discard(u32 ref) +void tipc_ref_discard(u32 ref) { struct reference *entry; u32 index; u32 index_mask; - assert(ref_table.entries); + assert(tipc_ref_table.entries); assert(ref != 0); - write_lock_bh(&reftbl_lock); - index_mask = ref_table.index_mask; + write_lock_bh(&ref_table_lock); + index_mask = tipc_ref_table.index_mask; index = ref & index_mask; - entry = &(ref_table.entries[index]); + entry = &(tipc_ref_table.entries[index]); assert(entry->object != 0); assert(entry->data.reference == ref); /* mark entry as unused */ entry->object = 0; - if (ref_table.first_free == 0) - ref_table.first_free = index; + if (tipc_ref_table.first_free == 0) + tipc_ref_table.first_free = index; else /* next_plus_upper is always XXXX|0--0 for last free entry */ - ref_table.entries[ref_table.last_free].data.next_plus_upper + tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper |= index; - ref_table.last_free = index; + tipc_ref_table.last_free = index; /* increment upper bits of entry to invalidate subsequent references */ entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); - write_unlock_bh(&reftbl_lock); + write_unlock_bh(&ref_table_lock); } diff --git a/net/tipc/ref.h b/net/tipc/ref.h index 429cde57228a..4f8f9f40dcac 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h @@ -54,7 +54,7 @@ struct reference { }; /** - * struct ref_table - table of TIPC object reference entries + * struct tipc_ref_table - table of TIPC object reference entries * @entries: pointer to array of reference entries * @index_mask: bitmask for array index portion of reference values * @first_free: array index of first unused object reference entry @@ -68,24 +68,24 @@ struct ref_table { u32 last_free; }; -extern struct ref_table ref_table; +extern struct ref_table tipc_ref_table; -int ref_table_init(u32 requested_size, u32 start); -void ref_table_stop(void); +int tipc_ref_table_init(u32 requested_size, u32 start); +void tipc_ref_table_stop(void); -u32 ref_acquire(void *object, spinlock_t **lock); -void ref_discard(u32 ref); +u32 tipc_ref_acquire(void *object, spinlock_t **lock); +void tipc_ref_discard(u32 ref); /** - * ref_lock - lock referenced object and return pointer to it + * tipc_ref_lock - lock referenced object and return pointer to it */ -static inline void *ref_lock(u32 ref) +static inline void *tipc_ref_lock(u32 ref) { - if (likely(ref_table.entries)) { + if (likely(tipc_ref_table.entries)) { struct reference *r = - &ref_table.entries[ref & ref_table.index_mask]; + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; spin_lock_bh(&r->lock); if (likely(r->data.reference == ref)) @@ -96,31 +96,31 @@ static inline void *ref_lock(u32 ref) } /** - * ref_unlock - unlock referenced object + * tipc_ref_unlock - unlock referenced object */ -static inline void ref_unlock(u32 ref) +static inline void tipc_ref_unlock(u32 ref) { - if (likely(ref_table.entries)) { + if (likely(tipc_ref_table.entries)) { struct reference *r = - &ref_table.entries[ref & ref_table.index_mask]; + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; if (likely(r->data.reference == ref)) spin_unlock_bh(&r->lock); else - err("ref_unlock() invoked using obsolete reference\n"); + err("tipc_ref_unlock() invoked using obsolete reference\n"); } } /** - * ref_deref - return pointer referenced object (without locking it) + * tipc_ref_deref - return pointer referenced object (without locking it) */ -static inline void *ref_deref(u32 ref) +static inline void *tipc_ref_deref(u32 ref) { - if (likely(ref_table.entries)) { + if (likely(tipc_ref_table.entries)) { struct reference *r = - &ref_table.entries[ref & ref_table.index_mask]; + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; if (likely(r->data.reference == ref)) return r->object; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index d21f8c0cd25a..67253bfcd702 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -42,9 +42,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/poll.h> -#include <linux/version.h> #include <linux/fcntl.h> -#include <linux/version.h> #include <asm/semaphore.h> #include <asm/string.h> #include <asm/atomic.h> @@ -1185,7 +1183,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) { sock->state = SS_DISCONNECTING; /* Note: Use signal since port lock is already taken! */ - k_signal((Handler)async_disconnect, tport->ref); + tipc_k_signal((Handler)async_disconnect, tport->ref); } /* Enqueue message (finally!) */ @@ -1685,11 +1683,11 @@ static struct proto tipc_proto = { }; /** - * socket_init - initialize TIPC socket interface + * tipc_socket_init - initialize TIPC socket interface * * Returns 0 on success, errno otherwise */ -int socket_init(void) +int tipc_socket_init(void) { int res; @@ -1712,9 +1710,9 @@ int socket_init(void) } /** - * sock_stop - stop TIPC socket interface + * tipc_socket_stop - stop TIPC socket interface */ -void socket_stop(void) +void tipc_socket_stop(void) { if (!sockets_enabled) return; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 80e219ba527d..5ff38b9f3194 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -118,14 +118,14 @@ static void subscr_send_event(struct subscription *sub, } /** - * subscr_overlap - test for subscription overlap with the given values + * tipc_subscr_overlap - test for subscription overlap with the given values * * Returns 1 if there is overlap, otherwise 0. */ -int subscr_overlap(struct subscription *sub, - u32 found_lower, - u32 found_upper) +int tipc_subscr_overlap(struct subscription *sub, + u32 found_lower, + u32 found_upper) { if (found_lower < sub->seq.lower) @@ -138,22 +138,22 @@ int subscr_overlap(struct subscription *sub, } /** - * subscr_report_overlap - issue event if there is subscription overlap + * tipc_subscr_report_overlap - issue event if there is subscription overlap * * Protected by nameseq.lock in name_table.c */ -void subscr_report_overlap(struct subscription *sub, - u32 found_lower, - u32 found_upper, - u32 event, - u32 port_ref, - u32 node, - int must) +void tipc_subscr_report_overlap(struct subscription *sub, + u32 found_lower, + u32 found_upper, + u32 event, + u32 port_ref, + u32 node, + int must) { dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower, sub->seq.upper, found_lower, found_upper); - if (!subscr_overlap(sub, found_lower, found_upper)) + if (!tipc_subscr_overlap(sub, found_lower, found_upper)) return; if (!must && (sub->filter != TIPC_SUB_PORTS)) return; @@ -172,13 +172,13 @@ static void subscr_timeout(struct subscription *sub) /* Validate subscriber reference (in case subscriber is terminating) */ subscriber_ref = sub->owner->ref; - subscriber = (struct subscriber *)ref_lock(subscriber_ref); + subscriber = (struct subscriber *)tipc_ref_lock(subscriber_ref); if (subscriber == NULL) return; /* Unlink subscription from name table */ - nametbl_unsubscribe(sub); + tipc_nametbl_unsubscribe(sub); /* Notify subscriber of timeout, then unlink subscription */ @@ -192,7 +192,7 @@ static void subscr_timeout(struct subscription *sub) /* Now destroy subscription */ - ref_unlock(subscriber_ref); + tipc_ref_unlock(subscriber_ref); k_term_timer(&sub->timer); kfree(sub); atomic_dec(&topsrv.subscription_count); @@ -216,7 +216,7 @@ static void subscr_terminate(struct subscriber *subscriber) /* Invalidate subscriber reference */ - ref_discard(subscriber->ref); + tipc_ref_discard(subscriber->ref); spin_unlock_bh(subscriber->lock); /* Destroy any existing subscriptions for subscriber */ @@ -227,7 +227,7 @@ static void subscr_terminate(struct subscriber *subscriber) k_cancel_timer(&sub->timer); k_term_timer(&sub->timer); } - nametbl_unsubscribe(sub); + tipc_nametbl_unsubscribe(sub); list_del(&sub->subscription_list); dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); @@ -315,7 +315,7 @@ static void subscr_subscribe(struct tipc_subscr *s, k_start_timer(&sub->timer, sub->timeout); } sub->owner = subscriber; - nametbl_subscribe(sub); + tipc_nametbl_subscribe(sub); } /** @@ -332,7 +332,7 @@ static void subscr_conn_shutdown_event(void *usr_handle, struct subscriber *subscriber; spinlock_t *subscriber_lock; - subscriber = ref_lock((u32)(unsigned long)usr_handle); + subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); if (subscriber == NULL) return; @@ -354,7 +354,7 @@ static void subscr_conn_msg_event(void *usr_handle, struct subscriber *subscriber; spinlock_t *subscriber_lock; - subscriber = ref_lock((u32)(unsigned long)usr_handle); + subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); if (subscriber == NULL) return; @@ -401,7 +401,7 @@ static void subscr_named_msg_event(void *usr_handle, memset(subscriber, 0, sizeof(struct subscriber)); INIT_LIST_HEAD(&subscriber->subscription_list); INIT_LIST_HEAD(&subscriber->subscriber_list); - subscriber->ref = ref_acquire(subscriber, &subscriber->lock); + subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock); if (subscriber->ref == 0) { warn("Failed to acquire subscriber reference\n"); kfree(subscriber); @@ -423,7 +423,7 @@ static void subscr_named_msg_event(void *usr_handle, &subscriber->port_ref); if (subscriber->port_ref == 0) { warn("Memory squeeze; failed to create subscription port\n"); - ref_discard(subscriber->ref); + tipc_ref_discard(subscriber->ref); kfree(subscriber); return; } @@ -432,7 +432,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Add subscriber to topology server's subscriber list */ - ref_lock(subscriber->ref); + tipc_ref_lock(subscriber->ref); spin_lock_bh(&topsrv.lock); list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); spin_unlock_bh(&topsrv.lock); @@ -451,7 +451,7 @@ static void subscr_named_msg_event(void *usr_handle, spin_unlock_bh(subscriber_lock); } -int subscr_start(void) +int tipc_subscr_start(void) { struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; int res = -1; @@ -481,7 +481,7 @@ int subscr_start(void) if (res) goto failed; - res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); + res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); if (res) goto failed; @@ -496,7 +496,7 @@ failed: return res; } -void subscr_stop(void) +void tipc_subscr_stop(void) { struct subscriber *subscriber; struct subscriber *subscriber_temp; @@ -507,7 +507,7 @@ void subscr_stop(void) list_for_each_entry_safe(subscriber, subscriber_temp, &topsrv.subscriber_list, subscriber_list) { - ref_lock(subscriber->ref); + tipc_ref_lock(subscriber->ref); subscriber_lock = subscriber->lock; subscr_terminate(subscriber); spin_unlock_bh(subscriber_lock); @@ -522,6 +522,6 @@ int tipc_ispublished(struct tipc_name const *name) { u32 domain = 0; - return(nametbl_translate(name->type, name->instance,&domain) != 0); + return(tipc_nametbl_translate(name->type, name->instance,&domain) != 0); } diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index ccff4efcb755..1e5090465d2e 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -60,21 +60,21 @@ struct subscription { struct subscriber *owner; }; -int subscr_overlap(struct subscription * sub, - u32 found_lower, - u32 found_upper); +int tipc_subscr_overlap(struct subscription * sub, + u32 found_lower, + u32 found_upper); -void subscr_report_overlap(struct subscription * sub, - u32 found_lower, - u32 found_upper, - u32 event, - u32 port_ref, - u32 node, - int must_report); +void tipc_subscr_report_overlap(struct subscription * sub, + u32 found_lower, + u32 found_upper, + u32 event, + u32 port_ref, + u32 node, + int must_report); -int subscr_start(void); +int tipc_subscr_start(void); -void subscr_stop(void); +void tipc_subscr_stop(void); #endif diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c index 35ec7dc8211d..106200d76587 100644 --- a/net/tipc/user_reg.c +++ b/net/tipc/user_reg.c @@ -114,10 +114,10 @@ static void reg_callback(struct tipc_user *user_ptr) } /** - * reg_start - activate TIPC user registry + * tipc_reg_start - activate TIPC user registry */ -int reg_start(void) +int tipc_reg_start(void) { u32 u; int res; @@ -127,17 +127,17 @@ int reg_start(void) for (u = 1; u <= MAX_USERID; u++) { if (users[u].callback) - k_signal((Handler)reg_callback, - (unsigned long)&users[u]); + tipc_k_signal((Handler)reg_callback, + (unsigned long)&users[u]); } return TIPC_OK; } /** - * reg_stop - shut down & delete TIPC user registry + * tipc_reg_stop - shut down & delete TIPC user registry */ -void reg_stop(void) +void tipc_reg_stop(void) { int id; @@ -184,7 +184,7 @@ int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle) atomic_inc(&tipc_user_count); if (cb && (tipc_mode != TIPC_NOT_RUNNING)) - k_signal((Handler)reg_callback, (unsigned long)user_ptr); + tipc_k_signal((Handler)reg_callback, (unsigned long)user_ptr); return TIPC_OK; } @@ -223,10 +223,10 @@ void tipc_detach(u32 userid) } /** - * reg_add_port - register a user's driver port + * tipc_reg_add_port - register a user's driver port */ -int reg_add_port(struct user_port *up_ptr) +int tipc_reg_add_port(struct user_port *up_ptr) { struct tipc_user *user_ptr; @@ -245,10 +245,10 @@ int reg_add_port(struct user_port *up_ptr) } /** - * reg_remove_port - deregister a user's driver port + * tipc_reg_remove_port - deregister a user's driver port */ -int reg_remove_port(struct user_port *up_ptr) +int tipc_reg_remove_port(struct user_port *up_ptr) { if (up_ptr->user_ref == 0) return TIPC_OK; diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h index 122ca9be3671..d0e88794ed1b 100644 --- a/net/tipc/user_reg.h +++ b/net/tipc/user_reg.h @@ -39,10 +39,10 @@ #include "port.h" -int reg_start(void); -void reg_stop(void); +int tipc_reg_start(void); +void tipc_reg_stop(void); -int reg_add_port(struct user_port *up_ptr); -int reg_remove_port(struct user_port *up_ptr); +int tipc_reg_add_port(struct user_port *up_ptr); +int tipc_reg_remove_port(struct user_port *up_ptr); #endif diff --git a/net/tipc/zone.c b/net/tipc/zone.c index 4eaef662d568..7c11f7f83a21 100644 --- a/net/tipc/zone.c +++ b/net/tipc/zone.c @@ -42,12 +42,12 @@ #include "cluster.h" #include "node.h" -struct _zone *zone_create(u32 addr) +struct _zone *tipc_zone_create(u32 addr) { struct _zone *z_ptr = 0; u32 z_num; - if (!addr_domain_valid(addr)) + if (!tipc_addr_domain_valid(addr)) return 0; z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); @@ -55,24 +55,24 @@ struct _zone *zone_create(u32 addr) memset(z_ptr, 0, sizeof(*z_ptr)); z_num = tipc_zone(addr); z_ptr->addr = tipc_addr(z_num, 0, 0); - net.zones[z_num] = z_ptr; + tipc_net.zones[z_num] = z_ptr; } return z_ptr; } -void zone_delete(struct _zone *z_ptr) +void tipc_zone_delete(struct _zone *z_ptr) { u32 c_num; if (!z_ptr) return; for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { - cluster_delete(z_ptr->clusters[c_num]); + tipc_cltr_delete(z_ptr->clusters[c_num]); } kfree(z_ptr); } -void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) +void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) { u32 c_num = tipc_cluster(c_ptr->addr); @@ -82,19 +82,19 @@ void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) z_ptr->clusters[c_num] = c_ptr; } -void zone_remove_as_router(struct _zone *z_ptr, u32 router) +void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router) { u32 c_num; for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { if (z_ptr->clusters[c_num]) { - cluster_remove_as_router(z_ptr->clusters[c_num], - router); + tipc_cltr_remove_as_router(z_ptr->clusters[c_num], + router); } } } -void zone_send_external_routes(struct _zone *z_ptr, u32 dest) +void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest) { u32 c_num; @@ -102,12 +102,12 @@ void zone_send_external_routes(struct _zone *z_ptr, u32 dest) if (z_ptr->clusters[c_num]) { if (in_own_cluster(z_ptr->addr)) continue; - cluster_send_ext_routes(z_ptr->clusters[c_num], dest); + tipc_cltr_send_ext_routes(z_ptr->clusters[c_num], dest); } } } -struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) +struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) { struct cluster *c_ptr; struct node *n_ptr; @@ -118,7 +118,7 @@ struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) c_ptr = z_ptr->clusters[tipc_cluster(addr)]; if (!c_ptr) return 0; - n_ptr = cluster_select_node(c_ptr, ref); + n_ptr = tipc_cltr_select_node(c_ptr, ref); if (n_ptr) return n_ptr; @@ -127,14 +127,14 @@ struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) c_ptr = z_ptr->clusters[c_num]; if (!c_ptr) return 0; - n_ptr = cluster_select_node(c_ptr, ref); + n_ptr = tipc_cltr_select_node(c_ptr, ref); if (n_ptr) return n_ptr; } return 0; } -u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) +u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) { struct cluster *c_ptr; u32 c_num; @@ -143,14 +143,14 @@ u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) if (!z_ptr) return 0; c_ptr = z_ptr->clusters[tipc_cluster(addr)]; - router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; + router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0; if (router) return router; /* Links to any other clusters within the zone? */ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { c_ptr = z_ptr->clusters[c_num]; - router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; + router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0; if (router) return router; } @@ -158,12 +158,12 @@ u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) } -u32 zone_next_node(u32 addr) +u32 tipc_zone_next_node(u32 addr) { - struct cluster *c_ptr = cluster_find(addr); + struct cluster *c_ptr = tipc_cltr_find(addr); if (c_ptr) - return cluster_next_node(c_ptr, addr); + return tipc_cltr_next_node(c_ptr, addr); return 0; } diff --git a/net/tipc/zone.h b/net/tipc/zone.h index 4326f78d8292..267999c5a240 100644 --- a/net/tipc/zone.h +++ b/net/tipc/zone.h @@ -54,18 +54,18 @@ struct _zone { u32 links; }; -struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); -u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); -void zone_remove_as_router(struct _zone *z_ptr, u32 router); -void zone_send_external_routes(struct _zone *z_ptr, u32 dest); -struct _zone *zone_create(u32 addr); -void zone_delete(struct _zone *z_ptr); -void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); -u32 zone_next_node(u32 addr); +struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); +u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); +void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router); +void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest); +struct _zone *tipc_zone_create(u32 addr); +void tipc_zone_delete(struct _zone *z_ptr); +void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); +u32 tipc_zone_next_node(u32 addr); -static inline struct _zone *zone_find(u32 addr) +static inline struct _zone *tipc_zone_find(u32 addr) { - return net.zones[tipc_zone(addr)]; + return tipc_net.zones[tipc_zone(addr)]; } #endif diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 077bbf9fb9b7..98ec53bd3ac7 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -13,7 +13,6 @@ * */ -#include <asm/bug.h> #include <linux/config.h> #include <linux/slab.h> #include <linux/kmod.h> @@ -890,7 +889,9 @@ restart: xfrm_pol_put(policy); if (dst) dst_free(dst); - goto restart; + + err = -EHOSTUNREACH; + goto error; } dst->next = policy->bundles; policy->bundles = dst; diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile index fae3e29fc924..bbf4887cff74 100644 --- a/scripts/kconfig/lxdialog/Makefile +++ b/scripts/kconfig/lxdialog/Makefile @@ -2,8 +2,11 @@ # check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh -HOST_EXTRACFLAGS:= $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) -HOST_LOADLIBES := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +# Use reursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) +HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) HOST_EXTRACFLAGS += -DLOCALE diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 448e353923f3..120d624e672c 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -4,17 +4,17 @@ # What library to link ldflags() { - echo "main() {}" | $cc -lncursesw -xc - -o /dev/null 2> /dev/null + $cc -print-file-name=libncursesw.so | grep -q / if [ $? -eq 0 ]; then echo '-lncursesw' exit fi - echo "main() {}" | $cc -lncurses -xc - -o /dev/null 2> /dev/null + $cc -print-file-name=libncurses.so | grep -q / if [ $? -eq 0 ]; then echo '-lncurses' exit fi - echo "main() {}" | $cc -lcurses -xc - -o /dev/null 2> /dev/null + $cc -print-file-name=libcurses.so | grep -q / if [ $? -eq 0 ]; then echo '-lcurses' exit @@ -36,10 +36,13 @@ ccflags() fi } -compiler="" +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + # Check if we can link to ncurses check() { - echo "main() {}" | $cc -xc - -o /dev/null 2> /dev/null + echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null if [ $? != 0 ]; then echo " *** Unable to find the ncurses libraries." 1>&2 echo " *** make menuconfig require the ncurses libraries" 1>&2 @@ -59,6 +62,7 @@ if [ $# == 0 ]; then exit 1 fi +cc="" case "$1" in "-check") shift diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9fd5f5b87d1e..99fe4b7fb2f1 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -45,7 +45,7 @@ use strict; # Note: This only supports 'c'. # usage: -# kerneldoc [ -docbook | -html | -text | -man ] +# kernel-doc [ -docbook | -html | -text | -man ] # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile # or # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile @@ -59,7 +59,7 @@ use strict; # -nofunction funcname # If set, then only generate documentation for the other function(s). All # other functions are ignored. Cannot be used with -function together -# (yes thats a bug - perl hackers can fix it 8)) +# (yes, that's a bug -- perl hackers can fix it 8)) # # c files - list of 'c' files to process # @@ -90,28 +90,28 @@ use strict; # * my_function - does my stuff # * @my_arg: its mine damnit # * -# * Does my stuff explained. +# * Does my stuff explained. # */ # # or, could also use: # /** # * my_function - does my stuff # * @my_arg: its mine damnit -# * Description: Does my stuff explained. +# * Description: Does my stuff explained. # */ # etc. # -# Beside functions you can also write documentation for structs, unions, -# enums and typedefs. Instead of the function name you must write the name -# of the declaration; the struct/union/enum/typedef must always precede -# the name. Nesting of declarations is not supported. +# Beside functions you can also write documentation for structs, unions, +# enums and typedefs. Instead of the function name you must write the name +# of the declaration; the struct/union/enum/typedef must always precede +# the name. Nesting of declarations is not supported. # Use the argument mechanism to document members or constants. # e.g. # /** # * struct my_struct - short description # * @a: first member # * @b: second member -# * +# * # * Longer description # */ # struct my_struct { @@ -122,12 +122,12 @@ use strict; # }; # # All descriptions can be multiline, except the short function description. -# -# You can also add additional sections. When documenting kernel functions you -# should document the "Context:" of the function, e.g. whether the functions +# +# You can also add additional sections. When documenting kernel functions you +# should document the "Context:" of the function, e.g. whether the functions # can be called form interrupts. Unlike other sections you can end it with an -# empty line. -# Example-sections should contain the string EXAMPLE so that they are marked +# empty line. +# Example-sections should contain the string EXAMPLE so that they are marked # appropriately in DocBook. # # Example: @@ -135,7 +135,7 @@ use strict; # * user_function - function that can only be called in user context # * @a: some argument # * Context: !in_interrupt() -# * +# * # * Some description # * Example: # * user_function(22); @@ -223,9 +223,9 @@ my %highlights = %highlights_man; my $blankline = $blankline_man; my $modulename = "Kernel API"; my $function_only = 0; -my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', - 'November', 'December')[(localtime)[4]] . +my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', + 'November', 'December')[(localtime)[4]] . " " . ((localtime)[5]+1900); # Essentially these are globals @@ -236,7 +236,7 @@ my ($function, %function_table,%parametertypes,$declaration_purpose); my ($type,$declaration_name,$return_type); my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map); -# Generated docbook code is inserted in a template at a point where +# Generated docbook code is inserted in a template at a point where # docbook v3.1 requires a non-zero sequence of RefEntry's; see: # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html # We keep track of number of generated entries and generate a dummy @@ -365,7 +365,7 @@ sub dump_section { # parameterdescs => %parameter descriptions # sectionlist => @list of sections # sections => %descriont descriptions -# +# sub output_highlight { my $contents = join "\n",@_; @@ -400,7 +400,7 @@ sub output_section_html(%) { print "<blockquote>\n"; output_highlight($args{'sections'}{$section}); print "</blockquote>\n"; - } + } } # output enum in html @@ -434,7 +434,7 @@ sub output_enum_html(%) { print "<hr>\n"; } -# output tyepdef in html +# output typedef in html sub output_typedef_html(%) { my %args = %{$_[0]}; my ($parameter); @@ -551,7 +551,7 @@ sub output_intro_html(%) { sub output_section_xml(%) { my %args = %{$_[0]}; - my $section; + my $section; # print out each section $lineprefix=" "; foreach $section (@{$args{'sectionlist'}}) { @@ -778,7 +778,7 @@ sub output_enum_xml(%) { print "</refsynopsisdiv>\n"; print "<refsect1>\n"; - print " <title>Constants</title>\n"; + print " <title>Constants</title>\n"; print " <variablelist>\n"; foreach $parameter (@{$args{'parameterlist'}}) { my $parameter_name = $parameter; @@ -1157,7 +1157,7 @@ sub output_section_text(%) { foreach $section (@{$args{'sectionlist'}}) { print "$section:\n\n"; output_highlight($args{'sections'}{$section}); - } + } print "\n\n"; } @@ -1262,8 +1262,8 @@ sub output_declaration { my $name = shift; my $functype = shift; my $func = "output_${functype}_$output_mode"; - if (($function_only==0) || - ( $function_only == 1 && defined($function_table{$name})) || + if (($function_only==0) || + ( $function_only == 1 && defined($function_table{$name})) || ( $function_only == 2 && !defined($function_table{$name}))) { &$func(@_); @@ -1282,7 +1282,7 @@ sub output_intro { } ## -# takes a declaration (struct, union, enum, typedef) and +# takes a declaration (struct, union, enum, typedef) and # invokes the right handler. NOT called for functions. sub dump_declaration($$) { no strict 'refs'; @@ -1352,7 +1352,7 @@ sub dump_enum($$) { } } - + output_declaration($declaration_name, 'enum', {'enum' => $declaration_name, @@ -1409,7 +1409,7 @@ sub create_parameterlist($$$) { while ($args =~ /(\([^\),]+),/) { $args =~ s/(\([^\),]+),/$1#/g; } - + foreach my $arg (split($splitter, $args)) { # strip comments $arg =~ s/\/\*.*\*\///; @@ -1529,7 +1529,7 @@ sub dump_function($$) { # the following functions' documentation still comes out right: # - parport_register_device (function pointer parameters) # - atomic_set (macro) - # - pci_match_device (long return type) + # - pci_match_device, __copy_to_user (long return type) if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || @@ -1544,7 +1544,9 @@ sub dump_function($$) { $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || - $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { + $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || + $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || + $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { $return_type = $1; $declaration_name = $2; my $args = $3; @@ -1556,7 +1558,7 @@ sub dump_function($$) { return; } - output_declaration($declaration_name, + output_declaration($declaration_name, 'function', {'function' => $declaration_name, 'module' => $modulename, @@ -1615,11 +1617,11 @@ sub reset_state { %sections = (); @sectionlist = (); $prototype = ""; - + $state = 0; } -sub process_state3_function($$) { +sub process_state3_function($$) { my $x = shift; my $file = shift; @@ -1638,7 +1640,7 @@ sub process_state3_function($$) { } } -sub process_state3_type($$) { +sub process_state3_type($$) { my $x = shift; my $file = shift; @@ -1778,7 +1780,7 @@ sub process_file($) { } elsif (/$doc_content/) { # miguel-style comment kludge, look for blank lines after # @parameter line to signify start of description - if ($1 eq "" && + if ($1 eq "" && ($section =~ m/^@/ || $section eq $section_context)) { dump_section($section, xml_escape($contents)); $section = $section_default; @@ -1788,7 +1790,7 @@ sub process_file($) { } } else { # i dont know - bad line? ignore. - print STDERR "Warning(${file}:$.): bad line: $_"; + print STDERR "Warning(${file}:$.): bad line: $_"; ++$warnings; } } elsif ($state == 3) { # scanning for function { (end of prototype) @@ -1843,7 +1845,7 @@ sub process_file($) { else { $contents .= $1 . "\n"; - } + } } } } diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 90db5c76cf6e..0c62798ac7d8 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -67,9 +67,10 @@ asmlinkage long sys_add_key(const char __user *_type, description = kmalloc(dlen + 1, GFP_KERNEL); if (!description) goto error; + description[dlen] = '\0'; ret = -EFAULT; - if (copy_from_user(description, _description, dlen + 1) != 0) + if (copy_from_user(description, _description, dlen) != 0) goto error2; /* pull the payload in if one was supplied */ @@ -161,9 +162,10 @@ asmlinkage long sys_request_key(const char __user *_type, description = kmalloc(dlen + 1, GFP_KERNEL); if (!description) goto error; + description[dlen] = '\0'; ret = -EFAULT; - if (copy_from_user(description, _description, dlen + 1) != 0) + if (copy_from_user(description, _description, dlen) != 0) goto error2; /* pull the callout info into kernel space */ @@ -182,9 +184,10 @@ asmlinkage long sys_request_key(const char __user *_type, callout_info = kmalloc(dlen + 1, GFP_KERNEL); if (!callout_info) goto error2; + callout_info[dlen] = '\0'; ret = -EFAULT; - if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0) + if (copy_from_user(callout_info, _callout_info, dlen) != 0) goto error3; } @@ -279,9 +282,10 @@ long keyctl_join_session_keyring(const char __user *_name) name = kmalloc(nlen + 1, GFP_KERNEL); if (!name) goto error; + name[nlen] = '\0'; ret = -EFAULT; - if (copy_from_user(name, _name, nlen + 1) != 0) + if (copy_from_user(name, _name, nlen) != 0) goto error2; } @@ -583,9 +587,10 @@ long keyctl_keyring_search(key_serial_t ringid, description = kmalloc(dlen + 1, GFP_KERNEL); if (!description) goto error; + description[dlen] = '\0'; ret = -EFAULT; - if (copy_from_user(description, _description, dlen + 1) != 0) + if (copy_from_user(description, _description, dlen) != 0) goto error2; /* get the keyring at which to begin the search */ diff --git a/security/seclvl.c b/security/seclvl.c index 1caac0164643..8529ea6f7aa8 100644 --- a/security/seclvl.c +++ b/security/seclvl.c @@ -368,8 +368,8 @@ static int seclvl_capable(struct task_struct *tsk, int cap) */ static int seclvl_settime(struct timespec *tv, struct timezone *tz) { - struct timespec now; - if (seclvl > 1) { + if (tv && seclvl > 1) { + struct timespec now; now = current_kernel_time(); if (tv->tv_sec < now.tv_sec || (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) { diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index b59582b92283..f636f53ca544 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -1,6 +1,6 @@ config SECURITY_SELINUX bool "NSA SELinux Support" - depends on SECURITY && NET && INET + depends on SECURITY_NETWORK && AUDIT && NET && INET default n help This selects NSA Security-Enhanced Linux (SELinux). diff --git a/security/selinux/Makefile b/security/selinux/Makefile index 06d54d9d20a5..688c0a267b62 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -4,9 +4,7 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ -selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o - -selinux-$(CONFIG_SECURITY_NETWORK) += netif.o +selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 53d6c7bbf564..ac5d69bb3377 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -43,13 +43,11 @@ static const struct av_perm_to_string #undef S_ }; -#ifdef CONFIG_AUDIT static const char *class_to_string[] = { #define S_(s) s, #include "class_to_string.h" #undef S_ }; -#endif #define TB_(s) static const char * s [] = { #define TE_(s) }; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b9f8d9731c3d..b7773bf68efa 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -127,7 +127,6 @@ static int task_alloc_security(struct task_struct *task) if (!tsec) return -ENOMEM; - tsec->magic = SELINUX_MAGIC; tsec->task = task; tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; task->security = tsec; @@ -138,10 +137,6 @@ static int task_alloc_security(struct task_struct *task) static void task_free_security(struct task_struct *task) { struct task_security_struct *tsec = task->security; - - if (!tsec || tsec->magic != SELINUX_MAGIC) - return; - task->security = NULL; kfree(tsec); } @@ -157,14 +152,10 @@ static int inode_alloc_security(struct inode *inode) init_MUTEX(&isec->sem); INIT_LIST_HEAD(&isec->list); - isec->magic = SELINUX_MAGIC; isec->inode = inode; isec->sid = SECINITSID_UNLABELED; isec->sclass = SECCLASS_FILE; - if (tsec && tsec->magic == SELINUX_MAGIC) - isec->task_sid = tsec->sid; - else - isec->task_sid = SECINITSID_UNLABELED; + isec->task_sid = tsec->sid; inode->i_security = isec; return 0; @@ -175,9 +166,6 @@ static void inode_free_security(struct inode *inode) struct inode_security_struct *isec = inode->i_security; struct superblock_security_struct *sbsec = inode->i_sb->s_security; - if (!isec || isec->magic != SELINUX_MAGIC) - return; - spin_lock(&sbsec->isec_lock); if (!list_empty(&isec->list)) list_del_init(&isec->list); @@ -192,19 +180,13 @@ static int file_alloc_security(struct file *file) struct task_security_struct *tsec = current->security; struct file_security_struct *fsec; - fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC); + fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL); if (!fsec) return -ENOMEM; - fsec->magic = SELINUX_MAGIC; fsec->file = file; - if (tsec && tsec->magic == SELINUX_MAGIC) { - fsec->sid = tsec->sid; - fsec->fown_sid = tsec->sid; - } else { - fsec->sid = SECINITSID_UNLABELED; - fsec->fown_sid = SECINITSID_UNLABELED; - } + fsec->sid = tsec->sid; + fsec->fown_sid = tsec->sid; file->f_security = fsec; return 0; @@ -213,10 +195,6 @@ static int file_alloc_security(struct file *file) static void file_free_security(struct file *file) { struct file_security_struct *fsec = file->f_security; - - if (!fsec || fsec->magic != SELINUX_MAGIC) - return; - file->f_security = NULL; kfree(fsec); } @@ -233,7 +211,6 @@ static int superblock_alloc_security(struct super_block *sb) INIT_LIST_HEAD(&sbsec->list); INIT_LIST_HEAD(&sbsec->isec_head); spin_lock_init(&sbsec->isec_lock); - sbsec->magic = SELINUX_MAGIC; sbsec->sb = sb; sbsec->sid = SECINITSID_UNLABELED; sbsec->def_sid = SECINITSID_FILE; @@ -246,9 +223,6 @@ static void superblock_free_security(struct super_block *sb) { struct superblock_security_struct *sbsec = sb->s_security; - if (!sbsec || sbsec->magic != SELINUX_MAGIC) - return; - spin_lock(&sb_security_lock); if (!list_empty(&sbsec->list)) list_del_init(&sbsec->list); @@ -258,7 +232,6 @@ static void superblock_free_security(struct super_block *sb) kfree(sbsec); } -#ifdef CONFIG_SECURITY_NETWORK static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) { struct sk_security_struct *ssec; @@ -270,7 +243,6 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) if (!ssec) return -ENOMEM; - ssec->magic = SELINUX_MAGIC; ssec->sk = sk; ssec->peer_sid = SECINITSID_UNLABELED; sk->sk_security = ssec; @@ -282,13 +254,12 @@ static void sk_free_security(struct sock *sk) { struct sk_security_struct *ssec = sk->sk_security; - if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC) + if (sk->sk_family != PF_UNIX) return; sk->sk_security = NULL; kfree(ssec); } -#endif /* CONFIG_SECURITY_NETWORK */ /* The security server must be initialized before any labeling or access decisions can be provided. */ @@ -1483,7 +1454,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) if (!bsec) return -ENOMEM; - bsec->magic = SELINUX_MAGIC; bsec->bprm = bprm; bsec->sid = SECINITSID_UNLABELED; bsec->set = 0; @@ -2454,35 +2424,27 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, prot = reqprot; #ifndef CONFIG_PPC32 - if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) && - (vma->vm_start >= vma->vm_mm->start_brk && - vma->vm_end <= vma->vm_mm->brk)) { - /* - * We are making an executable mapping in the brk region. - * This has an additional execheap check. - */ - rc = task_has_perm(current, current, PROCESS__EXECHEAP); - if (rc) - return rc; - } - if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) { - /* - * We are making executable a file mapping that has - * had some COW done. Since pages might have been written, - * check ability to execute the possibly modified content. - * This typically should only occur for text relocations. - */ - int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD); - if (rc) - return rc; - } - if (!vma->vm_file && (prot & PROT_EXEC) && - vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack) { - /* Attempt to make the process stack executable. - * This has an additional execstack check. - */ - rc = task_has_perm(current, current, PROCESS__EXECSTACK); + if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { + rc = 0; + if (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk) { + rc = task_has_perm(current, current, + PROCESS__EXECHEAP); + } else if (!vma->vm_file && + vma->vm_start <= vma->vm_mm->start_stack && + vma->vm_end >= vma->vm_mm->start_stack) { + rc = task_has_perm(current, current, PROCESS__EXECSTACK); + } else if (vma->vm_file && vma->anon_vma) { + /* + * We are making executable a file mapping that has + * had some COW done. Since pages might have been + * written, check ability to execute the possibly + * modified content. This typically should only + * occur for text relocations. + */ + rc = file_has_perm(current, vma->vm_file, + FILE__EXECMOD); + } if (rc) return rc; } @@ -2772,8 +2734,6 @@ static void selinux_task_to_inode(struct task_struct *p, return; } -#ifdef CONFIG_SECURITY_NETWORK - /* Returns error only if unable to parse addresses */ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) { @@ -3592,15 +3552,6 @@ static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, #endif /* CONFIG_NETFILTER */ -#else - -static inline int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) -{ - return 0; -} - -#endif /* CONFIG_SECURITY_NETWORK */ - static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { struct task_security_struct *tsec; @@ -3642,14 +3593,9 @@ static int ipc_alloc_security(struct task_struct *task, if (!isec) return -ENOMEM; - isec->magic = SELINUX_MAGIC; isec->sclass = sclass; isec->ipc_perm = perm; - if (tsec) { - isec->sid = tsec->sid; - } else { - isec->sid = SECINITSID_UNLABELED; - } + isec->sid = tsec->sid; perm->security = isec; return 0; @@ -3658,9 +3604,6 @@ static int ipc_alloc_security(struct task_struct *task, static void ipc_free_security(struct kern_ipc_perm *perm) { struct ipc_security_struct *isec = perm->security; - if (!isec || isec->magic != SELINUX_MAGIC) - return; - perm->security = NULL; kfree(isec); } @@ -3673,7 +3616,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg) if (!msec) return -ENOMEM; - msec->magic = SELINUX_MAGIC; msec->msg = msg; msec->sid = SECINITSID_UNLABELED; msg->security = msec; @@ -3684,8 +3626,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg) static void msg_msg_free_security(struct msg_msg *msg) { struct msg_security_struct *msec = msg->security; - if (!msec || msec->magic != SELINUX_MAGIC) - return; msg->security = NULL; kfree(msec); @@ -4387,7 +4327,6 @@ static struct security_operations selinux_ops = { .getprocattr = selinux_getprocattr, .setprocattr = selinux_setprocattr, -#ifdef CONFIG_SECURITY_NETWORK .unix_stream_connect = selinux_socket_unix_stream_connect, .unix_may_send = selinux_socket_unix_may_send, @@ -4409,7 +4348,6 @@ static struct security_operations selinux_ops = { .sk_alloc_security = selinux_sk_alloc_security, .sk_free_security = selinux_sk_free_security, .sk_getsid = selinux_sk_getsid_security, -#endif #ifdef CONFIG_SECURITY_NETWORK_XFRM .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, @@ -4487,7 +4425,7 @@ next_sb: all processes and objects when they are created. */ security_initcall(selinux_init); -#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_NETFILTER) +#if defined(CONFIG_NETFILTER) static struct nf_hook_ops selinux_ipv4_op = { .hook = selinux_ipv4_postroute_last, @@ -4548,13 +4486,13 @@ static void selinux_nf_ip_exit(void) } #endif -#else /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */ +#else /* CONFIG_NETFILTER */ #ifdef CONFIG_SECURITY_SELINUX_DISABLE #define selinux_nf_ip_exit() #endif -#endif /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */ +#endif /* CONFIG_NETFILTER */ #ifdef CONFIG_SECURITY_SELINUX_DISABLE int selinux_disable(void) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 887937c8134a..54c030778882 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -27,7 +27,6 @@ #include "avc.h" struct task_security_struct { - unsigned long magic; /* magic number for this module */ struct task_struct *task; /* back pointer to task object */ u32 osid; /* SID prior to last execve */ u32 sid; /* current SID */ @@ -37,7 +36,6 @@ struct task_security_struct { }; struct inode_security_struct { - unsigned long magic; /* magic number for this module */ struct inode *inode; /* back pointer to inode object */ struct list_head list; /* list of inode_security_struct */ u32 task_sid; /* SID of creating task */ @@ -49,14 +47,12 @@ struct inode_security_struct { }; struct file_security_struct { - unsigned long magic; /* magic number for this module */ struct file *file; /* back pointer to file object */ u32 sid; /* SID of open file description */ u32 fown_sid; /* SID of file owner (for SIGIO) */ }; struct superblock_security_struct { - unsigned long magic; /* magic number for this module */ struct super_block *sb; /* back pointer to sb object */ struct list_head list; /* list of superblock_security_struct */ u32 sid; /* SID of file system */ @@ -70,20 +66,17 @@ struct superblock_security_struct { }; struct msg_security_struct { - unsigned long magic; /* magic number for this module */ struct msg_msg *msg; /* back pointer */ u32 sid; /* SID of message */ }; struct ipc_security_struct { - unsigned long magic; /* magic number for this module */ struct kern_ipc_perm *ipc_perm; /* back pointer */ u16 sclass; /* security class of this object */ u32 sid; /* SID of IPC resource */ }; struct bprm_security_struct { - unsigned long magic; /* magic number for this module */ struct linux_binprm *bprm; /* back pointer to bprm object */ u32 sid; /* SID for transformed process */ unsigned char set; @@ -102,7 +95,6 @@ struct netif_security_struct { }; struct sk_security_struct { - unsigned long magic; /* magic number for this module */ struct sock *sk; /* back pointer to sk object */ u32 peer_sid; /* SID of peer */ }; diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 54147c1f6361..149feb410654 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -882,14 +882,20 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id) writel(0x1fff, aaci->base + AACI_INTCLR); writel(aaci->maincr, aaci->base + AACI_MAINCR); + ret = aaci_probe_ac97(aaci); + if (ret) + goto out; + /* - * Size the FIFOs. + * Size the FIFOs (must be multiple of 16). */ aaci->fifosize = aaci_size_fifo(aaci); - - ret = aaci_probe_ac97(aaci); - if (ret) + if (aaci->fifosize & 15) { + printk(KERN_WARNING "AACI: fifosize = %d not supported\n", + aaci->fifosize); + ret = -ENODEV; goto out; + } ret = aaci_init_pcm(aaci); if (ret) diff --git a/sound/core/info.c b/sound/core/info.c index ae8853921464..af123e3bdb24 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -444,8 +444,8 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait) return mask; } -static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct snd_info_private_data *data; struct snd_info_entry *entry; @@ -465,17 +465,6 @@ static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file, return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_info_entry_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_info_entry_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file->f_dentry->d_inode; @@ -499,15 +488,15 @@ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) static struct file_operations snd_info_entry_operations = { - .owner = THIS_MODULE, - .llseek = snd_info_entry_llseek, - .read = snd_info_entry_read, - .write = snd_info_entry_write, - .poll = snd_info_entry_poll, - .ioctl = snd_info_entry_ioctl, - .mmap = snd_info_entry_mmap, - .open = snd_info_entry_open, - .release = snd_info_entry_release, + .owner = THIS_MODULE, + .llseek = snd_info_entry_llseek, + .read = snd_info_entry_read, + .write = snd_info_entry_write, + .poll = snd_info_entry_poll, + .unlocked_ioctl = snd_info_entry_ioctl, + .mmap = snd_info_entry_mmap, + .open = snd_info_entry_open, + .release = snd_info_entry_release, }; /** diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 29676d800cae..112ddf705402 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -789,7 +789,7 @@ static int __init snd_uart16550_create(struct snd_card *card, if ((err = snd_uart16550_detect(uart)) <= 0) { printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); - return err; + return -ENODEV; } if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index bd8e23818460..fd9bb2575de8 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -109,7 +109,9 @@ module_param_array(wssdma, int, NULL, 0444); MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); static struct platform_device *platform_devices[SNDRV_CARDS]; +#ifdef CONFIG_PNP static int pnp_registered; +#endif #define CMI8330_RMUX3D 16 #define CMI8330_MUTEMUX 17 @@ -672,8 +674,10 @@ static void __init_or_module snd_cmi8330_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&cmi8330_pnpc_driver); +#endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_cmi8330_driver); @@ -700,11 +704,13 @@ static int __init alsa_card_cmi8330_init(void) cards++; } +#ifdef CONFIG_PNP err = pnp_register_card_driver(&cmi8330_pnpc_driver); if (err >= 0) { pnp_registered = 1; cards += err; } +#endif if (!cards) { #ifdef MODULE diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index e1683337e6cd..4fa431040564 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -75,8 +75,10 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235}," #ifdef CS4232 #define IDENT "CS4232" +#define CS423X_DRIVER "snd_cs4232" #else #define IDENT "CS4236+" +#define CS423X_DRIVER "snd_cs4236" #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ @@ -125,10 +127,12 @@ module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); static struct platform_device *platform_devices[SNDRV_CARDS]; +#ifdef CONFIG_PNP static int pnpc_registered; #ifdef CS4232 static int pnp_registered; #endif +#endif /* CONFIG_PNP */ struct snd_card_cs4236 { struct snd_cs4231 *chip; @@ -158,7 +162,6 @@ MODULE_DEVICE_TABLE(pnp, snd_cs4232_pnpbiosids); #endif /* CS4232 */ #ifdef CS4232 -#define CS423X_DRIVER "snd_cs4232" #define CS423X_ISAPNP_DRIVER "cs4232_isapnp" static struct pnp_card_device_id snd_cs423x_pnpids[] = { /* Philips PCA70PS */ @@ -175,11 +178,12 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = { { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } }, /* SIC CrystalWave 32 (CS4232) */ { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, + /* Netfinity 3000 on-board soundcard */ + { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } }, /* --- */ { .id = "" } /* end */ }; #else /* CS4236 */ -#define CS423X_DRIVER "snd_cs4236" #define CS423X_ISAPNP_DRIVER "cs4236_isapnp" static struct pnp_card_device_id snd_cs423x_pnpids[] = { /* Intel Marlin Spike Motherboard - CS4235 */ @@ -747,12 +751,14 @@ static void __init_or_module snd_cs423x_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnpc_registered) pnp_unregister_card_driver(&cs423x_pnpc_driver); #ifdef CS4232 if (pnp_registered) pnp_unregister_driver(&cs4232_pnp_driver); #endif +#endif /* CONFIG_PNP */ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&cs423x_nonpnp_driver); @@ -778,6 +784,7 @@ static int __init alsa_card_cs423x_init(void) platform_devices[i] = device; cards++; } +#ifdef CONFIG_PNP #ifdef CS4232 i = pnp_register_driver(&cs4232_pnp_driver); if (i >= 0) { @@ -790,6 +797,8 @@ static int __init alsa_card_cs423x_init(void) pnpc_registered = 1; cards += i; } +#endif /* CONFIG_PNP */ + if (!cards) { #ifdef MODULE printk(KERN_ERR IDENT " soundcard not found or device busy\n"); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index bf5de0782eb0..08f032b51107 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1878,9 +1878,9 @@ module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; #ifdef CONFIG_PNP +static int pnp_registered; static struct pnp_card_device_id snd_audiodrive_pnpids[] = { /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ @@ -2209,8 +2209,10 @@ static void __init_or_module snd_es18xx_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&es18xx_pnpc_driver); +#endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_es18xx_nonpnp_driver); @@ -2237,11 +2239,13 @@ static int __init alsa_card_es18xx_init(void) cards++; } +#ifdef CONFIG_PNP i = pnp_register_card_driver(&es18xx_pnpc_driver); if (i >= 0) { pnp_registered = 1; cards += i; } +#endif if(!cards) { #ifdef MODULE diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index d1165b96fa3f..91c219116d7a 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -195,7 +195,7 @@ static int __init snd_gusclassic_probe(struct platform_device *pdev) goto _err; } sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1); - if (dma2 >= 0) + if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", xdma2); snd_card_set_dev(card, &pdev->dev); diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index ca359e0c674b..9d8431978501 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -91,8 +91,10 @@ module_param_array(opl3sa3_ymode, int, NULL, 0444); MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); static struct platform_device *platform_devices[SNDRV_CARDS]; +#ifdef CONFIG_PNP static int pnp_registered; static int pnpc_registered; +#endif /* control ports */ #define OPL3SA2_PM_CTRL 0x01 @@ -721,7 +723,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) } sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", card->shortname, chip->port, xirq, xdma1); - if (dma2 >= 0) + if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", xdma2); return snd_card_register(card); @@ -779,7 +781,7 @@ static int snd_opl3sa2_pnp_resume(struct pnp_dev *pdev) #endif static struct pnp_driver opl3sa2_pnp_driver = { - .name = "opl3sa2-pnpbios", + .name = "snd-opl3sa2-pnpbios", .id_table = snd_opl3sa2_pnpbiosids, .probe = snd_opl3sa2_pnp_detect, .remove = __devexit_p(snd_opl3sa2_pnp_remove), @@ -846,7 +848,7 @@ static int snd_opl3sa2_pnp_cresume(struct pnp_card_link *pcard) static struct pnp_card_driver opl3sa2_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, - .name = "opl3sa2", + .name = "snd-opl3sa2-cpnp", .id_table = snd_opl3sa2_pnpids, .probe = snd_opl3sa2_pnp_cdetect, .remove = __devexit_p(snd_opl3sa2_pnp_cremove), @@ -929,10 +931,12 @@ static void __init_or_module snd_opl3sa2_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnpc_registered) pnp_unregister_card_driver(&opl3sa2_pnpc_driver); if (pnp_registered) pnp_unregister_driver(&opl3sa2_pnp_driver); +#endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_opl3sa2_nonpnp_driver); @@ -961,6 +965,7 @@ static int __init alsa_card_opl3sa2_init(void) cards++; } +#ifdef CONFIG_PNP err = pnp_register_driver(&opl3sa2_pnp_driver); if (err >= 0) { pnp_registered = 1; @@ -971,6 +976,7 @@ static int __init alsa_card_opl3sa2_init(void) pnpc_registered = 1; cards += err; } +#endif if (!cards) { #ifdef MODULE diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 1ea3944ef7ab..63d96be11b2b 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -1349,7 +1349,7 @@ static int snd_opti93x_pcm(struct snd_opti93x *codec, int device, struct snd_pcm int error; struct snd_pcm *pcm; - if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm))) + if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)) < 0) return error; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index c0be7a5a3425..0667bd14ad60 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -179,6 +179,8 @@ static struct pnp_card_device_id snd_sb16_pnpids[] = { { .id = "CTL0086", .devs = { { "CTL0041" } } }, /* Sound Blaster Vibra16X */ { .id = "CTL00f0", .devs = { { "CTL0043" } } }, + /* Sound Blaster 16 (Virtual PC 2004) */ + { .id = "tBA03b0", .devs = { {.id="PNPb003" } } }, #else /* SNDRV_SBAWE defined */ /* Sound Blaster AWE 32 PnP */ { .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } }, @@ -235,8 +237,6 @@ static struct pnp_card_device_id snd_sb16_pnpids[] = { { .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } }, { .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } }, #endif /* SNDRV_SBAWE */ - /* Sound Blaster 16 PnP (Virtual PC 2004)*/ - { .id = "tBA03b0", .devs = { { "PNPb003" } } }, { .id = "", } }; diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 5fb981c0a281..29bba8cc3ef3 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -69,9 +69,9 @@ module_param_array(dma, int, NULL, 0444); MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; #ifdef CONFIG_PNP +static int pnp_registered; static struct pnp_card_device_id sscape_pnpids[] = { { .id = "ENS3081", .devs = { { "ENS0000" } } }, { .id = "" } /* end */ @@ -1391,8 +1391,10 @@ static void __init_or_module sscape_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&sscape_pnpc_driver); +#endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_sscape_driver); @@ -1466,8 +1468,10 @@ static int __init sscape_init(void) ret = sscape_manual_probe(); if (ret < 0) return ret; +#ifdef CONFIG_PNP if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0) pnp_registered = 1; +#endif return 0; } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index a6dcb2f970ca..fa3ab960de17 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -84,10 +84,9 @@ module_param_array(use_cs4232_midi, bool, NULL, 0444); MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; - #ifdef CONFIG_PNP +static int pnp_registered; static struct pnp_card_device_id snd_wavefront_pnpids[] = { /* Tropez */ @@ -695,8 +694,10 @@ static void __init_or_module snd_wavefront_unregister_all(void) { int i; +#ifdef CONFIG_PNP if (pnp_registered) pnp_unregister_card_driver(&wavefront_pnpc_driver); +#endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_wavefront_driver); @@ -725,11 +726,13 @@ static int __init alsa_card_wavefront_init(void) cards++; } +#ifdef CONFIG_PNP i = pnp_register_card_driver(&wavefront_pnpc_driver); if (i >= 0) { pnp_registered = 1; cards += i; } +#endif if (!cards) { #ifdef MODULE diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index ed81eec6e732..68aa091e8961 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -866,7 +866,7 @@ wavefront_send_sample (snd_wavefront_t *dev, divided by 2. */ - u16 sample_short; + u16 sample_short = 0; u32 length; u16 __user *data_end = NULL; unsigned int i; diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index b963c550dae6..bdee0502f3e2 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -462,7 +462,7 @@ stop_dac(struct au1550_state *s) /* Wait for Transmit Busy to show disabled. */ do { - stat = readl((void *)PSC_AC97STAT); + stat = au_readl(PSC_AC97STAT); au_sync(); } while ((stat & PSC_AC97STAT_TB) != 0); @@ -491,7 +491,7 @@ stop_adc(struct au1550_state *s) /* Wait for Receive Busy to show disabled. */ do { - stat = readl((void *)PSC_AC97STAT); + stat = au_readl(PSC_AC97STAT); au_sync(); } while ((stat & PSC_AC97STAT_RB) != 0); @@ -541,7 +541,7 @@ set_xmit_slots(int num_channels) /* Wait for Device ready. */ do { - stat = readl((void *)PSC_AC97STAT); + stat = au_readl(PSC_AC97STAT); au_sync(); } while ((stat & PSC_AC97STAT_DR) == 0); } @@ -573,7 +573,7 @@ set_recv_slots(int num_channels) /* Wait for Device ready. */ do { - stat = readl((void *)PSC_AC97STAT); + stat = au_readl(PSC_AC97STAT); au_sync(); } while ((stat & PSC_AC97STAT_DR) == 0); } @@ -1995,7 +1995,7 @@ au1550_probe(void) /* Wait for PSC ready. */ do { - val = readl((void *)PSC_AC97STAT); + val = au_readl(PSC_AC97STAT); au_sync(); } while ((val & PSC_AC97STAT_SR) == 0); @@ -2018,7 +2018,7 @@ au1550_probe(void) /* Wait for Device ready. */ do { - val = readl((void *)PSC_AC97STAT); + val = au_readl(PSC_AC97STAT); au_sync(); } while ((val & PSC_AC97STAT_DR) == 0); diff --git a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h index 3a6d48666db0..0741c28e56ce 100644 --- a/sound/oss/dmasound/tas_common.h +++ b/sound/oss/dmasound/tas_common.h @@ -178,10 +178,10 @@ tas_write_register( struct tas_data_t *self, if (write_mode & WRITE_SHADOW) memcpy(self->shadow[reg_num],data,reg_width); if (write_mode & WRITE_HW) { - rc=i2c_smbus_write_block_data(self->client, - reg_num, - reg_width, - data); + rc=i2c_smbus_write_i2c_block_data(self->client, + reg_num, + reg_width, + data); if (rc < 0) { printk("tas: I2C block write failed \n"); return rc; @@ -199,10 +199,10 @@ tas_sync_register( struct tas_data_t *self, if (reg_width==0 || self==NULL) return -EINVAL; - rc=i2c_smbus_write_block_data(self->client, - reg_num, - reg_width, - self->shadow[reg_num]); + rc=i2c_smbus_write_i2c_block_data(self->client, + reg_num, + reg_width, + self->shadow[reg_num]); if (rc < 0) { printk("tas: I2C block write failed \n"); return rc; diff --git a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c index 67c3fd04cfdd..2ce56180e7d4 100644 --- a/sound/oss/emu10k1/recmgr.c +++ b/sound/oss/emu10k1/recmgr.c @@ -29,7 +29,7 @@ ********************************************************************** */ -#include <asm/delay.h> +#include <linux/delay.h> #include "8010.h" #include "recmgr.h" diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 5f0ad6bb43b9..a21c663e7e12 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c @@ -278,16 +278,14 @@ static char *card_names[] = { }; static struct pci_device_id trident_pci_tbl[] = { - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX}, - {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, - {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451}, - {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050}, + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), + PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX}, + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), + 0, 0, TRIDENT_4D_NX}, + {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018}, + {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451}, + {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050), + 0, 0, CYBER5050}, {0,} }; diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 4aa5fdc5688e..a444a78c7c94 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1621,8 +1621,27 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = { AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), }; +/* black list to avoid HP/Line jack-sense controls + * (SS vendor << 16 | device) + */ +static unsigned int ad1981_jacks_blacklist[] = { + 0x10140554, /* Thinkpad T42p/R50p */ + 0 /* end */ +}; + +static int check_list(struct snd_ac97 *ac97, const unsigned int *list) +{ + u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device; + for (; *list; list++) + if (*list == subid) + return 1; + return 0; +} + static int patch_ad1981a_specific(struct snd_ac97 * ac97) { + if (check_list(ac97, ad1981_jacks_blacklist)) + return 0; return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); } @@ -1635,22 +1654,26 @@ static struct snd_ac97_build_ops patch_ad1981a_build_ops = { #endif }; +/* white list to enable HP jack-sense bits + * (SS vendor << 16 | device) + */ +static unsigned int ad1981_jacks_whitelist[] = { + 0x0e11005a, /* HP nc4000/4010 */ + 0x103c0890, /* HP nc6000 */ + 0x103c0938, /* HP nc4220 */ + 0x103c099c, /* HP nx6110 */ + 0x103c0944, /* HP nc6220 */ + 0x103c0934, /* HP nc8220 */ + 0x103c006d, /* HP nx9105 */ + 0x17340088, /* FSC Scenic-W */ + 0 /* end */ +}; + static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97) { - u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device; - switch (subid) { - case 0x0e11005a: /* HP nc4000/4010 */ - case 0x103c0890: /* HP nc6000 */ - case 0x103c0938: /* HP nc4220 */ - case 0x103c099c: /* HP nx6110 */ - case 0x103c0944: /* HP nc6220 */ - case 0x103c0934: /* HP nc8220 */ - case 0x103c006d: /* HP nx9105 */ - case 0x17340088: /* FSC Scenic-W */ + if (check_list(ac97, ad1981_jacks_whitelist)) /* enable headphone jack sense */ snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); - break; - } } int patch_ad1981a(struct snd_ac97 *ac97) @@ -1672,6 +1695,8 @@ static int patch_ad1981b_specific(struct snd_ac97 *ac97) if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) return err; + if (check_list(ac97, ad1981_jacks_blacklist)) + return 0; return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); } @@ -2210,9 +2235,9 @@ static void alc850_update_jacks(struct snd_ac97 *ac97) /* Vref disable (bit12), 1kOhm (bit13) */ snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), shared ? (1<<12) : (1<<13)); - /* MIC-IN = 1, CENTER-LFE = 2 */ + /* MIC-IN = 1, CENTER-LFE = 5 */ snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, - shared ? (2<<4) : (1<<4)); + shared ? (5<<4) : (1<<4)); } static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = { diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index bc4d1ef08efa..e264136e8fb4 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -279,7 +279,7 @@ struct snd_ali { }; static struct pci_device_id snd_ali_ids[] = { - {0x10b9, 0x5451, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0}, {0, } }; MODULE_DEVICE_TABLE(pci, snd_ali_ids); diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 13bc8ed301c5..c8280f82eb5a 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c @@ -849,7 +849,7 @@ static int snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int i, count; + int i, count = 0; u16 peaks[20]; vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index dc9cd3079b14..c840a4c08e98 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -781,6 +781,8 @@ static struct pci_device_id snd_bt87x_ids[] = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), /* Viewcast Osprey 200 */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), + /* AVerMedia Studio No. 103, 203, ...? */ + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), { } }; MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); @@ -808,7 +810,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) const struct pci_device_id *supported; supported = pci_match_device(&driver, pci); - if (supported) + if (supported && supported->driver_data > 0) return supported->driver_data; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 6ed7c0bfa091..9477838a9c88 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -199,7 +199,8 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "MSI K8N Diamond MB [SB0438]", .gpio_type = 1, .i2c_adc = 1 } , - /* Shuttle XPC SD31P which has an onboard Creative Labs Sound Blaster Live! 24-bit EAX + /* Shuttle XPC SD31P which has an onboard Creative Labs + * Sound Blaster Live! 24-bit EAX * high-definition 7.1 audio processor". * Added using info from andrewvegan in alsa bug #1298 */ @@ -207,6 +208,15 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "Shuttle XPC SD31P [SD31P]", .gpio_type = 1, .i2c_adc = 1 } , + /* Shuttle XPC SD11G5 which has an onboard Creative Labs + * Sound Blaster Live! 24-bit EAX + * high-definition 7.1 audio processor". + * Fixes ALSA bug#1600 + */ + { .serial = 0x30411297, + .name = "Shuttle XPC SD11G5 [SD11G5]", + .gpio_type = 1, + .i2c_adc = 1 } , { .serial = 0, .name = "AudigyLS [Unknown]" } }; diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 509aa2b63331..d4e0fb39bd06 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -675,7 +675,7 @@ cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, if (pass_through) { /* wont work with any other rate than the native DSP rate */ - snd_assert (rate = 48000); + snd_assert (rate == 48000); scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, dest,"DMAREADER",parent_scb, diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index f36ede827479..02e3721030b7 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -46,8 +46,10 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; static struct pci_device_id snd_cs5535audio_ids[] = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0, }, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, {} }; diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 2e86a901a0a4..2a9d12d10680 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -759,6 +759,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, "Master Mono Playback Volume", "PCM Out Path & Mute", "Mono Output Select", + "Front Playback Switch", + "Front Playback Volume", "Surround Playback Switch", "Surround Playback Volume", "Center Playback Switch", @@ -829,9 +831,9 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, } if (emu->audigy) { /* set master volume to 0 dB */ - snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000); + snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); /* set capture source to mic */ - snd_ac97_write(emu->ac97, AC97_REC_SEL, 0x0000); + snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); c = audigy_remove_ctls; } else { /* @@ -844,8 +846,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); } /* remove unused AC97 controls */ - snd_ac97_write(emu->ac97, AC97_SURROUND_MASTER, 0x0202); - snd_ac97_write(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202); + snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); + snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202); c = emu10k1_remove_ctls; } for (; *c; c++) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a983deba4025..fd12b6991fe4 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -75,6 +75,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH6M}," "{Intel, ICH7}," "{Intel, ESB2}," + "{Intel, ICH8}," "{ATI, SB450}," "{VIA, VT8251}," "{VIA, VT8237A}," @@ -1586,6 +1587,7 @@ static struct pci_device_id azx_ids[] = { { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */ { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */ { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ + { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ad9e501a9818..b76755264730 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1668,6 +1668,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST }, { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */ + { .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */ { .modelname = "6stack-digout", .config = ALC880_6ST_DIG }, { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, @@ -2475,7 +2476,7 @@ static struct hda_verb alc260_init_verbs[] = { /* LINE-2 is used for line-out in rear */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* select line-out */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, /* LINE-OUT pin */ {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* enable HP */ @@ -2945,6 +2946,8 @@ static int alc260_auto_init(struct hda_codec *codec) */ static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "basic", .config = ALC260_BASIC }, + { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, + .config = ALC260_BASIC }, /* Sony VAIO */ { .modelname = "hp", .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, @@ -3414,12 +3417,12 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { * configuration and preset */ static struct hda_board_config alc882_cfg_tbl[] = { - { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, - { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, + { .modelname = "3stack-dig", .config = ALC882_3ST_DIG }, + { .modelname = "6stack-dig", .config = ALC882_6ST_DIG }, { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */ { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */ { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */ - { .modelname = "auto", .config = ALC861_AUTO }, + { .modelname = "auto", .config = ALC882_AUTO }, {} }; diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 8f8840e6002b..250242cd6c70 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -297,6 +297,7 @@ static int patch_si3054(struct hda_codec *codec) struct hda_codec_preset snd_hda_preset_si3054[] = { { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, + { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, {} }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 61903848cd43..35c2823a0a2b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -50,10 +50,11 @@ struct sigmatel_spec { unsigned int surr_switch: 1; unsigned int line_switch: 1; unsigned int mic_switch: 1; + unsigned int alt_switch: 1; /* playback */ struct hda_multi_out multiout; - hda_nid_t dac_nids[4]; + hda_nid_t dac_nids[5]; /* capture */ hda_nid_t *adc_nids; @@ -73,7 +74,7 @@ struct sigmatel_spec { /* capture source */ struct hda_input_mux *input_mux; - unsigned int cur_mux[2]; + unsigned int cur_mux[3]; /* i/o switches */ unsigned int io_switch[2]; @@ -107,6 +108,14 @@ static hda_nid_t stac922x_mux_nids[2] = { 0x12, 0x13, }; +static hda_nid_t stac927x_adc_nids[3] = { + 0x07, 0x08, 0x09 +}; + +static hda_nid_t stac927x_mux_nids[3] = { + 0x15, 0x16, 0x17 +}; + static hda_nid_t stac9200_pin_nids[8] = { 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, }; @@ -116,6 +125,12 @@ static hda_nid_t stac922x_pin_nids[10] = { 0x0f, 0x10, 0x11, 0x15, 0x1b, }; +static hda_nid_t stac927x_pin_nids[14] = { + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x21, 0x22, 0x23, +}; + static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); @@ -155,6 +170,12 @@ static struct hda_verb stac922x_core_init[] = { {} }; +static struct hda_verb stac927x_core_init[] = { + /* set master volume and direct control */ + { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + {} +}; + static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), @@ -183,10 +204,26 @@ static struct snd_kcontrol_new stac922x_mixer[] = { .put = stac92xx_mux_enum_put, }, HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), { } /* end */ }; +static snd_kcontrol_new_t stac927x_mixer[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Input Source", + .count = 1, + .info = stac92xx_mux_enum_info, + .get = stac92xx_mux_enum_get, + .put = stac92xx_mux_enum_put, + }, + HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), + { } /* end */ +}; + static int stac92xx_build_controls(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -240,14 +277,14 @@ static unsigned int ref922x_pin_configs[10] = { }; static unsigned int d945gtp3_pin_configs[10] = { - 0x0221401f, 0x01a19022, 0x01813021, 0x01114010, + 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, 0x40000100, 0x40000100, 0x40000100, 0x40000100, 0x02a19120, 0x40000100, }; static unsigned int d945gtp5_pin_configs[10] = { - 0x0221401f, 0x01111012, 0x01813024, 0x01114010, - 0x01a19021, 0x01116011, 0x01452130, 0x40000100, + 0x0221401f, 0x01011012, 0x01813024, 0x01014010, + 0x01a19021, 0x01016011, 0x01452130, 0x40000100, 0x02a19320, 0x40000100, }; @@ -274,6 +311,28 @@ static struct hda_board_config stac922x_cfg_tbl[] = { { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0013, .config = STAC_D945GTP5 }, /* Intel D955XBK - 5 Stack */ + { .pci_subvendor = PCI_VENDOR_ID_INTEL, + .pci_subdevice = 0x0417, + .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ + {} /* terminator */ +}; + +static unsigned int ref927x_pin_configs[14] = { + 0x01813122, 0x01a19021, 0x01014010, 0x01016011, + 0x01012012, 0x01011014, 0x40000100, 0x40000100, + 0x40000100, 0x40000100, 0x40000100, 0x01441030, + 0x01c41030, 0x40000100, +}; + +static unsigned int *stac927x_brd_tbl[] = { + ref927x_pin_configs, +}; + +static struct hda_board_config stac927x_cfg_tbl[] = { + { .modelname = "ref", + .pci_subvendor = PCI_VENDOR_ID_INTEL, + .pci_subdevice = 0x2668, /* DFI LanParty */ + .config = STAC_REF }, /* SigmaTel reference board */ {} /* terminator */ }; @@ -408,11 +467,23 @@ static struct hda_pcm_stream stac92xx_pcm_analog_playback = { }, }; +static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x06, /* NID to query formats and rates */ + .ops = { + .open = stac92xx_playback_pcm_open, + .prepare = stac92xx_playback_pcm_prepare, + .cleanup = stac92xx_playback_pcm_cleanup + }, +}; + static struct hda_pcm_stream stac92xx_pcm_analog_capture = { .substreams = 2, .channels_min = 2, .channels_max = 2, - .nid = 0x06, /* NID to query formats and rates */ + /* NID is set in stac92xx_build_pcms */ .ops = { .prepare = stac92xx_capture_pcm_prepare, .cleanup = stac92xx_capture_pcm_cleanup @@ -430,6 +501,14 @@ static int stac92xx_build_pcms(struct hda_codec *codec) info->name = "STAC92xx Analog"; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; + + if (spec->alt_switch) { + codec->num_pcms++; + info++; + info->name = "STAC92xx Analog Alt"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback; + } if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms++; @@ -588,6 +667,16 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf return 0; } +/* + * XXX The line_out pin widget connection list may not be set to the + * desired DAC nid. This is the case on 927x where ports A and B can + * be routed to several DACs. + * + * This requires an analysis of the line-out/hp pin configuration + * to provide a best fit for pin/DAC configurations that are routable. + * For now, 927x DAC4 is not supported and 927x DAC1 output to ports + * A and B is not supported. + */ /* fill in the dac_nids table from the parsed pin configuration */ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { @@ -602,7 +691,13 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct aut AC_VERB_GET_CONNECT_LIST, 0) & 0xff; } - spec->multiout.num_dacs = cfg->line_outs; + if (cfg->line_outs) + spec->multiout.num_dacs = cfg->line_outs; + else if (cfg->hp_pin) { + spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0, + AC_VERB_GET_CONNECT_LIST, 0) & 0xff; + spec->multiout.num_dacs = 1; + } return 0; } @@ -753,19 +848,21 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); } -static int stac922x_parse_auto_config(struct hda_codec *codec) +static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) { struct sigmatel_spec *spec = codec->spec; int err; if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) return err; + if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) + return 0; /* can't find valid pin config */ + stac92xx_auto_init_multi_out(codec); + stac92xx_auto_init_hp_out(codec); if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) return err; if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) - return 0; /* can't find valid pin config */ if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || @@ -777,11 +874,11 @@ static int stac922x_parse_auto_config(struct hda_codec *codec) spec->surr_switch = 1; if (spec->autocfg.dig_out_pin) { - spec->multiout.dig_out_nid = 0x08; + spec->multiout.dig_out_nid = dig_out; stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); } if (spec->autocfg.dig_in_pin) { - spec->dig_in_nid = 0x09; + spec->dig_in_nid = dig_in; stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); } @@ -827,9 +924,6 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_sequence_write(codec, spec->init); - stac92xx_auto_init_multi_out(codec); - stac92xx_auto_init_hp_out(codec); - return 0; } @@ -996,7 +1090,47 @@ static int patch_stac922x(struct hda_codec *codec) spec->multiout.dac_nids = spec->dac_nids; - err = stac922x_parse_auto_config(codec); + err = stac92xx_parse_auto_config(codec, 0x08, 0x09); + if (err < 0) { + stac92xx_free(codec); + return err; + } + + codec->patch_ops = stac92xx_patch_ops; + + return 0; +} + +static int patch_stac927x(struct hda_codec *codec) +{ + struct sigmatel_spec *spec; + int err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); + if (spec->board_config < 0) + snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); + else { + spec->num_pins = 14; + spec->pin_nids = stac927x_pin_nids; + spec->pin_configs = stac927x_brd_tbl[spec->board_config]; + stac92xx_set_config_regs(codec); + } + + spec->adc_nids = stac927x_adc_nids; + spec->mux_nids = stac927x_mux_nids; + spec->num_muxes = 3; + + spec->init = stac927x_core_init; + spec->mixer = stac927x_mixer; + + spec->multiout.dac_nids = spec->dac_nids; + + err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); if (err < 0) { stac92xx_free(codec); return err; @@ -1018,5 +1152,15 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, + { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, + { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, + { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, + { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, + { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, + { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, + { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, + { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, + { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, + { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, {} /* terminator */ }; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5466b1fa0cd5..174237f4a22c 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -427,6 +427,7 @@ static struct pci_device_id snd_intel8x0_ids[] = { { 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8 */ { 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */ { 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8S */ + { 0x10de, 0x026b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* MCP51 */ { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ { 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ @@ -1805,6 +1806,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x0151, + .name = "Dell Optiplex GX270", /* AD1981B */ + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x1028, .subdevice = 0x0163, .name = "Dell Unknown", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY @@ -1847,12 +1854,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x103c, - .subdevice = 0x099c, - .name = "HP nx6110", /* AD1981B */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, .subdevice = 0x129d, .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY @@ -1866,7 +1867,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { { .subvendor = 0x103c, .subdevice = 0x099c, - .name = "HP nc6120", + .name = "HP nx6110/nc6120", .type = AC97_TUNE_HP_MUTE_LED }, { diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index b8c0853a8278..b2cba75b6b16 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -454,7 +454,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream) is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE); stream_num = is_capture ? 0 : subs->number; - snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%x) subs(%d)\n", + snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n", is_capture ? 'c' : 'p', chip->chip_idx, (void*)subs->runtime->dma_addr, subs->runtime->dma_bytes, subs->number); @@ -744,13 +744,14 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) /* only the first stream can choose the sample rate */ /* the further opened streams will be limited to its frequency (see open) */ /* set the clock only once (first stream) */ - if (mgr->sample_rate == 0) { + if (mgr->sample_rate != subs->runtime->rate) { err = pcxhr_set_clock(mgr, subs->runtime->rate); if (err) break; + if (mgr->sample_rate == 0) + /* start the DSP-timer */ + err = pcxhr_hardware_timer(mgr, 1); mgr->sample_rate = subs->runtime->rate; - - err = pcxhr_hardware_timer(mgr, 1); /* start the DSP-timer */ } } while(0); /* do only once (so we can use break instead of goto) */ diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 3dec616bad6b..103b4d715ff4 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -3324,11 +3324,11 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) snd_dma_pci_data(hdspm->pci), wanted, wanted)) < 0) { - snd_printdd("Could not preallocate %d Bytes\n", wanted); + snd_printdd("Could not preallocate %zd Bytes\n", wanted); return err; } else - snd_printdd(" Preallocated %d Bytes\n", wanted); + snd_printdd(" Preallocated %zd Bytes\n", wanted); return 0; } @@ -3510,7 +3510,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp hdspm->monitor_outs = enable_monitor; - snd_printdd("kmalloc Mixer memory of %d Bytes\n", + snd_printdd("kmalloc Mixer memory of %zd Bytes\n", sizeof(struct hdspm_mixer)); if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL)) == NULL) { diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 2b21df16ad6a..b4538045049f 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -64,9 +64,11 @@ module_param_array(wavetable_size, int, NULL, 0444); MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); static struct pci_device_id snd_trident_ids[] = { - { 0x1023, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Trident 4DWave DX PCI Audio */ - { 0x1023, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Trident 4DWave NX PCI Audio */ - { 0x1039, 0x7018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* SiS SI7018 PCI Audio */ + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), + PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, + {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), + 0, 0, 0}, + {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0}, { 0, } }; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index ed26a155c344..423741371191 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2340,6 +2340,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ { .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */ { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ + { .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC }, /* ASUS */ { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */ { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ @@ -2358,6 +2359,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */ + { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */ { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */ { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ @@ -2371,6 +2373,9 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ + { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */ + { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ + { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 1dfc7233c6a8..a1aa74b79b3d 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1229,6 +1229,7 @@ static int snd_ymfpci_spdif_default_get(struct snd_kcontrol *kcontrol, spin_lock_irq(&chip->reg_lock); ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff; + ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1303,6 +1304,7 @@ static int snd_ymfpci_spdif_stream_get(struct snd_kcontrol *kcontrol, spin_lock_irq(&chip->reg_lock); ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff; + ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; spin_unlock_irq(&chip->reg_lock); return 0; } diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index a642e4cfcf45..aa57170101fd 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -66,7 +66,7 @@ static int snd_pmac_dbdma_alloc(struct snd_pmac *chip, struct pmac_dbdma *rec, i static void snd_pmac_dbdma_free(struct snd_pmac *chip, struct pmac_dbdma *rec) { - if (rec) { + if (rec->space) { unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); @@ -881,6 +881,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) chip->can_capture = 1; chip->num_freqs = ARRAY_SIZE(awacs_freqs); chip->freq_table = awacs_freqs; + chip->pdev = NULL; chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */ @@ -1216,7 +1217,7 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) goto __error; } for (i = 0; i < 3; i ++) { - if (of_address_to_resource(np->parent, i, + if (of_address_to_resource(np, i, &chip->rsrc[i])) { printk(KERN_ERR "snd: can't translate rsrc " " %d (%s)\n", i, rnames[i]); diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 15c63cb2ccba..838fc113c441 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -239,8 +239,8 @@ static int tumbler_set_master_volume(struct pmac_tumbler *mix) block[4] = (right_vol >> 8) & 0xff; block[5] = (right_vol >> 0) & 0xff; - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_VOL, - 6, block) < 0) { + if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, + block) < 0) { snd_printk("failed to set volume \n"); return -EINVAL; } @@ -345,8 +345,8 @@ static int tumbler_set_drc(struct pmac_tumbler *mix) val[1] = 0; } - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, - 2, val) < 0) { + if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, + 2, val) < 0) { snd_printk("failed to set DRC\n"); return -EINVAL; } @@ -381,8 +381,8 @@ static int snapper_set_drc(struct pmac_tumbler *mix) val[4] = 0x60; val[5] = 0xa0; - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, - 6, val) < 0) { + if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, + 6, val) < 0) { snd_printk("failed to set DRC\n"); return -EINVAL; } @@ -492,8 +492,8 @@ static int tumbler_set_mono_volume(struct pmac_tumbler *mix, vol = info->table[vol]; for (i = 0; i < info->bytes; i++) block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; - if (i2c_smbus_write_block_data(mix->i2c.client, info->reg, - info->bytes, block) < 0) { + if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, + info->bytes, block) < 0) { snd_printk("failed to set mono volume %d\n", info->index); return -EINVAL; } @@ -625,7 +625,8 @@ static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int r for (j = 0; j < 3; j++) block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff; } - if (i2c_smbus_write_block_data(mix->i2c.client, reg, 9, block) < 0) { + if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, + 9, block) < 0) { snd_printk("failed to set mono volume %d\n", reg); return -EINVAL; } diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index a1bd8040dea4..d5013383fad7 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -478,22 +478,38 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs, /* * Prepare urb for streaming before playback starts. * - * We don't care about (or have) any data, so we just send a transfer delimiter. + * We don't yet have data, so we send a frame of silence. */ static int prepare_startup_playback_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *urb) { - unsigned int i; + unsigned int i, offs, counts; struct snd_urb_ctx *ctx = urb->context; + int stride = runtime->frame_bits >> 3; + offs = 0; urb->dev = ctx->subs->dev; urb->number_of_packets = subs->packs_per_ms; for (i = 0; i < subs->packs_per_ms; ++i) { - urb->iso_frame_desc[i].offset = 0; - urb->iso_frame_desc[i].length = 0; + /* calculate the size of a packet */ + if (subs->fill_max) + counts = subs->maxframesize; /* fixed */ + else { + subs->phase = (subs->phase & 0xffff) + + (subs->freqm << subs->datainterval); + counts = subs->phase >> 16; + if (counts > subs->maxframesize) + counts = subs->maxframesize; + } + urb->iso_frame_desc[i].offset = offs * stride; + urb->iso_frame_desc[i].length = counts * stride; + offs += counts; } - urb->transfer_buffer_length = 0; + urb->transfer_buffer_length = offs * stride; + memset(urb->transfer_buffer, + subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, + offs * stride); return 0; } @@ -2477,12 +2493,13 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp if (err < 0) return err; #if 1 - /* FIXME: temporary hack for extigy/audigy 2 nx */ + /* FIXME: temporary hack for extigy/audigy 2 nx/zs */ /* extigy apparently supports sample rates other than 48k * but not in ordinary way. so we enable only 48k atm. */ if (chip->usb_id == USB_ID(0x041e, 0x3000) || - chip->usb_id == USB_ID(0x041e, 0x3020)) { + chip->usb_id == USB_ID(0x041e, 0x3020) || + chip->usb_id == USB_ID(0x041e, 0x3061)) { if (fmt[3] == USB_FORMAT_TYPE_I && fp->rates != SNDRV_PCM_RATE_48000 && fp->rates != SNDRV_PCM_RATE_96000) |