diff options
313 files changed, 7951 insertions, 3321 deletions
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 6761a7b241a5..7f43b040311e 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -149,6 +149,11 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the MAINTAINERS file for a mailing list that relates specifically to your change. +If changes affect userland-kernel interfaces, please send +the MAN-PAGES maintainer (as listed in the MAINTAINERS file) +a man-pages patch, or at least a notification of the change, +so that some information makes its way into the manual pages. + Even if the maintainer did not respond in step #4, make sure to ALWAYS copy the maintainer when you change their code. diff --git a/Documentation/dontdiff b/Documentation/dontdiff index b974cf595d01..96bea278bbf6 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -104,6 +104,7 @@ logo_*.c logo_*_clut224.c logo_*_mono.c lxdialog +mach-types mach-types.h make_times_h map diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt index 814e2f56a6ad..62db6758d1c1 100644 --- a/Documentation/fb/vesafb.txt +++ b/Documentation/fb/vesafb.txt @@ -144,7 +144,21 @@ vgapal Use the standard vga registers for palette changes. This is the default. pmipal Use the protected mode interface for palette changes. -mtrr setup memory type range registers for the vesafb framebuffer. +mtrr:n setup memory type range registers for the vesafb framebuffer + where n: + 0 - disabled (equivalent to nomtrr) + 1 - uncachable + 2 - write-back + 3 - write-combining (default) + 4 - write-through + + If you see the following in dmesg, choose the type that matches the + old one. In this example, use "mtrr:2". +... +mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining +... + +nomtrr disable mtrr vremap:n remap 'n' MiB of video RAM. If 0 or not specified, remap memory diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 0bc2ed136a38..24d029455baa 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -1,5 +1,7 @@ - Linux Ethernet Bonding Driver HOWTO + Linux Ethernet Bonding Driver HOWTO + + Latest update: 21 June 2005 Initial release : Thomas Davis <tadavis at lbl.gov> Corrections, HA extensions : 2000/10/03-15 : @@ -11,15 +13,22 @@ Corrections, HA extensions : 2000/10/03-15 : Reorganized and updated Feb 2005 by Jay Vosburgh -Note : ------- +Introduction +============ + + The Linux bonding driver provides a method for aggregating +multiple network interfaces into a single logical "bonded" interface. +The behavior of the bonded interfaces depends upon the mode; generally +speaking, modes provide either hot standby or load balancing services. +Additionally, link integrity monitoring may be performed. -The bonding driver originally came from Donald Becker's beowulf patches for -kernel 2.0. It has changed quite a bit since, and the original tools from -extreme-linux and beowulf sites will not work with this version of the driver. + The bonding driver originally came from Donald Becker's +beowulf patches for kernel 2.0. It has changed quite a bit since, and +the original tools from extreme-linux and beowulf sites will not work +with this version of the driver. -For new versions of the driver, patches for older kernels and the updated -userspace tools, please follow the links at the end of this file. + For new versions of the driver, updated userspace tools, and +who to ask for help, please follow the links at the end of this file. Table of Contents ================= @@ -30,9 +39,13 @@ Table of Contents 3. Configuring Bonding Devices 3.1 Configuration with sysconfig support +3.1.1 Using DHCP with sysconfig +3.1.2 Configuring Multiple Bonds with sysconfig 3.2 Configuration with initscripts support +3.2.1 Using DHCP with initscripts +3.2.2 Configuring Multiple Bonds with initscripts 3.3 Configuring Bonding Manually -3.4 Configuring Multiple Bonds +3.3.1 Configuring Multiple Bonds Manually 5. Querying Bonding Configuration 5.1 Bonding Configuration @@ -56,21 +69,30 @@ Table of Contents 11. Promiscuous mode -12. High Availability Information +12. Configuring Bonding for High Availability 12.1 High Availability in a Single Switch Topology -12.1.1 Bonding Mode Selection for Single Switch Topology -12.1.2 Link Monitoring for Single Switch Topology 12.2 High Availability in a Multiple Switch Topology -12.2.1 Bonding Mode Selection for Multiple Switch Topology -12.2.2 Link Monitoring for Multiple Switch Topology -12.3 Switch Behavior Issues for High Availability +12.2.1 HA Bonding Mode Selection for Multiple Switch Topology +12.2.2 HA Link Monitoring for Multiple Switch Topology + +13. Configuring Bonding for Maximum Throughput +13.1 Maximum Throughput in a Single Switch Topology +13.1.1 MT Bonding Mode Selection for Single Switch Topology +13.1.2 MT Link Monitoring for Single Switch Topology +13.2 Maximum Throughput in a Multiple Switch Topology +13.2.1 MT Bonding Mode Selection for Multiple Switch Topology +13.2.2 MT Link Monitoring for Multiple Switch Topology -13. Hardware Specific Considerations -13.1 IBM BladeCenter +14. Switch Behavior Issues +14.1 Link Establishment and Failover Delays +14.2 Duplicated Incoming Packets -14. Frequently Asked Questions +15. Hardware Specific Considerations +15.1 IBM BladeCenter -15. Resources and Links +16. Frequently Asked Questions + +17. Resources and Links 1. Bonding Driver Installation @@ -86,16 +108,10 @@ the following steps: 1.1 Configure and build the kernel with bonding ----------------------------------------------- - The latest version of the bonding driver is available in the + The current version of the bonding driver is available in the drivers/net/bonding subdirectory of the most recent kernel source -(which is available on http://kernel.org). - - Prior to the 2.4.11 kernel, the bonding driver was maintained -largely outside the kernel tree; patches for some earlier kernels are -available on the bonding sourceforge site, although those patches are -still several years out of date. Most users will want to use either -the most recent kernel from kernel.org or whatever kernel came with -their distro. +(which is available on http://kernel.org). Most users "rolling their +own" will want to use the most recent kernel from kernel.org. Configure kernel with "make menuconfig" (or "make xconfig" or "make config"), then select "Bonding driver support" in the "Network @@ -103,8 +119,8 @@ device support" section. It is recommended that you configure the driver as module since it is currently the only way to pass parameters to the driver or configure more than one bonding device. - Build and install the new kernel and modules, then proceed to -step 2. + Build and install the new kernel and modules, then continue +below to install ifenslave. 1.2 Install ifenslave Control Utility ------------------------------------- @@ -147,9 +163,9 @@ default kernel source include directory. Options for the bonding driver are supplied as parameters to the bonding module at load time. They may be given as command line arguments to the insmod or modprobe command, but are usually specified -in either the /etc/modprobe.conf configuration file, or in a -distro-specific configuration file (some of which are detailed in the -next section). +in either the /etc/modules.conf or /etc/modprobe.conf configuration +file, or in a distro-specific configuration file (some of which are +detailed in the next section). The available bonding driver parameters are listed below. If a parameter is not specified the default value is used. When initially @@ -162,34 +178,34 @@ degradation will occur during link failures. Very few devices do not support at least miimon, so there is really no reason not to use it. Options with textual values will accept either the text name - or, for backwards compatibility, the option value. E.g., - "mode=802.3ad" and "mode=4" set the same mode. +or, for backwards compatibility, the option value. E.g., +"mode=802.3ad" and "mode=4" set the same mode. The parameters are as follows: arp_interval - Specifies the ARP monitoring frequency in milli-seconds. If - ARP monitoring is used in a load-balancing mode (mode 0 or 2), - the switch should be configured in a mode that evenly - distributes packets across all links - such as round-robin. If - the switch is configured to distribute the packets in an XOR + Specifies the ARP link monitoring frequency in milliseconds. + If ARP monitoring is used in an etherchannel compatible mode + (modes 0 and 2), the switch should be configured in a mode + that evenly distributes packets across all links. If the + switch is configured to distribute the packets in an XOR fashion, all replies from the ARP targets will be received on the same link which could cause the other team members to - fail. ARP monitoring should not be used in conjunction with - miimon. A value of 0 disables ARP monitoring. The default + fail. ARP monitoring should not be used in conjunction with + miimon. A value of 0 disables ARP monitoring. The default value is 0. arp_ip_target - Specifies the ip addresses to use when arp_interval is > 0. - These are the targets of the ARP request sent to determine the - health of the link to the targets. Specify these values in - ddd.ddd.ddd.ddd format. Multiple ip adresses must be - seperated by a comma. At least one IP address must be given - for ARP monitoring to function. The maximum number of targets - that can be specified is 16. The default value is no IP - addresses. + Specifies the IP addresses to use as ARP monitoring peers when + arp_interval is > 0. These are the targets of the ARP request + sent to determine the health of the link to the targets. + Specify these values in ddd.ddd.ddd.ddd format. Multiple IP + addresses must be separated by a comma. At least one IP + address must be given for ARP monitoring to function. The + maximum number of targets that can be specified is 16. The + default value is no IP addresses. downdelay @@ -207,11 +223,13 @@ lacp_rate are: slow or 0 - Request partner to transmit LACPDUs every 30 seconds (default) + Request partner to transmit LACPDUs every 30 seconds fast or 1 Request partner to transmit LACPDUs every 1 second + The default is slow. + max_bonds Specifies the number of bonding devices to create for this @@ -221,10 +239,11 @@ max_bonds miimon - Specifies the frequency in milli-seconds that MII link - monitoring will occur. A value of zero disables MII link - monitoring. A value of 100 is a good starting point. The - use_carrier option, below, affects how the link state is + Specifies the MII link monitoring frequency in milliseconds. + This determines how often the link state of each slave is + inspected for link failures. A value of zero disables MII + link monitoring. A value of 100 is a good starting point. + The use_carrier option, below, affects how the link state is determined. See the High Availability section for additional information. The default value is 0. @@ -246,17 +265,31 @@ mode active. A different slave becomes active if, and only if, the active slave fails. The bond's MAC address is externally visible on only one port (network adapter) - to avoid confusing the switch. This mode provides - fault tolerance. The primary option affects the - behavior of this mode. + to avoid confusing the switch. + + In bonding version 2.6.2 or later, when a failover + occurs in active-backup mode, bonding will issue one + or more gratuitous ARPs on the newly active slave. + One gratutious ARP is issued for the bonding master + interface and each VLAN interfaces configured above + it, provided that the interface has at least one IP + address configured. Gratuitous ARPs issued for VLAN + interfaces are tagged with the appropriate VLAN id. + + This mode provides fault tolerance. The primary + option, documented below, affects the behavior of this + mode. balance-xor or 2 - XOR policy: Transmit based on [(source MAC address - XOR'd with destination MAC address) modulo slave - count]. This selects the same slave for each - destination MAC address. This mode provides load - balancing and fault tolerance. + XOR policy: Transmit based on the selected transmit + hash policy. The default policy is a simple [(source + MAC address XOR'd with destination MAC address) modulo + slave count]. Alternate transmit policies may be + selected via the xmit_hash_policy option, described + below. + + This mode provides load balancing and fault tolerance. broadcast or 3 @@ -270,7 +303,17 @@ mode duplex settings. Utilizes all slaves in the active aggregator according to the 802.3ad specification. - Pre-requisites: + Slave selection for outgoing traffic is done according + to the transmit hash policy, which may be changed from + the default simple XOR policy via the xmit_hash_policy + option, documented below. Note that not all transmit + policies may be 802.3ad compliant, particularly in + regards to the packet mis-ordering requirements of + section 43.2.4 of the 802.3ad standard. Differing + peer implementations will have varying tolerances for + noncompliance. + + Prerequisites: 1. Ethtool support in the base drivers for retrieving the speed and duplex of each slave. @@ -333,7 +376,7 @@ mode When a link is reconnected or a new slave joins the bond the receive traffic is redistributed among all - active slaves in the bond by intiating ARP Replies + active slaves in the bond by initiating ARP Replies with the selected mac address to each of the clients. The updelay parameter (detailed below) must be set to a value equal or greater than the switch's @@ -396,6 +439,60 @@ use_carrier 0 will use the deprecated MII / ETHTOOL ioctls. The default value is 1. +xmit_hash_policy + + Selects the transmit hash policy to use for slave selection in + balance-xor and 802.3ad modes. Possible values are: + + layer2 + + Uses XOR of hardware MAC addresses to generate the + hash. The formula is + + (source MAC XOR destination MAC) modulo slave count + + This algorithm will place all traffic to a particular + network peer on the same slave. + + This algorithm is 802.3ad compliant. + + layer3+4 + + This policy uses upper layer protocol information, + when available, to generate the hash. This allows for + traffic to a particular network peer to span multiple + slaves, although a single connection will not span + multiple slaves. + + The formula for unfragmented TCP and UDP packets is + + ((source port XOR dest port) XOR + ((source IP XOR dest IP) AND 0xffff) + modulo slave count + + For fragmented TCP or UDP packets and all other IP + protocol traffic, the source and destination port + information is omitted. For non-IP traffic, the + formula is the same as for the layer2 transmit hash + policy. + + This policy is intended to mimic the behavior of + certain switches, notably Cisco switches with PFC2 as + well as some Foundry and IBM products. + + This algorithm is not fully 802.3ad compliant. A + single TCP or UDP conversation containing both + fragmented and unfragmented packets will see packets + striped across two interfaces. This may result in out + of order delivery. Most traffic types will not meet + this criteria, as TCP rarely fragments traffic, and + most UDP traffic is not involved in extended + conversations. Other implementations of 802.3ad may + or may not tolerate this noncompliance. + + The default value is layer2. This option was added in bonding +version 2.6.3. In earlier versions of bonding, this parameter does +not exist, and the layer2 policy is the only policy. 3. Configuring Bonding Devices @@ -448,8 +545,9 @@ Bonding devices can be managed by hand, however, as follows. slave devices. On SLES 9, this is most easily done by running the yast2 sysconfig configuration utility. The goal is for to create an ifcfg-id file for each slave device. The simplest way to accomplish -this is to configure the devices for DHCP. The name of the -configuration file for each device will be of the form: +this is to configure the devices for DHCP (this is only to get the +file ifcfg-id file created; see below for some issues with DHCP). The +name of the configuration file for each device will be of the form: ifcfg-id-xx:xx:xx:xx:xx:xx @@ -459,7 +557,7 @@ the device's permanent MAC address. Once the set of ifcfg-id-xx:xx:xx:xx:xx:xx files has been created, it is necessary to edit the configuration files for the slave devices (the MAC addresses correspond to those of the slave devices). -Before editing, the file will contain muliple lines, and will look +Before editing, the file will contain multiple lines, and will look something like this: BOOTPROTO='dhcp' @@ -496,16 +594,11 @@ STARTMODE="onboot" BONDING_MASTER="yes" BONDING_MODULE_OPTS="mode=active-backup miimon=100" BONDING_SLAVE0="eth0" -BONDING_SLAVE1="eth1" +BONDING_SLAVE1="bus-pci-0000:06:08.1" Replace the sample BROADCAST, IPADDR, NETMASK and NETWORK values with the appropriate values for your network. - Note that configuring the bonding device with BOOTPROTO='dhcp' -does not work; the scripts attempt to obtain the device address from -DHCP prior to adding any of the slave devices. Without active slaves, -the DHCP requests are not sent to the network. - The STARTMODE specifies when the device is brought online. The possible values are: @@ -531,9 +624,17 @@ for the bonding mode, link monitoring, and so on here. Do not include the max_bonds bonding parameter; this will confuse the configuration system if you have multiple bonding devices. - Finally, supply one BONDING_SLAVEn="ethX" for each slave, -where "n" is an increasing value, one for each slave, and "ethX" is -the name of the slave device (eth0, eth1, etc). + Finally, supply one BONDING_SLAVEn="slave device" for each +slave. where "n" is an increasing value, one for each slave. The +"slave device" is either an interface name, e.g., "eth0", or a device +specifier for the network device. The interface name is easier to +find, but the ethN names are subject to change at boot time if, e.g., +a device early in the sequence has failed. The device specifiers +(bus-pci-0000:06:08.1 in the example above) specify the physical +network device, and will not change unless the device's bus location +changes (for example, it is moved from one PCI slot to another). The +example above uses one of each type for demonstration purposes; most +configurations will choose one or the other for all slave devices. When all configuration files have been modified or created, networking must be restarted for the configuration changes to take @@ -544,7 +645,7 @@ effect. This can be accomplished via the following: Note that the network control script (/sbin/ifdown) will remove the bonding module as part of the network shutdown processing, so it is not necessary to remove the module by hand if, e.g., the -module paramters have changed. +module parameters have changed. Also, at this writing, YaST/YaST2 will not manage bonding devices (they do not show bonding interfaces on its list of network @@ -559,12 +660,37 @@ format can be found in an example ifcfg template file: Note that the template does not document the various BONDING_ settings described above, but does describe many of the other options. +3.1.1 Using DHCP with sysconfig +------------------------------- + + Under sysconfig, configuring a device with BOOTPROTO='dhcp' +will cause it to query DHCP for its IP address information. At this +writing, this does not function for bonding devices; the scripts +attempt to obtain the device address from DHCP prior to adding any of +the slave devices. Without active slaves, the DHCP requests are not +sent to the network. + +3.1.2 Configuring Multiple Bonds with sysconfig +----------------------------------------------- + + The sysconfig network initialization system is capable of +handling multiple bonding devices. All that is necessary is for each +bonding instance to have an appropriately configured ifcfg-bondX file +(as described above). Do not specify the "max_bonds" parameter to any +instance of bonding, as this will confuse sysconfig. If you require +multiple bonding devices with identical parameters, create multiple +ifcfg-bondX files. + + Because the sysconfig scripts supply the bonding module +options in the ifcfg-bondX file, it is not necessary to add them to +the system /etc/modules.conf or /etc/modprobe.conf configuration file. + 3.2 Configuration with initscripts support ------------------------------------------ This section applies to distros using a version of initscripts with bonding support, for example, Red Hat Linux 9 or Red Hat -Enterprise Linux version 3. On these systems, the network +Enterprise Linux version 3 or 4. On these systems, the network initialization scripts have some knowledge of bonding, and can be configured to control bonding devices. @@ -614,10 +740,11 @@ USERCTL=no Be sure to change the networking specific lines (IPADDR, NETMASK, NETWORK and BROADCAST) to match your network configuration. - Finally, it is necessary to edit /etc/modules.conf to load the -bonding module when the bond0 interface is brought up. The following -sample lines in /etc/modules.conf will load the bonding module, and -select its options: + Finally, it is necessary to edit /etc/modules.conf (or +/etc/modprobe.conf, depending upon your distro) to load the bonding +module with your desired options when the bond0 interface is brought +up. The following lines in /etc/modules.conf (or modprobe.conf) will +load the bonding module, and select its options: alias bond0 bonding options bond0 mode=balance-alb miimon=100 @@ -629,6 +756,33 @@ options for your configuration. will restart the networking subsystem and your bond link should be now up and running. +3.2.1 Using DHCP with initscripts +--------------------------------- + + Recent versions of initscripts (the version supplied with +Fedora Core 3 and Red Hat Enterprise Linux 4 is reported to work) do +have support for assigning IP information to bonding devices via DHCP. + + To configure bonding for DHCP, configure it as described +above, except replace the line "BOOTPROTO=none" with "BOOTPROTO=dhcp" +and add a line consisting of "TYPE=Bonding". Note that the TYPE value +is case sensitive. + +3.2.2 Configuring Multiple Bonds with initscripts +------------------------------------------------- + + At this writing, the initscripts package does not directly +support loading the bonding driver multiple times, so the process for +doing so is the same as described in the "Configuring Multiple Bonds +Manually" section, below. + + NOTE: It has been observed that some Red Hat supplied kernels +are apparently unable to rename modules at load time (the "-obonding1" +part). Attempts to pass that option to modprobe will produce an +"Operation not permitted" error. This has been reported on some +Fedora Core kernels, and has been seen on RHEL 4 as well. On kernels +exhibiting this problem, it will be impossible to configure multiple +bonds with differing parameters. 3.3 Configuring Bonding Manually -------------------------------- @@ -638,10 +792,11 @@ scripts (the sysconfig or initscripts package) do not have specific knowledge of bonding. One such distro is SuSE Linux Enterprise Server version 8. - The general methodology for these systems is to place the -bonding module parameters into /etc/modprobe.conf, then add modprobe -and/or ifenslave commands to the system's global init script. The -name of the global init script differs; for sysconfig, it is + The general method for these systems is to place the bonding +module parameters into /etc/modules.conf or /etc/modprobe.conf (as +appropriate for the installed distro), then add modprobe and/or +ifenslave commands to the system's global init script. The name of +the global init script differs; for sysconfig, it is /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local. For example, if you wanted to make a simple bond of two e100 @@ -649,7 +804,7 @@ devices (presumed to be eth0 and eth1), and have it persist across reboots, edit the appropriate file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the following: -modprobe bonding -obond0 mode=balance-alb miimon=100 +modprobe bonding mode=balance-alb miimon=100 modprobe e100 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up ifenslave bond0 eth0 @@ -657,11 +812,7 @@ ifenslave bond0 eth1 Replace the example bonding module parameters and bond0 network configuration (IP address, netmask, etc) with the appropriate -values for your configuration. The above example loads the bonding -module with the name "bond0," this simplifies the naming if multiple -bonding modules are loaded (each successive instance of the module is -given a different name, and the module instance names match the -bonding interface names). +values for your configuration. Unfortunately, this method will not provide support for the ifup and ifdown scripts on the bond devices. To reload the bonding @@ -684,20 +835,23 @@ appropriate device driver modules. For our example above, you can do the following: # ifconfig bond0 down -# rmmod bond0 +# rmmod bonding # rmmod e100 Again, for convenience, it may be desirable to create a script with these commands. -3.4 Configuring Multiple Bonds ------------------------------- +3.3.1 Configuring Multiple Bonds Manually +----------------------------------------- This section contains information on configuring multiple -bonding devices with differing options. If you require multiple -bonding devices, but all with the same options, see the "max_bonds" -module paramter, documented above. +bonding devices with differing options for those systems whose network +initialization scripts lack support for configuring multiple bonds. + + If you require multiple bonding devices, but all with the same +options, you may wish to use the "max_bonds" module parameter, +documented above. To create multiple bonding devices with differing options, it is necessary to load the bonding driver multiple times. Note that @@ -724,11 +878,16 @@ named "bond0" and creates the bond0 device in balance-rr mode with an miimon of 100. The second instance is named "bond1" and creates the bond1 device in balance-alb mode with an miimon of 50. + In some circumstances (typically with older distributions), +the above does not work, and the second bonding instance never sees +its options. In that case, the second options line can be substituted +as follows: + +install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50 + This may be repeated any number of times, specifying a new and -unique name in place of bond0 or bond1 for each instance. +unique name in place of bond1 for each subsequent instance. - When the appropriate module paramters are in place, then -configure bonding according to the instructions for your distro. 5. Querying Bonding Configuration ================================= @@ -846,8 +1005,8 @@ tagged internally by bonding itself. As a result, bonding must self generated packets. For reasons of simplicity, and to support the use of adapters -that can do VLAN hardware acceleration offloding, the bonding -interface declares itself as fully hardware offloaing capable, it gets +that can do VLAN hardware acceleration offloading, the bonding +interface declares itself as fully hardware offloading capable, it gets the add_vid/kill_vid notifications to gather the necessary information, and it propagates those actions to the slaves. In case of mixed adapter types, hardware accelerated tagged packets that @@ -880,7 +1039,7 @@ bond interface: matches the hardware address of the VLAN interfaces. Note that changing a VLAN interface's HW address would set the -underlying device -- i.e. the bonding interface -- to promiscouos +underlying device -- i.e. the bonding interface -- to promiscuous mode, which might not be what you want. @@ -923,7 +1082,7 @@ down or have a problem making it unresponsive to ARP requests. Having an additional target (or several) increases the reliability of the ARP monitoring. - Multiple ARP targets must be seperated by commas as follows: + Multiple ARP targets must be separated by commas as follows: # example options for ARP monitoring with three targets alias bond0 bonding @@ -1045,7 +1204,7 @@ install bonding /sbin/modprobe tg3; /sbin/modprobe e1000; This will, when loading the bonding module, rather than performing the normal action, instead execute the provided command. This command loads the device drivers in the order needed, then calls -modprobe with --ingore-install to cause the normal action to then take +modprobe with --ignore-install to cause the normal action to then take place. Full documentation on this can be found in the modprobe.conf and modprobe manual pages. @@ -1130,14 +1289,14 @@ association. common to enable promiscuous mode on the device, so that all traffic is seen (instead of seeing only traffic destined for the local host). The bonding driver handles promiscuous mode changes to the bonding -master device (e.g., bond0), and propogates the setting to the slave +master device (e.g., bond0), and propagates the setting to the slave devices. For the balance-rr, balance-xor, broadcast, and 802.3ad modes, -the promiscuous mode setting is propogated to all slaves. +the promiscuous mode setting is propagated to all slaves. For the active-backup, balance-tlb and balance-alb modes, the -promiscuous mode setting is propogated only to the active slave. +promiscuous mode setting is propagated only to the active slave. For balance-tlb mode, the active slave is the slave currently receiving inbound traffic. @@ -1148,46 +1307,182 @@ sending to peers that are unassigned or if the load is unbalanced. For the active-backup, balance-tlb and balance-alb modes, when the active slave changes (e.g., due to a link failure), the -promiscuous setting will be propogated to the new active slave. +promiscuous setting will be propagated to the new active slave. -12. High Availability Information -================================= +12. Configuring Bonding for High Availability +============================================= High Availability refers to configurations that provide maximum network availability by having redundant or backup devices, -links and switches between the host and the rest of the world. - - There are currently two basic methods for configuring to -maximize availability. They are dependent on the network topology and -the primary goal of the configuration, but in general, a configuration -can be optimized for maximum available bandwidth, or for maximum -network availability. +links or switches between the host and the rest of the world. The +goal is to provide the maximum availability of network connectivity +(i.e., the network always works), even though other configurations +could provide higher throughput. 12.1 High Availability in a Single Switch Topology -------------------------------------------------- - If two hosts (or a host and a switch) are directly connected -via multiple physical links, then there is no network availability -penalty for optimizing for maximum bandwidth: there is only one switch -(or peer), so if it fails, you have no alternative access to fail over -to. + If two hosts (or a host and a single switch) are directly +connected via multiple physical links, then there is no availability +penalty to optimizing for maximum bandwidth. In this case, there is +only one switch (or peer), so if it fails, there is no alternative +access to fail over to. Additionally, the bonding load balance modes +support link monitoring of their members, so if individual links fail, +the load will be rebalanced across the remaining devices. + + See Section 13, "Configuring Bonding for Maximum Throughput" +for information on configuring bonding with one peer device. + +12.2 High Availability in a Multiple Switch Topology +---------------------------------------------------- + + With multiple switches, the configuration of bonding and the +network changes dramatically. In multiple switch topologies, there is +a trade off between network availability and usable bandwidth. + + Below is a sample network, configured to maximize the +availability of the network: -Example 1 : host to switch (or other host) + | | + |port3 port3| + +-----+----+ +-----+----+ + | |port2 ISL port2| | + | switch A +--------------------------+ switch B | + | | | | + +-----+----+ +-----++---+ + |port1 port1| + | +-------+ | + +-------------+ host1 +---------------+ + eth0 +-------+ eth1 - +----------+ +----------+ - | |eth0 eth0| switch | - | Host A +--------------------------+ or | - | +--------------------------+ other | - | |eth1 eth1| host | - +----------+ +----------+ + In this configuration, there is a link between the two +switches (ISL, or inter switch link), and multiple ports connecting to +the outside world ("port3" on each switch). There is no technical +reason that this could not be extended to a third switch. +12.2.1 HA Bonding Mode Selection for Multiple Switch Topology +------------------------------------------------------------- -12.1.1 Bonding Mode Selection for single switch topology --------------------------------------------------------- + In a topology such as the example above, the active-backup and +broadcast modes are the only useful bonding modes when optimizing for +availability; the other modes require all links to terminate on the +same peer for them to behave rationally. + +active-backup: This is generally the preferred mode, particularly if + the switches have an ISL and play together well. If the + network configuration is such that one switch is specifically + a backup switch (e.g., has lower capacity, higher cost, etc), + then the primary option can be used to insure that the + preferred link is always used when it is available. + +broadcast: This mode is really a special purpose mode, and is suitable + only for very specific needs. For example, if the two + switches are not connected (no ISL), and the networks beyond + them are totally independent. In this case, if it is + necessary for some specific one-way traffic to reach both + independent networks, then the broadcast mode may be suitable. + +12.2.2 HA Link Monitoring Selection for Multiple Switch Topology +---------------------------------------------------------------- + + The choice of link monitoring ultimately depends upon your +switch. If the switch can reliably fail ports in response to other +failures, then either the MII or ARP monitors should work. For +example, in the above example, if the "port3" link fails at the remote +end, the MII monitor has no direct means to detect this. The ARP +monitor could be configured with a target at the remote end of port3, +thus detecting that failure without switch support. + + In general, however, in a multiple switch topology, the ARP +monitor can provide a higher level of reliability in detecting end to +end connectivity failures (which may be caused by the failure of any +individual component to pass traffic for any reason). Additionally, +the ARP monitor should be configured with multiple targets (at least +one for each switch in the network). This will insure that, +regardless of which switch is active, the ARP monitor has a suitable +target to query. + + +13. Configuring Bonding for Maximum Throughput +============================================== + +13.1 Maximizing Throughput in a Single Switch Topology +------------------------------------------------------ + + In a single switch configuration, the best method to maximize +throughput depends upon the application and network environment. The +various load balancing modes each have strengths and weaknesses in +different environments, as detailed below. + + For this discussion, we will break down the topologies into +two categories. Depending upon the destination of most traffic, we +categorize them into either "gatewayed" or "local" configurations. + + In a gatewayed configuration, the "switch" is acting primarily +as a router, and the majority of traffic passes through this router to +other networks. An example would be the following: + + + +----------+ +----------+ + | |eth0 port1| | to other networks + | Host A +---------------------+ router +-------------------> + | +---------------------+ | Hosts B and C are out + | |eth1 port2| | here somewhere + +----------+ +----------+ + + The router may be a dedicated router device, or another host +acting as a gateway. For our discussion, the important point is that +the majority of traffic from Host A will pass through the router to +some other network before reaching its final destination. + + In a gatewayed network configuration, although Host A may +communicate with many other systems, all of its traffic will be sent +and received via one other peer on the local network, the router. + + Note that the case of two systems connected directly via +multiple physical links is, for purposes of configuring bonding, the +same as a gatewayed configuration. In that case, it happens that all +traffic is destined for the "gateway" itself, not some other network +beyond the gateway. + + In a local configuration, the "switch" is acting primarily as +a switch, and the majority of traffic passes through this switch to +reach other stations on the same network. An example would be the +following: + + +----------+ +----------+ +--------+ + | |eth0 port1| +-------+ Host B | + | Host A +------------+ switch |port3 +--------+ + | +------------+ | +--------+ + | |eth1 port2| +------------------+ Host C | + +----------+ +----------+port4 +--------+ + + + Again, the switch may be a dedicated switch device, or another +host acting as a gateway. For our discussion, the important point is +that the majority of traffic from Host A is destined for other hosts +on the same local network (Hosts B and C in the above example). + + In summary, in a gatewayed configuration, traffic to and from +the bonded device will be to the same MAC level peer on the network +(the gateway itself, i.e., the router), regardless of its final +destination. In a local configuration, traffic flows directly to and +from the final destinations, thus, each destination (Host B, Host C) +will be addressed directly by their individual MAC addresses. + + This distinction between a gatewayed and a local network +configuration is important because many of the load balancing modes +available use the MAC addresses of the local network source and +destination to make load balancing decisions. The behavior of each +mode is described below. + + +13.1.1 MT Bonding Mode Selection for Single Switch Topology +----------------------------------------------------------- This configuration is the easiest to set up and to understand, although you will have to decide which bonding mode best suits your -needs. The tradeoffs for each mode are detailed below: +needs. The trade offs for each mode are detailed below: balance-rr: This mode is the only mode that will permit a single TCP/IP connection to stripe traffic across multiple @@ -1206,6 +1501,23 @@ balance-rr: This mode is the only mode that will permit a single interface's worth of throughput, even after adjusting tcp_reordering. + Note that this out of order delivery occurs when both the + sending and receiving systems are utilizing a multiple + interface bond. Consider a configuration in which a + balance-rr bond feeds into a single higher capacity network + channel (e.g., multiple 100Mb/sec ethernets feeding a single + gigabit ethernet via an etherchannel capable switch). In this + configuration, traffic sent from the multiple 100Mb devices to + a destination connected to the gigabit device will not see + packets out of order. However, traffic sent from the gigabit + device to the multiple 100Mb devices may or may not see + traffic out of order, depending upon the balance policy of the + switch. Many switches do not support any modes that stripe + traffic (instead choosing a port based upon IP or MAC level + addresses); for those devices, traffic flowing from the + gigabit device to the many 100Mb devices will only utilize one + interface. + If you are utilizing protocols other than TCP/IP, UDP for example, and your application can tolerate out of order delivery, then this mode can allow for single stream datagram @@ -1220,16 +1532,21 @@ active-backup: There is not much advantage in this network topology to connected to the same peer as the primary. In this case, a load balancing mode (with link monitoring) will provide the same level of network availability, but with increased - available bandwidth. On the plus side, it does not require - any configuration of the switch. + available bandwidth. On the plus side, active-backup mode + does not require any configuration of the switch, so it may + have value if the hardware available does not support any of + the load balance modes. balance-xor: This mode will limit traffic such that packets destined for specific peers will always be sent over the same interface. Since the destination is determined by the MAC - addresses involved, this may be desirable if you have a large - network with many hosts. It is likely to be suboptimal if all - your traffic is passed through a single router, however. As - with balance-rr, the switch ports need to be configured for + addresses involved, this mode works best in a "local" network + configuration (as described above), with destinations all on + the same local network. This mode is likely to be suboptimal + if all your traffic is passed through a single router (i.e., a + "gatewayed" network configuration, as described above). + + As with balance-rr, the switch ports need to be configured for "etherchannel" or "trunking." broadcast: Like active-backup, there is not much advantage to this @@ -1241,122 +1558,131 @@ broadcast: Like active-backup, there is not much advantage to this protocol includes automatic configuration of the aggregates, so minimal manual configuration of the switch is needed (typically only to designate that some set of devices is - usable for 802.3ad). The 802.3ad standard also mandates that - frames be delivered in order (within certain limits), so in - general single connections will not see misordering of + available for 802.3ad). The 802.3ad standard also mandates + that frames be delivered in order (within certain limits), so + in general single connections will not see misordering of packets. The 802.3ad mode does have some drawbacks: the standard mandates that all devices in the aggregate operate at the same speed and duplex. Also, as with all bonding load balance modes other than balance-rr, no single connection will be able to utilize more than a single interface's worth of - bandwidth. Additionally, the linux bonding 802.3ad - implementation distributes traffic by peer (using an XOR of - MAC addresses), so in general all traffic to a particular - destination will use the same interface. Finally, the 802.3ad - mode mandates the use of the MII monitor, therefore, the ARP - monitor is not available in this mode. - -balance-tlb: This mode is also a good choice for this type of - topology. It has no special switch configuration - requirements, and balances outgoing traffic by peer, in a - vaguely intelligent manner (not a simple XOR as in balance-xor - or 802.3ad mode), so that unlucky MAC addresses will not all - "bunch up" on a single interface. Interfaces may be of - differing speeds. On the down side, in this mode all incoming - traffic arrives over a single interface, this mode requires - certain ethtool support in the network device driver of the - slave interfaces, and the ARP monitor is not available. - -balance-alb: This mode is everything that balance-tlb is, and more. It - has all of the features (and restrictions) of balance-tlb, and - will also balance incoming traffic from peers (as described in - the Bonding Module Options section, above). The only extra - down side to this mode is that the network device driver must - support changing the hardware address while the device is - open. - -12.1.2 Link Monitoring for Single Switch Topology -------------------------------------------------- + bandwidth. + + Additionally, the linux bonding 802.3ad implementation + distributes traffic by peer (using an XOR of MAC addresses), + so in a "gatewayed" configuration, all outgoing traffic will + generally use the same device. Incoming traffic may also end + up on a single device, but that is dependent upon the + balancing policy of the peer's 8023.ad implementation. In a + "local" configuration, traffic will be distributed across the + devices in the bond. + + Finally, the 802.3ad mode mandates the use of the MII monitor, + therefore, the ARP monitor is not available in this mode. + +balance-tlb: The balance-tlb mode balances outgoing traffic by peer. + Since the balancing is done according to MAC address, in a + "gatewayed" configuration (as described above), this mode will + send all traffic across a single device. However, in a + "local" network configuration, this mode balances multiple + local network peers across devices in a vaguely intelligent + manner (not a simple XOR as in balance-xor or 802.3ad mode), + so that mathematically unlucky MAC addresses (i.e., ones that + XOR to the same value) will not all "bunch up" on a single + interface. + + Unlike 802.3ad, interfaces may be of differing speeds, and no + special switch configuration is required. On the down side, + in this mode all incoming traffic arrives over a single + interface, this mode requires certain ethtool support in the + network device driver of the slave interfaces, and the ARP + monitor is not available. + +balance-alb: This mode is everything that balance-tlb is, and more. + It has all of the features (and restrictions) of balance-tlb, + and will also balance incoming traffic from local network + peers (as described in the Bonding Module Options section, + above). + + The only additional down side to this mode is that the network + device driver must support changing the hardware address while + the device is open. + +13.1.2 MT Link Monitoring for Single Switch Topology +---------------------------------------------------- The choice of link monitoring may largely depend upon which mode you choose to use. The more advanced load balancing modes do not support the use of the ARP monitor, and are thus restricted to using -the MII monitor (which does not provide as high a level of assurance -as the ARP monitor). - - -12.2 High Availability in a Multiple Switch Topology ----------------------------------------------------- - - With multiple switches, the configuration of bonding and the -network changes dramatically. In multiple switch topologies, there is -a tradeoff between network availability and usable bandwidth. - - Below is a sample network, configured to maximize the -availability of the network: - - | | - |port3 port3| - +-----+----+ +-----+----+ - | |port2 ISL port2| | - | switch A +--------------------------+ switch B | - | | | | - +-----+----+ +-----++---+ - |port1 port1| - | +-------+ | - +-------------+ host1 +---------------+ - eth0 +-------+ eth1 - - In this configuration, there is a link between the two -switches (ISL, or inter switch link), and multiple ports connecting to -the outside world ("port3" on each switch). There is no technical -reason that this could not be extended to a third switch. - -12.2.1 Bonding Mode Selection for Multiple Switch Topology ----------------------------------------------------------- - - In a topology such as this, the active-backup and broadcast -modes are the only useful bonding modes; the other modes require all -links to terminate on the same peer for them to behave rationally. - -active-backup: This is generally the preferred mode, particularly if - the switches have an ISL and play together well. If the - network configuration is such that one switch is specifically - a backup switch (e.g., has lower capacity, higher cost, etc), - then the primary option can be used to insure that the - preferred link is always used when it is available. - -broadcast: This mode is really a special purpose mode, and is suitable - only for very specific needs. For example, if the two - switches are not connected (no ISL), and the networks beyond - them are totally independant. In this case, if it is - necessary for some specific one-way traffic to reach both - independent networks, then the broadcast mode may be suitable. - -12.2.2 Link Monitoring Selection for Multiple Switch Topology +the MII monitor (which does not provide as high a level of end to end +assurance as the ARP monitor). + +13.2 Maximum Throughput in a Multiple Switch Topology +----------------------------------------------------- + + Multiple switches may be utilized to optimize for throughput +when they are configured in parallel as part of an isolated network +between two or more systems, for example: + + +-----------+ + | Host A | + +-+---+---+-+ + | | | + +--------+ | +---------+ + | | | + +------+---+ +-----+----+ +-----+----+ + | Switch A | | Switch B | | Switch C | + +------+---+ +-----+----+ +-----+----+ + | | | + +--------+ | +---------+ + | | | + +-+---+---+-+ + | Host B | + +-----------+ + + In this configuration, the switches are isolated from one +another. One reason to employ a topology such as this is for an +isolated network with many hosts (a cluster configured for high +performance, for example), using multiple smaller switches can be more +cost effective than a single larger switch, e.g., on a network with 24 +hosts, three 24 port switches can be significantly less expensive than +a single 72 port switch. + + If access beyond the network is required, an individual host +can be equipped with an additional network device connected to an +external network; this host then additionally acts as a gateway. + +13.2.1 MT Bonding Mode Selection for Multiple Switch Topology ------------------------------------------------------------- - The choice of link monitoring ultimately depends upon your -switch. If the switch can reliably fail ports in response to other -failures, then either the MII or ARP monitors should work. For -example, in the above example, if the "port3" link fails at the remote -end, the MII monitor has no direct means to detect this. The ARP -monitor could be configured with a target at the remote end of port3, -thus detecting that failure without switch support. + In actual practice, the bonding mode typically employed in +configurations of this type is balance-rr. Historically, in this +network configuration, the usual caveats about out of order packet +delivery are mitigated by the use of network adapters that do not do +any kind of packet coalescing (via the use of NAPI, or because the +device itself does not generate interrupts until some number of +packets has arrived). When employed in this fashion, the balance-rr +mode allows individual connections between two hosts to effectively +utilize greater than one interface's bandwidth. - In general, however, in a multiple switch topology, the ARP -monitor can provide a higher level of reliability in detecting link -failures. Additionally, it should be configured with multiple targets -(at least one for each switch in the network). This will insure that, -regardless of which switch is active, the ARP monitor has a suitable -target to query. +13.2.2 MT Link Monitoring for Multiple Switch Topology +------------------------------------------------------ + Again, in actual practice, the MII monitor is most often used +in this configuration, as performance is given preference over +availability. The ARP monitor will function in this topology, but its +advantages over the MII monitor are mitigated by the volume of probes +needed as the number of systems involved grows (remember that each +host in the network is configured with bonding). -12.3 Switch Behavior Issues for High Availability -------------------------------------------------- +14. Switch Behavior Issues +========================== - You may encounter issues with the timing of link up and down -reporting by the switch. +14.1 Link Establishment and Failover Delays +------------------------------------------- + + Some switches exhibit undesirable behavior with regard to the +timing of link up and down reporting by the switch. First, when a link comes up, some switches may indicate that the link is up (carrier available), but not pass traffic over the @@ -1370,30 +1696,70 @@ relevant interface(s). Second, some switches may "bounce" the link state one or more times while a link is changing state. This occurs most commonly while the switch is initializing. Again, an appropriate updelay value may -help, but note that if all links are down, then updelay is ignored -when any link becomes active (the slave closest to completing its -updelay is chosen). +help. Note that when a bonding interface has no active links, the -driver will immediately reuse the first link that goes up, even if -updelay parameter was specified. If there are slave interfaces -waiting for the updelay timeout to expire, the interface that first -went into that state will be immediately reused. This reduces down -time of the network if the value of updelay has been overestimated. +driver will immediately reuse the first link that goes up, even if the +updelay parameter has been specified (the updelay is ignored in this +case). If there are slave interfaces waiting for the updelay timeout +to expire, the interface that first went into that state will be +immediately reused. This reduces down time of the network if the +value of updelay has been overestimated, and since this occurs only in +cases with no connectivity, there is no additional penalty for +ignoring the updelay. In addition to the concerns about switch timings, if your switches take a long time to go into backup mode, it may be desirable to not activate a backup interface immediately after a link goes down. Failover may be delayed via the downdelay bonding module option. -13. Hardware Specific Considerations +14.2 Duplicated Incoming Packets +-------------------------------- + + It is not uncommon to observe a short burst of duplicated +traffic when the bonding device is first used, or after it has been +idle for some period of time. This is most easily observed by issuing +a "ping" to some other host on the network, and noticing that the +output from ping flags duplicates (typically one per slave). + + For example, on a bond in active-backup mode with five slaves +all connected to one switch, the output may appear as follows: + +# ping -n 10.0.4.2 +PING 10.0.4.2 (10.0.4.2) from 10.0.3.10 : 56(84) bytes of data. +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.7 ms +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=2 ttl=64 time=0.216 ms +64 bytes from 10.0.4.2: icmp_seq=3 ttl=64 time=0.267 ms +64 bytes from 10.0.4.2: icmp_seq=4 ttl=64 time=0.222 ms + + This is not due to an error in the bonding driver, rather, it +is a side effect of how many switches update their MAC forwarding +tables. Initially, the switch does not associate the MAC address in +the packet with a particular switch port, and so it may send the +traffic to all ports until its MAC forwarding table is updated. Since +the interfaces attached to the bond may occupy multiple ports on a +single switch, when the switch (temporarily) floods the traffic to all +ports, the bond device receives multiple copies of the same packet +(one per slave device). + + The duplicated packet behavior is switch dependent, some +switches exhibit this, and some do not. On switches that display this +behavior, it can be induced by clearing the MAC forwarding table (on +most Cisco switches, the privileged command "clear mac address-table +dynamic" will accomplish this). + +15. Hardware Specific Considerations ==================================== This section contains additional information for configuring bonding on specific hardware platforms, or for interfacing bonding with particular switches or other devices. -13.1 IBM BladeCenter +15.1 IBM BladeCenter -------------------- This applies to the JS20 and similar systems. @@ -1407,12 +1773,12 @@ JS20 network adapter information -------------------------------- All JS20s come with two Broadcom Gigabit Ethernet ports -integrated on the planar. In the BladeCenter chassis, the eth0 port -of all JS20 blades is hard wired to I/O Module #1; similarly, all eth1 -ports are wired to I/O Module #2. An add-on Broadcom daughter card -can be installed on a JS20 to provide two more Gigabit Ethernet ports. -These ports, eth2 and eth3, are wired to I/O Modules 3 and 4, -respectively. +integrated on the planar (that's "motherboard" in IBM-speak). In the +BladeCenter chassis, the eth0 port of all JS20 blades is hard wired to +I/O Module #1; similarly, all eth1 ports are wired to I/O Module #2. +An add-on Broadcom daughter card can be installed on a JS20 to provide +two more Gigabit Ethernet ports. These ports, eth2 and eth3, are +wired to I/O Modules 3 and 4, respectively. Each I/O Module may contain either a switch or a passthrough module (which allows ports to be directly connected to an external @@ -1432,29 +1798,30 @@ BladeCenter networking configuration of ways, this discussion will be confined to describing basic configurations. - Normally, Ethernet Switch Modules (ESM) are used in I/O + Normally, Ethernet Switch Modules (ESMs) are used in I/O modules 1 and 2. In this configuration, the eth0 and eth1 ports of a JS20 will be connected to different internal switches (in the respective I/O modules). - An optical passthru module (OPM) connects the I/O module -directly to an external switch. By using OPMs in I/O module #1 and -#2, the eth0 and eth1 interfaces of a JS20 can be redirected to the -outside world and connected to a common external switch. - - Depending upon the mix of ESM and OPM modules, the network -will appear to bonding as either a single switch topology (all OPM -modules) or as a multiple switch topology (one or more ESM modules, -zero or more OPM modules). It is also possible to connect ESM modules -together, resulting in a configuration much like the example in "High -Availability in a multiple switch topology." - -Requirements for specifc modes ------------------------------- - - The balance-rr mode requires the use of OPM modules for -devices in the bond, all connected to an common external switch. That -switch must be configured for "etherchannel" or "trunking" on the + A passthrough module (OPM or CPM, optical or copper, +passthrough module) connects the I/O module directly to an external +switch. By using PMs in I/O module #1 and #2, the eth0 and eth1 +interfaces of a JS20 can be redirected to the outside world and +connected to a common external switch. + + Depending upon the mix of ESMs and PMs, the network will +appear to bonding as either a single switch topology (all PMs) or as a +multiple switch topology (one or more ESMs, zero or more PMs). It is +also possible to connect ESMs together, resulting in a configuration +much like the example in "High Availability in a Multiple Switch +Topology," above. + +Requirements for specific modes +------------------------------- + + The balance-rr mode requires the use of passthrough modules +for devices in the bond, all connected to an common external switch. +That switch must be configured for "etherchannel" or "trunking" on the appropriate ports, as is usual for balance-rr. The balance-alb and balance-tlb modes will function with @@ -1484,17 +1851,18 @@ connected to the JS20 system. Other concerns -------------- - The Serial Over LAN link is established over the primary + The Serial Over LAN (SoL) link is established over the primary ethernet (eth0) only, therefore, any loss of link to eth0 will result in losing your SoL connection. It will not fail over with other -network traffic. +network traffic, as the SoL system is beyond the control of the +bonding driver. It may be desirable to disable spanning tree on the switch (either the internal Ethernet Switch Module, or an external switch) to -avoid fail-over delays issues when using bonding. +avoid fail-over delay issues when using bonding. -14. Frequently Asked Questions +16. Frequently Asked Questions ============================== 1. Is it SMP safe? @@ -1505,8 +1873,8 @@ The new driver was designed to be SMP safe from the start. 2. What type of cards will work with it? Any Ethernet type cards (you can even mix cards - a Intel -EtherExpress PRO/100 and a 3com 3c905b, for example). They need not -be of the same speed. +EtherExpress PRO/100 and a 3com 3c905b, for example). For most modes, +devices need not be of the same speed. 3. How many bonding devices can I have? @@ -1524,11 +1892,12 @@ system. disabled. The active-backup mode will fail over to a backup link, and other modes will ignore the failed link. The link will continue to be monitored, and should it recover, it will rejoin the bond (in whatever -manner is appropriate for the mode). See the section on High -Availability for additional information. +manner is appropriate for the mode). See the sections on High +Availability and the documentation for each mode for additional +information. Link monitoring can be enabled via either the miimon or -arp_interval paramters (described in the module paramters section, +arp_interval parameters (described in the module parameters section, above). In general, miimon monitors the carrier state as sensed by the underlying network device, and the arp monitor (arp_interval) monitors connectivity to another host on the local network. @@ -1536,7 +1905,7 @@ monitors connectivity to another host on the local network. If no link monitoring is configured, the bonding driver will be unable to detect link failures, and will assume that all links are always available. This will likely result in lost packets, and a -resulting degredation of performance. The precise performance loss +resulting degradation of performance. The precise performance loss depends upon the bonding mode and network configuration. 6. Can bonding be used for High Availability? @@ -1550,12 +1919,12 @@ depends upon the bonding mode and network configuration. In the basic balance modes (balance-rr and balance-xor), it works with any system that supports etherchannel (also called trunking). Most managed switches currently available have such -support, and many unmananged switches as well. +support, and many unmanaged switches as well. The advanced balance modes (balance-tlb and balance-alb) do not have special switch requirements, but do need device drivers that support specific features (described in the appropriate section under -module paramters, above). +module parameters, above). In 802.3ad mode, it works with with systems that support IEEE 802.3ad Dynamic Link Aggregation. Most managed and many unmanaged @@ -1565,17 +1934,19 @@ switches currently available support 802.3ad. 8. Where does a bonding device get its MAC address from? - If not explicitly configured with ifconfig, the MAC address of -the bonding device is taken from its first slave device. This MAC -address is then passed to all following slaves and remains persistent -(even if the the first slave is removed) until the bonding device is -brought down or reconfigured. + If not explicitly configured (with ifconfig or ip link), the +MAC address of the bonding device is taken from its first slave +device. This MAC address is then passed to all following slaves and +remains persistent (even if the the first slave is removed) until the +bonding device is brought down or reconfigured. If you wish to change the MAC address, you can set it with -ifconfig: +ifconfig or ip link: # ifconfig bond0 hw ether 00:11:22:33:44:55 +# ip link set bond0 address 66:77:88:99:aa:bb + The MAC address can be also changed by bringing down/up the device and then changing its slaves (or their order): @@ -1591,23 +1962,28 @@ from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then restore the MAC addresses that the slaves had before they were enslaved. -15. Resources and Links +16. Resources and Links ======================= The latest version of the bonding driver can be found in the latest version of the linux kernel, found on http://kernel.org +The latest version of this document can be found in either the latest +kernel source (named Documentation/networking/bonding.txt), or on the +bonding sourceforge site: + +http://www.sourceforge.net/projects/bonding + Discussions regarding the bonding driver take place primarily on the bonding-devel mailing list, hosted at sourceforge.net. If you have -questions or problems, post them to the list. +questions or problems, post them to the list. The list address is: bonding-devel@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/bonding-devel - -There is also a project site on sourceforge. + The administrative interface (to subscribe or unsubscribe) can +be found at: -http://www.sourceforge.net/projects/bonding +https://lists.sourceforge.net/lists/listinfo/bonding-devel Donald Becker's Ethernet Drivers and diag programs may be found at : - http://www.scyld.com/network/ diff --git a/Documentation/stable_api_nonsense.txt b/Documentation/stable_api_nonsense.txt index 3cea13875277..f39c9d714db3 100644 --- a/Documentation/stable_api_nonsense.txt +++ b/Documentation/stable_api_nonsense.txt @@ -132,7 +132,7 @@ to extra work for the USB developers. Since all Linux USB developers do their work on their own time, asking programmers to do extra work for no gain, for free, is not a possibility. -Security issues are also a very important for Linux. When a +Security issues are also very important for Linux. When a security issue is found, it is fixed in a very short amount of time. A number of times this has caused internal kernel interfaces to be reworked to prevent the security problem from occurring. When this diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt new file mode 100644 index 000000000000..2c81305090df --- /dev/null +++ b/Documentation/stable_kernel_rules.txt @@ -0,0 +1,58 @@ +Everything you ever wanted to know about Linux 2.6 -stable releases. + +Rules on what kind of patches are accepted, and what ones are not, into +the "-stable" tree: + + - It must be obviously correct and tested. + - It can not bigger than 100 lines, with context. + - It must fix only one thing. + - It must fix a real bug that bothers people (not a, "This could be a + problem..." type thing.) + - It must fix a problem that causes a build error (but not for things + marked CONFIG_BROKEN), an oops, a hang, data corruption, a real + security issue, or some "oh, that's not good" issue. In short, + something critical. + - No "theoretical race condition" issues, unless an explanation of how + the race can be exploited. + - It can not contain any "trivial" fixes in it (spelling changes, + whitespace cleanups, etc.) + - It must be accepted by the relevant subsystem maintainer. + - It must follow Documentation/SubmittingPatches rules. + + +Procedure for submitting patches to the -stable tree: + + - Send the patch, after verifying that it follows the above rules, to + stable@kernel.org. + - The sender will receive an ack when the patch has been accepted into + the queue, or a nak if the patch is rejected. This response might + take a few days, according to the developer's schedules. + - If accepted, the patch will be added to the -stable queue, for review + by other developers. + - Security patches should not be sent to this alias, but instead to the + documented security@kernel.org. + + +Review cycle: + + - When the -stable maintainers decide for a review cycle, the patches + will be sent to the review committee, and the maintainer of the + affected area of the patch (unless the submitter is the maintainer of + the area) and CC: to the linux-kernel mailing list. + - The review committee has 48 hours in which to ack or nak the patch. + - If the patch is rejected by a member of the committee, or linux-kernel + members object to the patch, bringing up issues that the maintainers + and members did not realize, the patch will be dropped from the + queue. + - At the end of the review cycle, the acked patches will be added to + the latest -stable release, and a new -stable release will happen. + - Security patches will be accepted into the -stable tree directly from + the security kernel team, and not go through the normal review cycle. + Contact the kernel security team for more details on this procedure. + + +Review committe: + + - This will be made up of a number of kernel developers who have + volunteered for this task, and a few that haven't. + diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 6d44958289de..03deb0726aa4 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -29,3 +29,4 @@ card=27 - PixelView PlayTV Ultra Pro (Stereo) card=28 - DViCO FusionHDTV 3 Gold-T card=29 - ADS Tech Instant TV DVB-T PCI card=30 - TerraTec Cinergy 1400 DVB-T +card=31 - DViCO FusionHDTV 5 Gold diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index d1b9d21ffd89..f3302e1b1b9c 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -62,3 +62,5 @@ tuner=60 - Thomson DDT 7611 (ATSC/NTSC) tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner +tuner=64 - LG TDVS-H062F/TUA6034 +tuner=65 - Ymec TVF66T5-B/DFF diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index b9e6be00cadf..476c0c22fbb7 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -47,7 +47,7 @@ Timing notsc Don't use the CPU time stamp counter to read the wall time. This can be used to work around timing problems on multiprocessor systems - with not properly synchronized CPUs. Only useful with a SMP kernel + with not properly synchronized CPUs. report_lost_ticks Report when timer interrupts are lost because some code turned off @@ -74,6 +74,9 @@ Idle loop event. This will make the CPUs eat a lot more power, but may be useful to get slightly better performance in multiprocessor benchmarks. It also makes some profiling using performance counters more accurate. + Please note that on systems with MONITOR/MWAIT support (like Intel EM64T + CPUs) this option has no performance advantage over the normal idle loop. + It may also interact badly with hyperthreading. Rebooting @@ -178,6 +181,5 @@ Debugging Misc noreplacement Don't replace instructions with more appropiate ones - for the CPU. This may be useful on asymmetric MP systems - where some CPU have less capabilities than the others. - + for the CPU. This may be useful on asymmetric MP systems + where some CPU have less capabilities than the others. diff --git a/MAINTAINERS b/MAINTAINERS index ec8433c39dee..c31ddc4bcdd6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1521,6 +1521,12 @@ P: Zach Brown M: zab@zabbo.net S: Odd Fixes +MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 +P: Michael Kerrisk +M: mtk-manpages@gmx.net +W: ftp://ftp.kernel.org/pub/linux/docs/manpages +S: Maintained + MARVELL MV64340 ETHERNET DRIVER P: Manish Lachwani M: Manish_Lachwani@pmc-sierra.com @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 13 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc5 NAME=Woozy Numbat # *DOCUMENTATION* diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 295e0a8379cf..b2085735a2ba 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -176,6 +176,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) cpu_set(cpu, mm->cpu_vm_mask); cpu_switch_mm(mm->pgd, mm); enter_lazy_tlb(mm, current); + local_flush_tlb_all(); cpu_init(); diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 5382a3023602..2036ff15bda9 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -7,7 +7,7 @@ 1: ldrexb r2, [r1] \instr r2, r2, r3 strexb r0, r2, [r1] - cmpne r0, #0 + cmp r0, #0 bne 1b mov pc, lr .endm diff --git a/arch/arm/mach-integrator/platsmp.c b/arch/arm/mach-integrator/platsmp.c index aecf47ba033a..ea10bd8c972c 100644 --- a/arch/arm/mach-integrator/platsmp.c +++ b/arch/arm/mach-integrator/platsmp.c @@ -15,6 +15,7 @@ #include <linux/mm.h> #include <asm/atomic.h> +#include <asm/cacheflush.h> #include <asm/delay.h> #include <asm/mmu_context.h> #include <asm/procinfo.h> @@ -80,6 +81,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * "cpu" is Linux's internal ID. */ pen_release = cpu; + flush_cache_all(); /* * XXX diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 4ff4393ef0ea..7f58afb27e71 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 8ba1cd9406e7..65e356bd10d6 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index c2ba759e9946..4633470a6a37 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART1_BASE_PHYS, .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, @@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 1e7f343822d0..e9182242da95 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -30,6 +30,7 @@ * 28-Jun-2005 BJD Moved pm functionality out to common code * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s * 25-Jul-2005 BJD Removed ASIX static mappings + * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus */ #include <linux/kernel.h> @@ -60,6 +61,7 @@ #include <asm/arch/regs-mem.h> #include <asm/arch/regs-lcd.h> #include <asm/arch/nand.h> +#include <asm/arch/iic.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -304,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot) } static struct s3c2410_platform_nand bast_nand_info = { - .tacls = 80, + .tacls = 40, .twrph0 = 80, .twrph1 = 80, .nr_sets = ARRAY_SIZE(bast_nand_sets), @@ -385,6 +387,17 @@ static struct platform_device bast_sio = { }, }; +/* we have devices on the bus which cannot work much over the + * standard 100KHz i2c bus frequency +*/ + +static struct s3c2410_platform_i2c bast_i2c_info = { + .flags = 0, + .slave_addr = 0x10, + .bus_freq = 100*1000, + .max_freq = 130*1000, +}; + /* Standard BAST devices */ static struct platform_device *bast_devices[] __initdata = { @@ -431,6 +444,7 @@ void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c_device_nand.dev.platform_data = &bast_nand_info; + s3c_device_i2c.dev.platform_data = &bast_i2c_info; s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 2d977b4eeeab..b88de2700146 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area) bhi 1b mov pc, lr -/* ================================ CACHE LOCKING============================ - * - * The XScale MicroArchitecture implements support for locking entries into - * the data and instruction cache. The following functions implement the core - * low level instructions needed to accomplish the locking. The developer's - * manual states that the code that performs the locking must be in non-cached - * memory. To accomplish this, the code in xscale-cache-lock.c copies the - * following functions from the cache into a non-cached memory region that - * is allocated through consistent_alloc(). - * - */ - .align 5 -/* - * xscale_icache_lock - * - * r0: starting address to lock - * r1: end address to lock - */ -ENTRY(xscale_icache_lock) - -iLockLoop: - bic r0, r0, #CACHELINESIZE - 1 - mcr p15, 0, r0, c9, c1, 0 @ lock into cache - cmp r0, r1 @ are we done? - add r0, r0, #CACHELINESIZE @ advance to next cache line - bls iLockLoop - mov pc, lr - -/* - * xscale_icache_unlock - */ -ENTRY(xscale_icache_unlock) - mcr p15, 0, r0, c9, c1, 1 @ Unlock icache - mov pc, lr - -/* - * xscale_dcache_lock - * - * r0: starting address to lock - * r1: end address to lock - */ -ENTRY(xscale_dcache_lock) - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov r2, #1 - mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode - cpwait ip @ Wait for completion - - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT -dLockLoop: - msr cpsr_c, r3 - mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty - mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line - msr cpsr_c, r2 - ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from - @ location [r0]. Post-increment - @ r3 to next cache line - cmp r0, r1 @ Are we done? - bls dLockLoop - - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov r2, #0 - mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode - cpwait_ret lr, ip - -/* - * xscale_dcache_unlock - */ -ENTRY(xscale_dcache_unlock) - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mcr p15, 0, ip, c9, c2, 1 @ Unlock cache - mov pc, lr - -/* - * Needed to determine the length of the code that needs to be copied. - */ - .align 5 -ENTRY(xscale_cache_dummy) - mov pc, lr - -/* ================================ TLB LOCKING============================== - * - * The XScale MicroArchitecture implements support for locking entries into - * the Instruction and Data TLBs. The following functions provide the - * low level support for supporting these under Linux. xscale-lock.c - * implements some higher level management code. Most of the following - * is taken straight out of the Developer's Manual. - */ - -/* - * Lock I-TLB entry - * - * r0: Virtual address to translate and lock - */ - .align 5 -ENTRY(xscale_itlb_lock) - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT - msr cpsr_c, r3 @ Disable interrupts - mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry - mcr p15, 0, r0, c10, c4, 0 @ Translate and lock - msr cpsr_c, r2 @ Restore interrupts - cpwait_ret lr, ip - -/* - * Lock D-TLB entry - * - * r0: Virtual address to translate and lock - */ - .align 5 -ENTRY(xscale_dtlb_lock) - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT - msr cpsr_c, r3 @ Disable interrupts - mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry - mcr p15, 0, r0, c10, c8, 0 @ Translate and lock - msr cpsr_c, r2 @ Restore interrupts - cpwait_ret lr, ip - -/* - * Unlock all I-TLB entries - */ - .align 5 -ENTRY(xscale_itlb_unlock) - mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB - mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB - cpwait_ret lr, ip - -/* - * Unlock all D-TLB entries - */ -ENTRY(xscale_dtlb_unlock) - mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL - mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB - cpwait_ret lr, ip - /* =============================== PageTable ============================== */ #define PTE_CACHE_WRITE_ALLOCATE 0 diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c index 7ffd8cb9bc96..c51d1386a97c 100644 --- a/arch/arm/nwfpe/double_cpdo.c +++ b/arch/arm/nwfpe/double_cpdo.c @@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm); float64 float64_pow(float64 rFn, float64 rFm); float64 float64_pol(float64 rFn, float64 rFm); -static float64 float64_rsf(float64 rFn, float64 rFm) +static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) { - return float64_sub(rFm, rFn); + return float64_sub(roundData, rFm, rFn); } -static float64 float64_rdv(float64 rFn, float64 rFm) +static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) { - return float64_div(rFm, rFn); + return float64_div(roundData, rFm, rFn); } -static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { +static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { [ADF_CODE >> 20] = float64_add, [MUF_CODE >> 20] = float64_mul, [SUF_CODE >> 20] = float64_sub, @@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { [FRD_CODE >> 20] = float64_rdv, }; -static float64 float64_mvf(float64 rFm) +static float64 float64_mvf(struct roundingData *roundData,float64 rFm) { return rFm; } -static float64 float64_mnf(float64 rFm) +static float64 float64_mnf(struct roundingData *roundData,float64 rFm) { union float64_components u; @@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm) return u.f64; } -static float64 float64_abs(float64 rFm) +static float64 float64_abs(struct roundingData *roundData,float64 rFm) { union float64_components u; @@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm) return u.f64; } -static float64 (*const monadic_double[16])(float64 rFm) = { +static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { [MVF_CODE >> 20] = float64_mvf, [MNF_CODE >> 20] = float64_mnf, [ABS_CODE >> 20] = float64_abs, @@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = { [NRM_CODE >> 20] = float64_mvf, }; -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float64 rFm; @@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) } if (dyadic_double[opc_mask_shift]) { - rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); + rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_double[opc_mask_shift]) { - rFd->fDouble = monadic_double[opc_mask_shift](rFm); + rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c index c39f68a3449e..65a279ba927f 100644 --- a/arch/arm/nwfpe/extended_cpdo.c +++ b/arch/arm/nwfpe/extended_cpdo.c @@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm); floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); -static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) { - return floatx80_sub(rFm, rFn); + return floatx80_sub(roundData, rFm, rFn); } -static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) { - return floatx80_div(rFm, rFn); + return floatx80_div(roundData, rFm, rFn); } -static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { +static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { [ADF_CODE >> 20] = floatx80_add, [MUF_CODE >> 20] = floatx80_mul, [SUF_CODE >> 20] = floatx80_sub, @@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { [FRD_CODE >> 20] = floatx80_rdv, }; -static floatx80 floatx80_mvf(floatx80 rFm) +static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) { return rFm; } -static floatx80 floatx80_mnf(floatx80 rFm) +static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) { rFm.high ^= 0x8000; return rFm; } -static floatx80 floatx80_abs(floatx80 rFm) +static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) { rFm.high &= 0x7fff; return rFm; } -static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { +static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { [MVF_CODE >> 20] = floatx80_mvf, [MNF_CODE >> 20] = floatx80_mnf, [ABS_CODE >> 20] = floatx80_abs, @@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { [NRM_CODE >> 20] = floatx80_mvf, }; -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); floatx80 rFm; @@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) } if (dyadic_extended[opc_mask_shift]) { - rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); + rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_extended[opc_mask_shift]) { - rFd->fExtended = monadic_extended[opc_mask_shift](rFm); + rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index bf61696865ec..7690f731ee87 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -51,48 +51,42 @@ static void resetFPA11(void) fpa11->fpsr = FP_EMULATOR | BIT_AC; } -void SetRoundingMode(const unsigned int opcode) +int8 SetRoundingMode(const unsigned int opcode) { switch (opcode & MASK_ROUNDING_MODE) { default: case ROUND_TO_NEAREST: - float_rounding_mode = float_round_nearest_even; - break; + return float_round_nearest_even; case ROUND_TO_PLUS_INFINITY: - float_rounding_mode = float_round_up; - break; + return float_round_up; case ROUND_TO_MINUS_INFINITY: - float_rounding_mode = float_round_down; - break; + return float_round_down; case ROUND_TO_ZERO: - float_rounding_mode = float_round_to_zero; - break; + return float_round_to_zero; } } -void SetRoundingPrecision(const unsigned int opcode) +int8 SetRoundingPrecision(const unsigned int opcode) { #ifdef CONFIG_FPE_NWFPE_XP switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: - floatx80_rounding_precision = 32; - break; + return 32; case ROUND_DOUBLE: - floatx80_rounding_precision = 64; - break; + return 64; case ROUND_EXTENDED: - floatx80_rounding_precision = 80; - break; + return 80; default: - floatx80_rounding_precision = 80; + return 80; } #endif + return 80; } void nwfpe_init_fpa(union fp_state *fp) @@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp) #endif memset(fpa11, 0, sizeof(FPA11)); resetFPA11(); - SetRoundingMode(ROUND_TO_NEAREST); - SetRoundingPrecision(ROUND_EXTENDED); fpa11->initflag = 1; } diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index e4a61aea534b..93523ae4b7a1 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -37,6 +37,13 @@ /* includes */ #include "fpsr.h" /* FP control and status register definitions */ #include "milieu.h" + +struct roundingData { + int8 mode; + int8 precision; + signed char exception; +}; + #include "softfloat.h" #define typeNone 0x00 @@ -84,8 +91,8 @@ typedef struct tagFPA11 { initialised. */ } FPA11; -extern void SetRoundingMode(const unsigned int); -extern void SetRoundingPrecision(const unsigned int); +extern int8 SetRoundingMode(const unsigned int); +extern int8 SetRoundingPrecision(const unsigned int); extern void nwfpe_init_fpa(union fp_state *fp); #endif diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c index 1bea67437b6f..4a31dfd94068 100644 --- a/arch/arm/nwfpe/fpa11_cpdo.c +++ b/arch/arm/nwfpe/fpa11_cpdo.c @@ -24,15 +24,16 @@ #include "fpa11.h" #include "fpopcode.h" -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); +unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); +unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); unsigned int EmulateCPDO(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); FPREG *rFd; unsigned int nType, nDest, nRc; + struct roundingData roundData; /* Get the destination size. If not valid let Linux perform an invalid instruction trap. */ @@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeNone == nDest) return 0; - SetRoundingMode(opcode); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; /* Compare the size of the operands in Fn and Fm. Choose the largest size and perform operations in that size, @@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode) switch (nType) { case typeSingle: - nRc = SingleCPDO(opcode, rFd); + nRc = SingleCPDO(&roundData, opcode, rFd); break; case typeDouble: - nRc = DoubleCPDO(opcode, rFd); + nRc = DoubleCPDO(&roundData, opcode, rFd); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - nRc = ExtendedCPDO(opcode, rFd); + nRc = ExtendedCPDO(&roundData, opcode, rFd); break; #endif default: @@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode) case typeSingle: { if (typeDouble == nType) - rFd->fSingle = float64_to_float32(rFd->fDouble); + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); else - rFd->fSingle = floatx80_to_float32(rFd->fExtended); + rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended); } break; @@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeSingle == nType) rFd->fDouble = float32_to_float64(rFd->fSingle); else - rFd->fDouble = floatx80_to_float64(rFd->fExtended); + rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended); } break; @@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode) #else if (nDest != nType) { if (nDest == typeSingle) - rFd->fSingle = float64_to_float32(rFd->fDouble); + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); else rFd->fDouble = float32_to_float64(rFd->fSingle); } #endif } + if (roundData.exception) + float_raise(roundData.exception); + return nRc; } diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index 95fb63fa9d18..b0db5cbcc3b1 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user } } -static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) +static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) switch (fpa11->fType[Fn]) { case typeDouble: - val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); + val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended); break; #endif @@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) put_user(val.i[0], pMem); } -static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) +static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended); break; #endif @@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode) { unsigned int __user *pBase, *pAddress, *pFinal; unsigned int nRc = 1, write_back = WRITE_BACK(opcode); + struct roundingData roundData; - SetRoundingMode(ROUND_TO_NEAREST); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { @@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode) switch (opcode & MASK_TRANSFER_LENGTH) { case TRANSFER_SINGLE: - storeSingle(getFd(opcode), pAddress); + storeSingle(&roundData, getFd(opcode), pAddress); break; case TRANSFER_DOUBLE: - storeDouble(getFd(opcode), pAddress); + storeDouble(&roundData, getFd(opcode), pAddress); break; #ifdef CONFIG_FPE_NWFPE_XP case TRANSFER_EXTENDED: @@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode) nRc = 0; } + if (roundData.exception) + float_raise(roundData.exception); + if (write_back) writeRegister(getRn(opcode), (unsigned long) pFinal); return nRc; diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index db01fbc97216..adf8d3000540 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80); extern flag float64_is_nan(float64); extern flag float32_is_nan(float32); -void SetRoundingMode(const unsigned int opcode); - unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); @@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode) unsigned int PerformFLT(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); - SetRoundingMode(opcode); - SetRoundingPrecision(opcode); + struct roundingData roundData; + + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: { fpa11->fType[getFn(opcode)] = typeSingle; - fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode))); } break; @@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode) return 0; } + if (roundData.exception) + float_raise(roundData.exception); + return 1; } @@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); + struct roundingData roundData; - SetRoundingMode(opcode); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; switch (fpa11->fType[Fn]) { case typeSingle: { - writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); + writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { - writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); + writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble)); } break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: { - writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); + writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended)); } break; #endif @@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode) return 0; } + if (roundData.exception) + float_raise(roundData.exception); + return 1; } diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 12885f31d347..2dfe1ac42ee8 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!). code to access data in user space in some other source files at the moment (grep for get_user / put_user calls). --philb] -float_exception_flags is a global variable in SoftFloat. - This function is called by the SoftFloat routines to raise a floating point exception. We check the trap enable byte in the FPSR, and raise a SIGFPE exception if necessary. If not the relevant bits in the @@ -129,15 +127,14 @@ void float_raise(signed char flags) register unsigned int fpsr, cumulativeTraps; #ifdef CONFIG_DEBUG_USER - printk(KERN_DEBUG - "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", - current->comm, current->pid, flags, - __builtin_return_address(0), GET_USERREG()->ARM_pc); + /* Ignore inexact errors as there are far too many of them to log */ + if (flags & ~BIT_IXC) + printk(KERN_DEBUG + "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", + current->comm, current->pid, flags, + __builtin_return_address(0), GET_USERREG()->ARM_pc); #endif - /* Keep SoftFloat exception flags up to date. */ - float_exception_flags |= flags; - /* Read fpsr and initialize the cumulativeTraps. */ fpsr = readFPSR(); cumulativeTraps = 0; diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c index 705808e88d9d..c66981d682cf 100644 --- a/arch/arm/nwfpe/single_cpdo.c +++ b/arch/arm/nwfpe/single_cpdo.c @@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm); float32 float32_pow(float32 rFn, float32 rFm); float32 float32_pol(float32 rFn, float32 rFm); -static float32 float32_rsf(float32 rFn, float32 rFm) +static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm) { - return float32_sub(rFm, rFn); + return float32_sub(roundData, rFm, rFn); } -static float32 float32_rdv(float32 rFn, float32 rFm) +static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm) { - return float32_div(rFm, rFn); + return float32_div(roundData, rFm, rFn); } -static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { +static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = { [ADF_CODE >> 20] = float32_add, [MUF_CODE >> 20] = float32_mul, [SUF_CODE >> 20] = float32_sub, @@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { [FRD_CODE >> 20] = float32_rdv, }; -static float32 float32_mvf(float32 rFm) +static float32 float32_mvf(struct roundingData *roundData, float32 rFm) { return rFm; } -static float32 float32_mnf(float32 rFm) +static float32 float32_mnf(struct roundingData *roundData, float32 rFm) { return rFm ^ 0x80000000; } -static float32 float32_abs(float32 rFm) +static float32 float32_abs(struct roundingData *roundData, float32 rFm) { return rFm & 0x7fffffff; } -static float32 (*const monadic_single[16])(float32 rFm) = { +static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = { [MVF_CODE >> 20] = float32_mvf, [MNF_CODE >> 20] = float32_mnf, [ABS_CODE >> 20] = float32_abs, @@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = { [NRM_CODE >> 20] = float32_mvf, }; -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float32 rFm; @@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) if (fpa11->fType[Fn] == typeSingle && dyadic_single[opc_mask_shift]) { rFn = fpa11->fpreg[Fn].fSingle; - rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); + rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_single[opc_mask_shift]) { - rFd->fSingle = monadic_single[opc_mask_shift](rFm); + rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c index e038dd3be9b3..8b75a6e7cb3a 100644 --- a/arch/arm/nwfpe/softfloat.c +++ b/arch/arm/nwfpe/softfloat.c @@ -36,16 +36,6 @@ this code that are retained. /* ------------------------------------------------------------------------------- -Floating-point rounding mode, extended double-precision rounding precision, -and exception flags. -------------------------------------------------------------------------------- -*/ -int8 float_rounding_mode = float_round_nearest_even; -int8 floatx80_rounding_precision = 80; -int8 float_exception_flags; - -/* -------------------------------------------------------------------------------- Primitive arithmetic functions, including multi-word arithmetic, and division and square root approximations. (Can be specialized to target if desired.) @@ -77,14 +67,14 @@ input is too large, however, the invalid exception is raised and the largest positive or negative integer is returned. ------------------------------------------------------------------------------- */ -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; int32 z; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -107,10 +97,10 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ ) z = absZ; if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_exception_flags |= float_flag_invalid; + roundData->exception |= float_flag_invalid; return zSign ? 0x80000000 : 0x7FFFFFFF; } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; return z; } @@ -224,14 +214,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; flag isTiny; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -254,7 +244,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) || ( ( zExp == 0xFD ) && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) ) { - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -265,10 +255,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) shift32RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x7F; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>7; zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -287,12 +277,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) + normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount ); + return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); } @@ -395,14 +385,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) { int8 roundingMode; flag roundNearestEven; int16 roundIncrement, roundBits; flag isTiny; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x200; if ( ! roundNearestEven ) { @@ -427,7 +417,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) ) { //register int lr = __builtin_return_address(0); //printk("roundAndPackFloat64 called from 0x%08x\n",lr); - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -438,10 +428,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) shift64RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x3FF; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>10; zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -460,12 +450,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) + normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount ); + return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); } @@ -572,14 +562,15 @@ Floating-point Arithmetic. */ static floatx80 roundAndPackFloatx80( - int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 + struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { - int8 roundingMode; + int8 roundingMode, roundingPrecision; flag roundNearestEven, increment, isTiny; int64 roundIncrement, roundMask, roundBits; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; + roundingPrecision = roundData->precision; roundNearestEven = ( roundingMode == float_round_nearest_even ); if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { @@ -623,8 +614,8 @@ static floatx80 shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); zExp = 0; roundBits = zSig0 & roundMask; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig0 += roundIncrement; if ( (sbits64) zSig0 < 0 ) zExp = 1; roundIncrement = roundMask + 1; @@ -635,7 +626,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig0 += roundIncrement; if ( zSig0 < roundIncrement ) { ++zExp; @@ -672,7 +663,7 @@ static floatx80 ) { roundMask = 0; overflow: - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; if ( ( roundingMode == float_round_to_zero ) || ( zSign && ( roundingMode == float_round_up ) ) || ( ! zSign && ( roundingMode == float_round_down ) ) @@ -689,8 +680,8 @@ static floatx80 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); zExp = 0; - if ( isTiny && zSig1 ) float_raise( float_flag_underflow ); - if ( zSig1 ) float_exception_flags |= float_flag_inexact; + if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow; + if ( zSig1 ) roundData->exception |= float_flag_inexact; if ( roundNearestEven ) { increment = ( (sbits64) zSig1 < 0 ); } @@ -710,7 +701,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( zSig1 ) float_exception_flags |= float_flag_inexact; + if ( zSig1 ) roundData->exception |= float_flag_inexact; if ( increment ) { ++zSig0; if ( zSig0 == 0 ) { @@ -740,7 +731,7 @@ normalized. */ static floatx80 normalizeRoundAndPackFloatx80( - int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 + struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { int8 shiftCount; @@ -754,7 +745,7 @@ static floatx80 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); zExp -= shiftCount; return - roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 ); + roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 ); } @@ -767,14 +758,14 @@ the single-precision floating-point format. The conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 int32_to_float32( int32 a ) +float32 int32_to_float32(struct roundingData *roundData, int32 a) { flag zSign; if ( a == 0 ) return 0; if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); zSign = ( a < 0 ); - return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a ); + return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a ); } @@ -840,7 +831,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float32_to_int32( float32 a ) +int32 float32_to_int32( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp, shiftCount; @@ -856,7 +847,7 @@ int32 float32_to_int32( float32 a ) zSig = aSig; zSig <<= 32; if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); - return roundAndPackInt32( aSign, zSig ); + return roundAndPackInt32( roundData, aSign, zSig ); } @@ -889,13 +880,13 @@ int32 float32_to_int32_round_to_zero( float32 a ) return 0x80000000; } else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp | aSig ) float_raise( float_flag_inexact ); return 0; } aSig = ( aSig | 0x00800000 )<<8; z = aSig>>( - shiftCount ); if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; + float_raise( float_flag_inexact ); } return aSign ? - z : z; @@ -973,7 +964,7 @@ operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_round_to_int( float32 a ) +float32 float32_round_to_int( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp; @@ -988,11 +979,12 @@ float32 float32_round_to_int( float32 a ) } return a; } + roundingMode = roundData->mode; if ( aExp <= 0x7E ) { if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; + roundData->exception |= float_flag_inexact; aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundingMode ) { case float_round_nearest_even: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { return packFloat32( aSign, 0x7F, 0 ); @@ -1009,7 +1001,6 @@ float32 float32_round_to_int( float32 a ) lastBitMask <<= 0x96 - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1020,7 +1011,7 @@ float32 float32_round_to_int( float32 a ) } } z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; + if ( z != a ) roundData->exception |= float_flag_inexact; return z; } @@ -1034,7 +1025,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1093,7 +1084,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) ++zExp; } roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1106,7 +1097,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1123,7 +1114,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0xFF ) { if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aExp == 0 ) { @@ -1132,7 +1123,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); + return packFloat32( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); @@ -1169,7 +1160,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); + return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1180,17 +1171,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_add( float32 a, float32 b ) +float32 float32_add( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); + return addFloat32Sigs( roundData, a, b, aSign ); } else { - return subFloat32Sigs( a, b, aSign ); + return subFloat32Sigs( roundData, a, b, aSign ); } } @@ -1202,17 +1193,17 @@ Returns the result of subtracting the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sub( float32 a, float32 b ) +float32 float32_sub( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); + return subFloat32Sigs( roundData, a, b, aSign ); } else { - return addFloat32Sigs( a, b, aSign ); + return addFloat32Sigs( roundData, a, b, aSign ); } } @@ -1224,7 +1215,7 @@ Returns the result of multiplying the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_mul( float32 a, float32 b ) +float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1244,7 +1235,7 @@ float32 float32_mul( float32 a, float32 b ) return propagateFloat32NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1252,7 +1243,7 @@ float32 float32_mul( float32 a, float32 b ) if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1274,7 +1265,7 @@ float32 float32_mul( float32 a, float32 b ) zSig <<= 1; --zExp; } - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1285,7 +1276,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_div( float32 a, float32 b ) +float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1302,7 +1293,7 @@ float32 float32_div( float32 a, float32 b ) if ( aSig ) return propagateFloat32NaN( a, b ); if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1314,10 +1305,10 @@ float32 float32_div( float32 a, float32 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloat32( zSign, 0xFF, 0 ); } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1341,7 +1332,7 @@ float32 float32_div( float32 a, float32 b ) if ( ( zSig & 0x3F ) == 0 ) { zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); } - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1352,7 +1343,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_rem( float32 a, float32 b ) +float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -1372,7 +1363,7 @@ float32 float32_rem( float32 a, float32 b ) if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { return propagateFloat32NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( bExp == 0xFF ) { @@ -1381,7 +1372,7 @@ float32 float32_rem( float32 a, float32 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1444,7 +1435,7 @@ float32 float32_rem( float32 a, float32 b ) } zSign = ( (sbits32) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig ); } @@ -1455,7 +1446,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sqrt( float32 a ) +float32 float32_sqrt( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp, zExp; @@ -1468,12 +1459,12 @@ float32 float32_sqrt( float32 a ) if ( aExp == 0xFF ) { if ( aSig ) return propagateFloat32NaN( a, 0 ); if ( ! aSign ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aExp == 0 ) { @@ -1499,7 +1490,7 @@ float32 float32_sqrt( float32 a ) } } shift32RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat32( 0, zExp, zSig ); + return roundAndPackFloat32( roundData, 0, zExp, zSig ); } @@ -1661,7 +1652,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float64_to_int32( float64 a ) +int32 float64_to_int32( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp, shiftCount; @@ -1674,7 +1665,7 @@ int32 float64_to_int32( float64 a ) if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x42C - aExp; if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); + return roundAndPackInt32( roundData, aSign, aSig ); } @@ -1705,7 +1696,7 @@ int32 float64_to_int32_round_to_zero( float64 a ) goto invalid; } else if ( 52 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp || aSig ) float_raise( float_flag_inexact ); return 0; } aSig |= LIT64( 0x0010000000000000 ); @@ -1715,11 +1706,11 @@ int32 float64_to_int32_round_to_zero( float64 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_exception_flags |= float_flag_invalid; + float_raise( float_flag_invalid ); return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<<shiftCount ) != savedASig ) { - float_exception_flags |= float_flag_inexact; + float_raise( float_flag_inexact ); } return z; @@ -1736,7 +1727,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest positive integer is returned. ------------------------------------------------------------------------------- */ -int32 float64_to_uint32( float64 a ) +int32 float64_to_uint32( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp, shiftCount; @@ -1749,7 +1740,7 @@ int32 float64_to_uint32( float64 a ) if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x42C - aExp; if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); + return roundAndPackInt32( roundData, aSign, aSig ); } /* @@ -1778,7 +1769,7 @@ int32 float64_to_uint32_round_to_zero( float64 a ) goto invalid; } else if ( 52 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp || aSig ) float_raise( float_flag_inexact ); return 0; } aSig |= LIT64( 0x0010000000000000 ); @@ -1788,11 +1779,11 @@ int32 float64_to_uint32_round_to_zero( float64 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_exception_flags |= float_flag_invalid; + float_raise( float_flag_invalid ); return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<<shiftCount ) != savedASig ) { - float_exception_flags |= float_flag_inexact; + float_raise( float_flag_inexact ); } return z; } @@ -1805,7 +1796,7 @@ performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float64_to_float32( float64 a ) +float32 float64_to_float32( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp; @@ -1825,7 +1816,7 @@ float32 float64_to_float32( float64 a ) zSig |= 0x40000000; aExp -= 0x381; } - return roundAndPackFloat32( aSign, aExp, zSig ); + return roundAndPackFloat32( roundData, aSign, aExp, zSig ); } @@ -1872,7 +1863,7 @@ operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_round_to_int( float64 a ) +float64 float64_round_to_int( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp; @@ -1889,9 +1880,9 @@ float64 float64_round_to_int( float64 a ) } if ( aExp <= 0x3FE ) { if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; + roundData->exception |= float_flag_inexact; aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundData->mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { return packFloat64( aSign, 0x3FF, 0 ); @@ -1909,7 +1900,7 @@ float64 float64_round_to_int( float64 a ) lastBitMask <<= 0x433 - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1920,7 +1911,7 @@ float64 float64_round_to_int( float64 a ) } } z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; + if ( z != a ) roundData->exception |= float_flag_inexact; return z; } @@ -1934,7 +1925,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) +static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -1993,7 +1984,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) ++zExp; } roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2006,7 +1997,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) +static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -2023,7 +2014,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0x7FF ) { if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aExp == 0 ) { @@ -2032,7 +2023,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); + return packFloat64( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); @@ -2069,7 +2060,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); + return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2080,17 +2071,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_add( float64 a, float64 b ) +float64 float64_add( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); + return addFloat64Sigs( roundData, a, b, aSign ); } else { - return subFloat64Sigs( a, b, aSign ); + return subFloat64Sigs( roundData, a, b, aSign ); } } @@ -2102,17 +2093,17 @@ Returns the result of subtracting the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sub( float64 a, float64 b ) +float64 float64_sub( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); + return subFloat64Sigs( roundData, a, b, aSign ); } else { - return addFloat64Sigs( a, b, aSign ); + return addFloat64Sigs( roundData, a, b, aSign ); } } @@ -2124,7 +2115,7 @@ Returns the result of multiplying the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_mul( float64 a, float64 b ) +float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2142,7 +2133,7 @@ float64 float64_mul( float64 a, float64 b ) return propagateFloat64NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2150,7 +2141,7 @@ float64 float64_mul( float64 a, float64 b ) if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2172,7 +2163,7 @@ float64 float64_mul( float64 a, float64 b ) zSig0 <<= 1; --zExp; } - return roundAndPackFloat64( zSign, zExp, zSig0 ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig0 ); } @@ -2183,7 +2174,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_div( float64 a, float64 b ) +float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2202,7 +2193,7 @@ float64 float64_div( float64 a, float64 b ) if ( aSig ) return propagateFloat64NaN( a, b ); if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2214,10 +2205,10 @@ float64 float64_div( float64 a, float64 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloat64( zSign, 0x7FF, 0 ); } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2243,7 +2234,7 @@ float64 float64_div( float64 a, float64 b ) } zSig |= ( rem1 != 0 ); } - return roundAndPackFloat64( zSign, zExp, zSig ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2254,7 +2245,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_rem( float64 a, float64 b ) +float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -2272,7 +2263,7 @@ float64 float64_rem( float64 a, float64 b ) if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { return propagateFloat64NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( bExp == 0x7FF ) { @@ -2281,7 +2272,7 @@ float64 float64_rem( float64 a, float64 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2329,7 +2320,7 @@ float64 float64_rem( float64 a, float64 b ) } zSign = ( (sbits64) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig ); } @@ -2340,7 +2331,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sqrt( float64 a ) +float64 float64_sqrt( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp, zExp; @@ -2354,12 +2345,12 @@ float64 float64_sqrt( float64 a ) if ( aExp == 0x7FF ) { if ( aSig ) return propagateFloat64NaN( a, a ); if ( ! aSign ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aExp == 0 ) { @@ -2390,7 +2381,7 @@ float64 float64_sqrt( float64 a ) } } shift64RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat64( 0, zExp, zSig ); + return roundAndPackFloat64( roundData, 0, zExp, zSig ); } @@ -2554,7 +2545,7 @@ largest positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 floatx80_to_int32( floatx80 a ) +int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp, shiftCount; @@ -2567,7 +2558,7 @@ int32 floatx80_to_int32( floatx80 a ) shiftCount = 0x4037 - aExp; if ( shiftCount <= 0 ) shiftCount = 1; shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); + return roundAndPackInt32( roundData, aSign, aSig ); } @@ -2598,7 +2589,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) goto invalid; } else if ( 63 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp || aSig ) float_raise( float_flag_inexact ); return 0; } savedASig = aSig; @@ -2607,11 +2598,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_exception_flags |= float_flag_invalid; + float_raise( float_flag_invalid ); return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<<shiftCount ) != savedASig ) { - float_exception_flags |= float_flag_inexact; + float_raise( float_flag_inexact ); } return z; @@ -2625,7 +2616,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 floatx80_to_float32( floatx80 a ) +float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp; @@ -2642,7 +2633,7 @@ float32 floatx80_to_float32( floatx80 a ) } shift64RightJamming( aSig, 33, &aSig ); if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); + return roundAndPackFloat32( roundData, aSign, aExp, aSig ); } @@ -2654,7 +2645,7 @@ conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 floatx80_to_float64( floatx80 a ) +float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp; @@ -2671,7 +2662,7 @@ float64 floatx80_to_float64( floatx80 a ) } shift64RightJamming( aSig, 1, &zSig ); if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); + return roundAndPackFloat64( roundData, aSign, aExp, zSig ); } @@ -2683,7 +2674,7 @@ value. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_round_to_int( floatx80 a ) +floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp; @@ -2703,9 +2694,9 @@ floatx80 floatx80_round_to_int( floatx80 a ) && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { return a; } - float_exception_flags |= float_flag_inexact; + roundData->exception |= float_flag_inexact; aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundData->mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { @@ -2729,7 +2720,7 @@ floatx80 floatx80_round_to_int( floatx80 a ) lastBitMask <<= 0x403E - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; if ( roundingMode == float_round_nearest_even ) { z.low += lastBitMask>>1; if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; @@ -2744,7 +2735,7 @@ floatx80 floatx80_round_to_int( floatx80 a ) ++z.high; z.low = LIT64( 0x8000000000000000 ); } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; + if ( z.low != a.low ) roundData->exception |= float_flag_inexact; return z; } @@ -2758,7 +2749,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2814,7 +2805,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) roundAndPack: return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2827,7 +2818,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2845,7 +2836,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) if ( (bits64) ( ( aSig | bSig )<<1 ) ) { return propagateFloatx80NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2857,7 +2848,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) zSig1 = 0; if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); + return packFloatx80( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FFF ) { if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); @@ -2883,7 +2874,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) normalizeRoundAndPack: return normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2894,17 +2885,17 @@ values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_add( floatx80 a, floatx80 b ) +floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); + return addFloatx80Sigs( roundData, a, b, aSign ); } else { - return subFloatx80Sigs( a, b, aSign ); + return subFloatx80Sigs( roundData, a, b, aSign ); } } @@ -2916,17 +2907,17 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sub( floatx80 a, floatx80 b ) +floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); + return subFloatx80Sigs( roundData, a, b, aSign ); } else { - return addFloatx80Sigs( a, b, aSign ); + return addFloatx80Sigs( roundData, a, b, aSign ); } } @@ -2938,7 +2929,7 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_mul( floatx80 a, floatx80 b ) +floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -2964,7 +2955,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b ) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2987,7 +2978,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2998,7 +2989,7 @@ value `a' by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_div( floatx80 a, floatx80 b ) +floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -3029,12 +3020,12 @@ floatx80 floatx80_div( floatx80 a, floatx80 b ) if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); @@ -3068,7 +3059,7 @@ floatx80 floatx80_div( floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -3079,7 +3070,7 @@ Returns the remainder of the extended double-precision floating-point value according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_rem( floatx80 a, floatx80 b ) +floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, expDiff; @@ -3107,7 +3098,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3164,9 +3155,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b ) aSig1 = alternateASig1; zSign = ! zSign; } + return normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); + roundData, zSign, bExp + expDiff, aSig0, aSig1 ); } @@ -3177,7 +3169,7 @@ value `a'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sqrt( floatx80 a ) +floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp, zExp; @@ -3197,7 +3189,7 @@ floatx80 floatx80_sqrt( floatx80 a ) if ( aSign ) { if ( ( aExp | aSig0 ) == 0 ) return a; invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3242,7 +3234,7 @@ floatx80 floatx80_sqrt( floatx80 a ) } return roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); + roundData, 0, zExp, zSig0, zSig1 ); } @@ -3264,7 +3256,7 @@ flag floatx80_eq( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } @@ -3294,7 +3286,7 @@ flag floatx80_le( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } aSign = extractFloatx80Sign( a ); @@ -3328,7 +3320,7 @@ flag floatx80_lt( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } aSign = extractFloatx80Sign( a ); @@ -3361,7 +3353,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } return @@ -3392,7 +3384,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } @@ -3429,7 +3421,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 1e1743173899..1c8799b9ee4d 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -74,7 +74,7 @@ enum { Software IEC/IEEE floating-point rounding mode. ------------------------------------------------------------------------------- */ -extern signed char float_rounding_mode; +//extern int8 float_rounding_mode; enum { float_round_nearest_even = 0, float_round_to_zero = 1, @@ -86,7 +86,6 @@ enum { ------------------------------------------------------------------------------- Software IEC/IEEE floating-point exception flags. ------------------------------------------------------------------------------- -extern signed char float_exception_flags; enum { float_flag_inexact = 1, float_flag_underflow = 2, @@ -99,7 +98,6 @@ ScottB: November 4, 1998 Changed the enumeration to match the bit order in the FPA11. */ -extern signed char float_exception_flags; enum { float_flag_invalid = 1, float_flag_divbyzero = 2, @@ -121,7 +119,7 @@ void float_raise( signed char ); Software IEC/IEEE integer-to-floating-point conversion routines. ------------------------------------------------------------------------------- */ -float32 int32_to_float32( signed int ); +float32 int32_to_float32( struct roundingData *, signed int ); float64 int32_to_float64( signed int ); #ifdef FLOATX80 floatx80 int32_to_floatx80( signed int ); @@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int ); Software IEC/IEEE single-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float32_to_int32( float32 ); +signed int float32_to_int32( struct roundingData *, float32 ); signed int float32_to_int32_round_to_zero( float32 ); float64 float32_to_float64( float32 ); #ifdef FLOATX80 @@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 ); Software IEC/IEEE single-precision operations. ------------------------------------------------------------------------------- */ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); +float32 float32_round_to_int( struct roundingData*, float32 ); +float32 float32_add( struct roundingData *, float32, float32 ); +float32 float32_sub( struct roundingData *, float32, float32 ); +float32 float32_mul( struct roundingData *, float32, float32 ); +float32 float32_div( struct roundingData *, float32, float32 ); +float32 float32_rem( struct roundingData *, float32, float32 ); +float32 float32_sqrt( struct roundingData*, float32 ); char float32_eq( float32, float32 ); char float32_le( float32, float32 ); char float32_lt( float32, float32 ); @@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 ); Software IEC/IEEE double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float64_to_int32( float64 ); +signed int float64_to_int32( struct roundingData *, float64 ); signed int float64_to_int32_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); +float32 float64_to_float32( struct roundingData *, float64 ); #ifdef FLOATX80 floatx80 float64_to_floatx80( float64 ); #endif @@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 ); Software IEC/IEEE double-precision operations. ------------------------------------------------------------------------------- */ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); +float64 float64_round_to_int( struct roundingData *, float64 ); +float64 float64_add( struct roundingData *, float64, float64 ); +float64 float64_sub( struct roundingData *, float64, float64 ); +float64 float64_mul( struct roundingData *, float64, float64 ); +float64 float64_div( struct roundingData *, float64, float64 ); +float64 float64_rem( struct roundingData *, float64, float64 ); +float64 float64_sqrt( struct roundingData *, float64 ); char float64_eq( float64, float64 ); char float64_le( float64, float64 ); char float64_lt( float64, float64 ); @@ -198,31 +196,23 @@ char float64_is_signaling_nan( float64 ); Software IEC/IEEE extended double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int floatx80_to_int32( floatx80 ); +signed int floatx80_to_int32( struct roundingData *, floatx80 ); signed int floatx80_to_int32_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); - -/* -------------------------------------------------------------------------------- -Software IEC/IEEE extended double-precision rounding precision. Valid -values are 32, 64, and 80. -------------------------------------------------------------------------------- -*/ -extern signed char floatx80_rounding_precision; +float32 floatx80_to_float32( struct roundingData *, floatx80 ); +float64 floatx80_to_float64( struct roundingData *, floatx80 ); /* ------------------------------------------------------------------------------- Software IEC/IEEE extended double-precision operations. ------------------------------------------------------------------------------- */ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); +floatx80 floatx80_round_to_int( struct roundingData *, floatx80 ); +floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_sqrt( struct roundingData *, floatx80 ); char floatx80_eq( floatx80, floatx80 ); char floatx80_le( floatx80, floatx80 ); char floatx80_lt( floatx80, floatx80 ); diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index b801cd66b6ea..9b367a65cb4d 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, if ((s64)m_sig < 0) { vdd->sign = vfp_sign_negate(vdd->sign); m_sig = -m_sig; + } else if (m_sig == 0) { + vdd->sign = (fpscr & FPSCR_RMODE_MASK) == + FPSCR_ROUND_MINUSINF ? 0x8000 : 0; } } else { m_sig += vdn->significand; diff --git a/arch/arm26/mm/fault.c b/arch/arm26/mm/fault.c index dacca8bb7744..bd6f2db608b7 100644 --- a/arch/arm26/mm/fault.c +++ b/arch/arm26/mm/fault.c @@ -176,12 +176,12 @@ survive: * Handle the "normal" cases first - successful and sigbus */ switch (fault) { - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; return fault; - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; - case 0: + case VM_FAULT_SIGBUS: return fault; } @@ -226,14 +226,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) /* * Handle the "normal" case first */ - if (fault > 0) + switch (fault) { + case VM_FAULT_MINOR: + case VM_FAULT_MAJOR: return 0; - - /* - * We had some memory, but were unable to - * successfully fix up this page fault. - */ - if (fault == 0){ + case VM_FAULT_SIGBUS: goto do_sigbus; } diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index fe1cc36b5aca..934c51078cce 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -284,13 +284,13 @@ do_page_fault(unsigned long address, struct pt_regs *regs, */ switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 41d02ac48233..8b3eb50c5105 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c @@ -163,13 +163,13 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * the fault. */ switch (handle_mm_fault(mm, vma, ear0, write)) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 963e17aa205d..60a9e54dd20e 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -442,6 +442,13 @@ acpi_cpufreq_cpu_init ( (u32) data->acpi_data.states[i].transition_latency); cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); + + /* + * the first call to ->target() should result in us actually + * writing something to the appropriate registers. + */ + data->resume = 1; + return (result); err_freqfree: diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 31f65c8a4c24..ab6e0611303d 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -1,5 +1,5 @@ /* - * (c) 2003, 2004 Advanced Micro Devices, Inc. + * (c) 2003, 2004, 2005 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html @@ -44,7 +44,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.40.2" +#define VERSION "version 1.50.3" #include "powernow-k8.h" /* serialize freq changes */ @@ -231,7 +231,7 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid) /* * Reduce the vid by the max of step or reqvid. * Decreasing vid codes represent increasing voltages: - * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. + * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of VID_OFF is off. */ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid, u32 step) { @@ -466,7 +466,7 @@ static int check_supported_cpu(unsigned int cpu) eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || ((eax & CPUID_XFAM) != CPUID_XFAM_K8) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } @@ -695,6 +695,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & RVO_MASK; + data->exttype = (data->acpi_data.states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) & PLL_L_MASK; data->vidmvs = 1 << ((data->acpi_data.states[index].control >> MVS_SHIFT) & MVS_MASK); data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & VST_MASK; @@ -734,8 +735,16 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) } for (i = 0; i < data->acpi_data.state_count; i++) { - u32 fid = data->acpi_data.states[i].control & FID_MASK; - u32 vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; + u32 fid; + u32 vid; + + if (data->exttype) { + fid = data->acpi_data.states[i].status & FID_MASK; + vid = (data->acpi_data.states[i].status >> VID_SHIFT) & VID_MASK; + } else { + fid = data->acpi_data.states[i].control & FID_MASK; + vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; + } dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); @@ -752,7 +761,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) } /* verify voltage is OK - BIOSs are using "off" to indicate invalid */ - if (vid == 0x1f) { + if (vid == VID_OFF) { dprintk("invalid vid %u, ignoring\n", vid); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; @@ -929,15 +938,6 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi down(&fidvid_sem); - for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { - /* make sure the sibling is initialized */ - if (!powernow_data[i]) { - ret = 0; - up(&fidvid_sem); - goto err_out; - } - } - powernow_k8_acpi_pst_values(data, newstate); if (transition_frequency(data, newstate)) { @@ -977,7 +977,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; cpumask_t oldmask = CPU_MASK_ALL; - int rc; + int rc, i; if (!check_supported_cpu(pol->cpu)) return -ENODEV; @@ -1063,7 +1063,9 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) printk("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); - powernow_data[pol->cpu] = data; + for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { + powernow_data[i] = data; + } return 0; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 9ed5bf221cb7..b1e85bb36396 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -1,5 +1,5 @@ /* - * (c) 2003, 2004 Advanced Micro Devices, Inc. + * (c) 2003, 2004, 2005 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html @@ -19,6 +19,7 @@ struct powernow_k8_data { u32 vidmvs; /* usable value calculated from mvs */ u32 vstable; /* voltage stabilization time, units 20 us */ u32 plllock; /* pll lock time, units 1 us */ + u32 exttype; /* extended interface = 1 */ /* keep track of the current fid / vid */ u32 currvid, currfid; @@ -41,7 +42,7 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_E 0x00020000 +#define CPUID_XMOD_REV_F 0x00040000 #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 @@ -57,25 +58,26 @@ struct powernow_k8_data { /* Field definitions within the FID VID Low Control MSR : */ #define MSR_C_LO_INIT_FID_VID 0x00010000 -#define MSR_C_LO_NEW_VID 0x00001f00 -#define MSR_C_LO_NEW_FID 0x0000002f +#define MSR_C_LO_NEW_VID 0x00003f00 +#define MSR_C_LO_NEW_FID 0x0000003f #define MSR_C_LO_VID_SHIFT 8 /* Field definitions within the FID VID High Control MSR : */ -#define MSR_C_HI_STP_GNT_TO 0x000fffff +#define MSR_C_HI_STP_GNT_TO 0x000fffff /* Field definitions within the FID VID Low Status MSR : */ -#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */ -#define MSR_S_LO_MAX_RAMP_VID 0x1f000000 +#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */ +#define MSR_S_LO_MAX_RAMP_VID 0x3f000000 #define MSR_S_LO_MAX_FID 0x003f0000 #define MSR_S_LO_START_FID 0x00003f00 #define MSR_S_LO_CURRENT_FID 0x0000003f /* Field definitions within the FID VID High Status MSR : */ -#define MSR_S_HI_MAX_WORKING_VID 0x001f0000 -#define MSR_S_HI_START_VID 0x00001f00 -#define MSR_S_HI_CURRENT_VID 0x0000001f -#define MSR_C_HI_STP_GNT_BENIGN 0x00000001 +#define MSR_S_HI_MIN_WORKING_VID 0x3f000000 +#define MSR_S_HI_MAX_WORKING_VID 0x003f0000 +#define MSR_S_HI_START_VID 0x00003f00 +#define MSR_S_HI_CURRENT_VID 0x0000003f +#define MSR_C_HI_STP_GNT_BENIGN 0x00000001 /* * There are restrictions frequencies have to follow: @@ -99,13 +101,15 @@ struct powernow_k8_data { #define MIN_FREQ_RESOLUTION 200 /* fids jump by 2 matching freq jumps by 200 */ #define MAX_FID 0x2a /* Spec only gives FID values as far as 5 GHz */ -#define LEAST_VID 0x1e /* Lowest (numerically highest) useful vid value */ +#define LEAST_VID 0x3e /* Lowest (numerically highest) useful vid value */ #define MIN_FREQ 800 /* Min and max freqs, per spec */ #define MAX_FREQ 5000 #define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */ -#define INVALID_VID_MASK 0xffffffe0 /* not a valid vid if these bits are set */ +#define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */ + +#define VID_OFF 0x3f #define STOP_GRANT_5NS 1 /* min poss memory access latency for voltage change */ @@ -121,12 +125,14 @@ struct powernow_k8_data { #define IRT_SHIFT 30 #define RVO_SHIFT 28 +#define EXT_TYPE_SHIFT 27 #define PLL_L_SHIFT 20 #define MVS_SHIFT 18 #define VST_SHIFT 11 #define VID_SHIFT 6 #define IRT_MASK 3 #define RVO_MASK 3 +#define EXT_TYPE_MASK 1 #define PLL_L_MASK 0x7f #define MVS_MASK 3 #define VST_MASK 0x7f diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index 1d768b263269..6c55b50cf048 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -128,7 +128,7 @@ static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le cpuid_count(4, index, &eax, &ebx, &ecx, &edx); cache_eax.full = eax; if (cache_eax.split.type == CACHE_TYPE_NULL) - return -1; + return -EIO; /* better error ? */ this_leaf->eax.full = eax; this_leaf->ebx.full = ebx; @@ -334,6 +334,7 @@ static int __devinit detect_cache_attributes(unsigned int cpu) struct _cpuid4_info *this_leaf; unsigned long j; int retval; + cpumask_t oldmask; if (num_cache_leaves == 0) return -ENOENT; @@ -345,19 +346,26 @@ static int __devinit detect_cache_attributes(unsigned int cpu) memset(cpuid4_info[cpu], 0, sizeof(struct _cpuid4_info) * num_cache_leaves); + oldmask = current->cpus_allowed; + retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (retval) + goto out; + /* Do cpuid and store the results */ + retval = 0; for (j = 0; j < num_cache_leaves; j++) { this_leaf = CPUID4_INFO_IDX(cpu, j); retval = cpuid4_cache_lookup(j, this_leaf); if (unlikely(retval < 0)) - goto err_out; + break; cache_shared_cpu_map_setup(cpu, j); } - return 0; + set_cpus_allowed(current, oldmask); -err_out: - free_cache_attributes(cpu); - return -ENOMEM; +out: + if (retval) + free_cache_attributes(cpu); + return retval; } #ifdef CONFIG_SYSFS diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index f57e5ee94943..fc426380366b 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -76,6 +76,12 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) #define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV) if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 ) c->x86 = 6; + +#ifdef CONFIG_SYSCTL + /* randomize_va_space slows us down enormously; + it probably triggers retranslation of x86->native bytecode */ + randomize_va_space = 0; +#endif } static void transmeta_identify(struct cpuinfo_x86 * c) diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c index 52ed18d8b511..cb699a2aa1f8 100644 --- a/arch/i386/kernel/machine_kexec.c +++ b/arch/i386/kernel/machine_kexec.c @@ -16,6 +16,7 @@ #include <asm/io.h> #include <asm/apic.h> #include <asm/cpufeature.h> +#include <asm/desc.h> static inline unsigned long read_cr3(void) { @@ -90,33 +91,32 @@ static void identity_map_page(unsigned long address) } #endif - static void set_idt(void *newidt, __u16 limit) { - unsigned char curidt[6]; + struct Xgt_desc_struct curidt; /* ia32 supports unaliged loads & stores */ - (*(__u16 *)(curidt)) = limit; - (*(__u32 *)(curidt +2)) = (unsigned long)(newidt); + curidt.size = limit; + curidt.address = (unsigned long)newidt; __asm__ __volatile__ ( - "lidt %0\n" - : "=m" (curidt) + "lidtl %0\n" + : : "m" (curidt) ); }; static void set_gdt(void *newgdt, __u16 limit) { - unsigned char curgdt[6]; + struct Xgt_desc_struct curgdt; /* ia32 supports unaligned loads & stores */ - (*(__u16 *)(curgdt)) = limit; - (*(__u32 *)(curgdt +2)) = (unsigned long)(newgdt); + curgdt.size = limit; + curgdt.address = (unsigned long)newgdt; __asm__ __volatile__ ( - "lgdt %0\n" - : "=m" (curgdt) + "lgdtl %0\n" + : : "m" (curgdt) ); }; diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index af917f609c7d..ce838abb27d8 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -1116,7 +1116,15 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) */ int irq = gsi; if (gsi < MAX_GSI_NUM) { - gsi = pci_irq++; + if (gsi > 15) + gsi = pci_irq++; +#ifdef CONFIG_ACPI_BUS + /* + * Don't assign IRQ used by ACPI SCI + */ + if (gsi == acpi_fadt.sci_int) + gsi = pci_irq++; +#endif gsi_to_irq[irq] = gsi; } else { printk(KERN_ERR "GSI %u is too high\n", gsi); diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c index e51edf0a6564..5f5b075f860a 100644 --- a/arch/i386/kernel/numaq.c +++ b/arch/i386/kernel/numaq.c @@ -31,6 +31,7 @@ #include <linux/nodemask.h> #include <asm/numaq.h> #include <asm/topology.h> +#include <asm/processor.h> #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) @@ -77,3 +78,11 @@ int __init get_memcfg_numaq(void) smp_dump_qct(); return 1; } + +static int __init numaq_dsc_disable(void) +{ + printk(KERN_DEBUG "NUMAQ: disabling TSC\n"); + tsc_disable = 1; + return 0; +} +core_initcall(numaq_dsc_disable); diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 468500a7e894..9b21a31d4f4e 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -251,7 +251,7 @@ ENTRY(sys_call_table) .long sys_io_submit .long sys_io_cancel .long sys_fadvise64 /* 250 */ - .long sys_set_zone_reclaim + .long sys_ni_syscall .long sys_exit_group .long sys_lookup_dcookie .long sys_epoll_create diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index b358f0702a44..c369a8bf7cbe 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c @@ -243,6 +243,14 @@ static unsigned long calculate_numa_remap_pages(void) /* now the roundup is correct, convert to PAGE_SIZE pages */ size = size * PTRS_PER_PTE; + if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) { + /* + * Adjust size if node_end_pfn is not on a proper + * pmd boundary. remap_numa_kva will barf otherwise. + */ + size += node_end_pfn[nid] & (PTRS_PER_PTE-1); + } + /* * Validate the region we are allocating only contains valid * pages. diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index 2db65ec45dc3..42913f43feb0 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c @@ -30,6 +30,7 @@ static int __init pci_acpi_init(void) acpi_irq_penalty_init(); pcibios_scanned++; pcibios_enable_irq = acpi_pci_irq_enable; + pcibios_disable_irq = acpi_pci_irq_disable; if (pci_routeirq) { /* diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 70bcd53451f6..ade5bc57c34c 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -254,3 +254,9 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pcibios_enable_irq(dev); } + +void pcibios_disable_device (struct pci_dev *dev) +{ + if (pcibios_disable_irq) + pcibios_disable_irq(dev); +} diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index d291fb7f1357..86348b68fda1 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -56,6 +56,7 @@ struct irq_router_handler { }; int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; +void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; /* * Check passed address for the PCI IRQ Routing Table signature diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index a80f0f55ff51..127d53ad16be 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -73,3 +73,4 @@ extern int pcibios_scanned; extern spinlock_t pci_config_lock; extern int (*pcibios_enable_irq)(struct pci_dev *dev); +extern void (*pcibios_disable_irq)(struct pci_dev *dev); diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 66946f3fdac7..9be53e1ea404 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1573,7 +1573,7 @@ sys_call_table: data8 sys_keyctl data8 sys_ioprio_set data8 sys_ioprio_get // 1275 - data8 sys_set_zone_reclaim + data8 sys_ni_syscall data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 3c4707280a52..8a2b77bc5749 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -205,8 +205,7 @@ static long last_rtc_update = 0; * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void -do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { #ifndef CONFIG_SMP profile_tick(CPU_PROFILING, regs); @@ -221,6 +220,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ + write_seqlock(&xtime_lock); if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2 @@ -231,6 +231,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) else /* do it again in 60 s */ last_rtc_update = xtime.tv_sec - 600; } + write_sequnlock(&xtime_lock); /* As we return to user mode fire off the other CPU schedulers.. this is basically because we don't yet share IRQ's around. This message is rigged to be safe on the 386 - basically it's @@ -238,14 +239,8 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); + smp_send_timer(); #endif -} - -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, NULL, regs); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index ac48b6d2aff6..aec15270d334 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -160,13 +160,13 @@ good_area: printk("handle_mm_fault returns %d\n",fault); #endif switch (fault) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto bus_err; default: goto out_of_memory; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index eaa701479f5f..0ad945d4c0a4 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -178,17 +178,17 @@ good_area: */ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) { - case 1: + case VM_FAULT_MINOR: ++current->min_flt; break; - case 2: + case VM_FAULT_MAJOR: ++current->maj_flt; break; - case 0: + case VM_FAULT_SIGBUS: /* - * We ran out of memory, or some other thing happened - * to us that made us unable to handle the page fault - * gracefully. + * We hit a hared mapping outside of the file, or some + * other thing happened to us that made us unable to + * handle the page fault gracefully. */ goto bad_area; default: diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 2c2da9b43b7a..f6db3b385fea 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -558,6 +558,7 @@ config PPC_MULTIPLATFORM config APUS bool "Amiga-APUS" + depends on BROKEN help Select APUS if configuring for a PowerUP Amiga. More information is available at: @@ -647,6 +648,7 @@ config PAL4 config GEMINI bool "Synergy-Gemini" + depends on BROKEN help Select Gemini if configuring for a Synergy Microsystems' Gemini series Single Board Computer. More information is available at: diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index 991b4cbb83c8..d4dc4fa79647 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -61,6 +61,12 @@ zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE end-$(CONFIG_EMBEDDEDBOOT) := embedded misc-$(CONFIG_EMBEDDEDBOOT) := misc-embedded.o + zimage-$(CONFIG_BAMBOO) := zImage-TREE +zimageinitrd-$(CONFIG_BAMBOO) := zImage.initrd-TREE + end-$(CONFIG_BAMBOO) := bamboo + entrypoint-$(CONFIG_BAMBOO) := 0x01000000 + extra.o-$(CONFIG_BAMBOO) := pibs.o + zimage-$(CONFIG_EBONY) := zImage-TREE zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE end-$(CONFIG_EBONY) := ebony diff --git a/arch/ppc/boot/simple/pibs.c b/arch/ppc/boot/simple/pibs.c index 1348740e503f..67222d57c345 100644 --- a/arch/ppc/boot/simple/pibs.c +++ b/arch/ppc/boot/simple/pibs.c @@ -91,9 +91,11 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16); memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6); -#ifdef CONFIG_440GX +#if defined(CONFIG_440GX) || defined(CONFIG_440EP) mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16); memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6); +#endif +#ifdef CONFIG_440GX mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16); memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6); mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16); diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig new file mode 100644 index 000000000000..0ba4e70d50b6 --- /dev/null +++ b/arch/ppc/configs/bamboo_defconfig @@ -0,0 +1,943 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.12 +# Tue Jun 28 15:24:25 2005 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# 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_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=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_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Processor +# +# CONFIG_6xx is not set +# CONFIG_40x is not set +CONFIG_44x=y +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_PPC_FPU=y +CONFIG_BOOKE=y +CONFIG_PTE_64BIT=y +CONFIG_PHYS_64BIT=y +# CONFIG_MATH_EMULATION is not set +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +CONFIG_4xx=y + +# +# IBM 4xx options +# +CONFIG_BAMBOO=y +# CONFIG_EBONY is not set +# CONFIG_LUAN is not set +# CONFIG_OCOTEA is not set +CONFIG_440EP=y +CONFIG_440=y +CONFIG_IBM440EP_ERR42=y +CONFIG_IBM_OCP=y +# CONFIG_PPC4xx_DMA is not set +CONFIG_PPC_GEN550=y +# CONFIG_PM is not set +CONFIG_NOT_COHERENT_CACHE=y + +# +# Platform options +# +# CONFIG_PC_KEYBOARD is not set +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_HIGHMEM is not set +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_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 +CONFIG_BOOT_LOAD=0x01000000 + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM 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 +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +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 + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +# CONFIG_BLK_DEV_SD is not set +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR 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_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# 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 is not set +CONFIG_IP_PNP_BOOTP=y +# 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_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES 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 +# +# 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 +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_IBM_EMAC=y +# CONFIG_IBM_EMAC_ERRMSG is not set +CONFIG_IBM_EMAC_RXB=64 +CONFIG_IBM_EMAC_TXB=8 +CONFIG_IBM_EMAC_FGAP=8 +CONFIG_IBM_EMAC_SKBRES=0 +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=y +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +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 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=y +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# 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 + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB 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=y +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set +CONFIG_BDI_SWITCH=y +# CONFIG_SERIAL_TEXT_DEBUG is not set +CONFIG_PPC_OCP=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 50936cda0af9..8a3d74f2531e 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -852,6 +852,26 @@ struct cpu_spec cpu_specs[] = { #endif /* CONFIG_40x */ #ifdef CONFIG_44x + { + .pvr_mask = 0xf0000fff, + .pvr_value = 0x40000850, + .cpu_name = "440EP Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { + .pvr_mask = 0xf0000fff, + .pvr_value = 0x400008d3, + .cpu_name = "440EP Rev. B", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ + .icache_bsize = 32, + .dcache_bsize = 32, + }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index d4df68629cc6..cb83045e2edf 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -215,6 +215,7 @@ syscall_dotrace_cont: lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ mtlr r10 addi r9,r1,STACK_FRAME_OVERHEAD + PPC440EP_ERR42 blrl /* Call handler */ .globl ret_from_syscall ret_from_syscall: diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 6c7ae6052464..69ff3a9961e8 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -179,24 +179,26 @@ skpinv: addi r4,r4,1 /* Increment */ 4: #ifdef CONFIG_SERIAL_TEXT_DEBUG /* - * Add temporary UART mapping for early debug. This - * mapping must be identical to that used by the early - * bootloader code since the same asm/serial.h parameters - * are used for polled operation. + * Add temporary UART mapping for early debug. + * We can map UART registers wherever we want as long as they don't + * interfere with other system mappings (e.g. with pinned entries). + * For an example of how we handle this - see ocotea.h. --ebs */ /* pageid fields */ lis r3,UART0_IO_BASE@h - ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M + ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K /* xlat fields */ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ +#ifndef CONFIG_440EP ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ +#endif /* attrib fields */ li r5,0 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) - li r0,1 /* TLB slot 1 */ + li r0,0 /* TLB slot 0 */ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ @@ -228,6 +230,16 @@ skpinv: addi r4,r4,1 /* Increment */ lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ mtspr SPRN_IVPR,r4 +#ifdef CONFIG_440EP + /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */ + mfspr r2,SPRN_CCR0 + lis r3,0xffef + ori r3,r3,0xffff + and r2,r2,r3 + mtspr SPRN_CCR0,r2 + isync +#endif + /* * This is where the main kernel code starts. */ diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 191a8def3bdb..ce71b4a01585 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1145,6 +1145,7 @@ _GLOBAL(kernel_thread) stwu r0,-16(r1) mtlr r30 /* fn addr in lr */ mr r3,r31 /* load arg and call fn */ + PPC440EP_ERR42 blrl li r0,__NR_exit /* exit if function returns */ li r3,0 @@ -1451,3 +1452,6 @@ _GLOBAL(sys_call_table) .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/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index a0612a86455a..f7c045764e04 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -68,6 +68,11 @@ choice depends on 44x default EBONY +config BAMBOO + bool "Bamboo" + help + This option enables support for the IBM PPC440EP evaluation board. + config EBONY bool "Ebony" help @@ -98,6 +103,12 @@ config NP405H depends on ASH default y +config 440EP + bool + depends on BAMBOO + select PPC_FPU + default y + config 440GP bool depends on EBONY @@ -115,7 +126,7 @@ config 440SP config 440 bool - depends on 440GP || 440SP + depends on 440GP || 440SP || 440EP default y config 440A @@ -123,6 +134,11 @@ config 440A depends on 440GX default y +config IBM440EP_ERR42 + bool + depends on 440EP + default y + # All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool @@ -142,7 +158,7 @@ config BOOKE config IBM_OCP bool - depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y config XILINX_OCP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index ea470c6adbb6..844c3b5066e8 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -2,6 +2,7 @@ # Makefile for the PowerPC 4xx linux kernel. obj-$(CONFIG_ASH) += ash.o +obj-$(CONFIG_BAMBOO) += bamboo.o obj-$(CONFIG_CPCI405) += cpci405.o obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o @@ -19,6 +20,7 @@ obj-$(CONFIG_405GP) += ibm405gp.o obj-$(CONFIG_REDWOOD_5) += ibmstb4.o obj-$(CONFIG_NP405H) += ibmnp405h.o obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o +obj-$(CONFIG_440EP) += ibm440ep.o obj-$(CONFIG_440GP) += ibm440gp.o obj-$(CONFIG_440GX) += ibm440gx.o obj-$(CONFIG_440SP) += ibm440sp.o diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c new file mode 100644 index 000000000000..f116787b0b76 --- /dev/null +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -0,0 +1,427 @@ +/* + * arch/ppc/platforms/4xx/bamboo.c + * + * Bamboo board specific routines + * + * Wade Farnsworth <wfarnsworth@mvista.com> + * Copyright 2004 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/types.h> +#include <linux/major.h> +#include <linux/blkdev.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/ide.h> +#include <linux/initrd.h> +#include <linux/irq.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/ethtool.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/ocp.h> +#include <asm/pci-bridge.h> +#include <asm/time.h> +#include <asm/todc.h> +#include <asm/bootinfo.h> +#include <asm/ppc4xx_pic.h> +#include <asm/ppcboot.h> + +#include <syslib/gen550.h> +#include <syslib/ibm440gx_common.h> + +/* + * This is a horrible kludge, we eventually need to abstract this + * generic PHY stuff, so the standard phy mode defines can be + * easily used from arch code. + */ +#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" + +bd_t __res; + +static struct ibm44x_clocks clocks __initdata; + +/* + * Bamboo external IRQ triggering/polarity settings + */ +unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: Ethernet transceiver */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ1: Expansion connector */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ4: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ5: PCI slot 3 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ6: SMI pushbutton */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ7: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */ +}; + +static void __init +bamboo_calibrate_decr(void) +{ + unsigned int freq; + + if (mfspr(SPRN_CCR1) & CCR1_TCS) + freq = BAMBOO_TMRCLK; + else + freq = clocks.cpu; + + ibm44x_calibrate_decr(freq); + +} + +static int +bamboo_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: IBM\n"); + seq_printf(m, "machine\t\t: PPC440EP EVB (Bamboo)\n"); + + return 0; +} + +static inline int +bamboo_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 28, 28, 28, 28 }, /* IDSEL 1 - PCI Slot 0 */ + { 27, 27, 27, 27 }, /* IDSEL 2 - PCI Slot 1 */ + { 26, 26, 26, 26 }, /* IDSEL 3 - PCI Slot 2 */ + { 25, 25, 25, 25 }, /* IDSEL 4 - PCI Slot 3 */ + }; + + const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static void __init bamboo_set_emacdata(void) +{ + unsigned char * selection1_base; + struct ocp_def *def; + struct ocp_func_emac_data *emacdata; + u8 selection1_val; + int mode; + + selection1_base = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16); + selection1_val = readb(selection1_base); + iounmap((void *) selection1_base); + if (BAMBOO_SEL_MII(selection1_val)) + mode = PHY_MODE_MII; + else if (BAMBOO_SEL_RMII(selection1_val)) + mode = PHY_MODE_RMII; + else + mode = PHY_MODE_SMII; + + /* Set mac_addr and phy mode for each EMAC */ + + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); + emacdata = def->additions; + memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); + emacdata->phy_mode = mode; + + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1); + emacdata = def->additions; + memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); + emacdata->phy_mode = mode; +} + +static int +bamboo_exclude_device(unsigned char bus, unsigned char devfn) +{ + return (bus == 0 && devfn == 0); +} + +#define PCI_READW(offset) \ + (readw((void *)((u32)pci_reg_base+offset))) + +#define PCI_WRITEW(value, offset) \ + (writew(value, (void *)((u32)pci_reg_base+offset))) + +#define PCI_WRITEL(value, offset) \ + (writel(value, (void *)((u32)pci_reg_base+offset))) + +static void __init +bamboo_setup_pci(void) +{ + void *pci_reg_base; + unsigned long memory_size; + memory_size = ppc_md.find_end_of_memory(); + + pci_reg_base = ioremap64(BAMBOO_PCIL0_BASE, BAMBOO_PCIL0_SIZE); + + /* Enable PCI I/O, Mem, and Busmaster cycles */ + PCI_WRITEW(PCI_READW(PCI_COMMAND) | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER, PCI_COMMAND); + + /* Disable region first */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM0MA); + + /* PLB starting addr: 0x00000000A0000000 */ + PCI_WRITEL(BAMBOO_PCI_PHY_MEM_BASE, BAMBOO_PCIL0_PMM0LA); + + /* PCI start addr, 0xA0000000 (PCI Address) */ + PCI_WRITEL(BAMBOO_PCI_MEM_BASE, BAMBOO_PCIL0_PMM0PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM0PCIHA); + + /* Enable no pre-fetch, enable region */ + PCI_WRITEL(((0xffffffff - + (BAMBOO_PCI_UPPER_MEM - BAMBOO_PCI_MEM_BASE)) | 0x01), + BAMBOO_PCIL0_PMM0MA); + + /* Disable region one */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1LA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCIHA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); + + /* Disable region two */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2LA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCIHA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); + + /* Now configure the PCI->PLB windows, we only use PTM1 + * + * For Inbound flow, set the window size to all available memory + * This is required because if size is smaller, + * then Eth/PCI DD would fail as PCI card not able to access + * the memory allocated by DD. + */ + + PCI_WRITEL(0, BAMBOO_PCIL0_PTM1MS); /* disabled region 1 */ + PCI_WRITEL(0, BAMBOO_PCIL0_PTM1LA); /* begin of address map */ + + memory_size = 1 << fls(memory_size - 1); + + /* Size low + Enabled */ + PCI_WRITEL((0xffffffff - (memory_size - 1)) | 0x1, BAMBOO_PCIL0_PTM1MS); + + eieio(); + iounmap(pci_reg_base); +} + +static void __init +bamboo_setup_hose(void) +{ + unsigned int bar_response, bar; + struct pci_controller *hose; + + bamboo_setup_pci(); + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + hose->pci_mem_offset = BAMBOO_PCI_MEM_OFFSET; + + pci_init_resource(&hose->io_resource, + BAMBOO_PCI_LOWER_IO, + BAMBOO_PCI_UPPER_IO, + IORESOURCE_IO, + "PCI host bridge"); + + pci_init_resource(&hose->mem_resources[0], + BAMBOO_PCI_LOWER_MEM, + BAMBOO_PCI_UPPER_MEM, + IORESOURCE_MEM, + "PCI host bridge"); + + ppc_md.pci_exclude_device = bamboo_exclude_device; + + hose->io_space.start = BAMBOO_PCI_LOWER_IO; + hose->io_space.end = BAMBOO_PCI_UPPER_IO; + hose->mem_space.start = BAMBOO_PCI_LOWER_MEM; + hose->mem_space.end = BAMBOO_PCI_UPPER_MEM; + isa_io_base = + (unsigned long)ioremap64(BAMBOO_PCI_IO_BASE, BAMBOO_PCI_IO_SIZE); + hose->io_base_virt = (void *)isa_io_base; + + setup_indirect_pci(hose, + BAMBOO_PCI_CFGA_PLB32, + BAMBOO_PCI_CFGD_PLB32); + hose->set_cfg_type = 1; + + /* Zero config bars */ + for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { + early_write_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + 0x00000000); + early_read_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + &bar_response); + } + + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = bamboo_map_irq; +} + +TODC_ALLOC(); + +static void __init +bamboo_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440EP_UART0_ADDR, 8); + port.irq = 0; + port.uartclk = clocks.uart0; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(0, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART1_ADDR, 8); + port.irq = 1; + port.uartclk = clocks.uart1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(1, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART2_ADDR, 8); + port.irq = 3; + port.uartclk = clocks.uart2; + port.line = 2; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 2 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(2, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART3_ADDR, 8); + port.irq = 4; + port.uartclk = clocks.uart3; + port.line = 3; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 3 failed\n"); + } +} + +static void __init +bamboo_setup_arch(void) +{ + + bamboo_set_emacdata(); + + ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ocp_sys_info.opb_bus_freq = clocks.opb; + + /* Setup TODC access */ + TODC_INIT(TODC_TYPE_DS1743, + 0, + 0, + ioremap64(BAMBOO_RTC_ADDR, BAMBOO_RTC_SIZE), + 8); + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCI host bridge */ + bamboo_setup_hose(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + + bamboo_early_serial_map(); + + /* Identify the system */ + printk("IBM Bamboo port (MontaVista Software, Inc. (source@mvista.com))\n"); +} + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) + __res = *(bd_t *)(r3 + KERNELBASE); + + + ibm44x_platform_init(); + + ppc_md.setup_arch = bamboo_setup_arch; + ppc_md.show_cpuinfo = bamboo_show_cpuinfo; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.calibrate_decr = bamboo_calibrate_decr; + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = bamboo_early_serial_map; +#endif +} + diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h new file mode 100644 index 000000000000..63d714504148 --- /dev/null +++ b/arch/ppc/platforms/4xx/bamboo.h @@ -0,0 +1,136 @@ +/* + * arch/ppc/platforms/bamboo.h + * + * Bamboo board definitions + * + * Wade Farnsworth <wfarnsworth@mvista.com> + * + * Copyright 2004 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_BAMBOO_H__ +#define __ASM_BAMBOO_H__ + +#include <linux/config.h> +#include <platforms/4xx/ibm440ep.h> + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0x0EF600E00 + +/* Location of MAC addresses in PIBS image */ +#define PIBS_FLASH_BASE 0xfff00000 +#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0xc0400) +#define PIBS_MAC_SIZE 0x200 +#define PIBS_MAC_OFFSET 0x100 + +/* Default clock rate */ +#define BAMBOO_TMRCLK 25000000 + +/* RTC/NVRAM location */ +#define BAMBOO_RTC_ADDR 0x080000000ULL +#define BAMBOO_RTC_SIZE 0x2000 + +/* FPGA Registers */ +#define BAMBOO_FPGA_ADDR 0x080002000ULL + +#define BAMBOO_FPGA_CONFIG2_REG_ADDR (BAMBOO_FPGA_ADDR + 0x1) +#define BAMBOO_FULL_DUPLEX_EN(x) (x & 0x08) +#define BAMBOO_FORCE_100Mbps(x) (x & 0x04) +#define BAMBOO_AUTONEGOTIATE(x) (x & 0x02) + +#define BAMBOO_FPGA_SETTING_REG_ADDR (BAMBOO_FPGA_ADDR + 0x3) +#define BAMBOO_BOOT_SMALL_FLASH(x) (!(x & 0x80)) +#define BAMBOO_LARGE_FLASH_EN(x) (!(x & 0x40)) +#define BAMBOO_BOOT_NAND_FLASH(x) (!(x & 0x20)) + +#define BAMBOO_FPGA_SELECTION1_REG_ADDR (BAMBOO_FPGA_ADDR + 0x4) +#define BAMBOO_SEL_MII(x) (x & 0x80) +#define BAMBOO_SEL_RMII(x) (x & 0x40) +#define BAMBOO_SEL_SMII(x) (x & 0x20) + +/* Flash */ +#define BAMBOO_SMALL_FLASH_LOW 0x087f00000ULL +#define BAMBOO_SMALL_FLASH_HIGH 0x0fff00000ULL +#define BAMBOO_SMALL_FLASH_SIZE 0x100000 +#define BAMBOO_LARGE_FLASH_LOW 0x087800000ULL +#define BAMBOO_LARGE_FLASH_HIGH1 0x0ff800000ULL +#define BAMBOO_LARGE_FLASH_HIGH2 0x0ffc00000ULL +#define BAMBOO_LARGE_FLASH_SIZE 0x400000 +#define BAMBOO_SRAM_LOW 0x087f00000ULL +#define BAMBOO_SRAM_HIGH1 0x0fff00000ULL +#define BAMBOO_SRAM_HIGH2 0x0ff800000ULL +#define BAMBOO_SRAM_SIZE 0x100000 +#define BAMBOO_NAND_FLASH_REG_ADDR 0x090000000ULL +#define BAMBOO_NAND_FLASH_REG_SIZE 0x2000 + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 4 + +#define UART0_IO_BASE 0xEF600300 +#define UART1_IO_BASE 0xEF600400 +#define UART2_IO_BASE 0xEF600500 +#define UART3_IO_BASE 0xEF600600 + +#define BASE_BAUD 33177600/3/16 +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 3 +#define UART3_INT 4 + +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) \ + STD_UART_OP(2) \ + STD_UART_OP(3) + +/* PCI support */ +#define BAMBOO_PCI_CFGA_PLB32 0xeec00000 +#define BAMBOO_PCI_CFGD_PLB32 0xeec00004 + +#define BAMBOO_PCI_IO_BASE 0x00000000e8000000ULL +#define BAMBOO_PCI_IO_SIZE 0x00010000 +#define BAMBOO_PCI_MEM_OFFSET 0x00000000 +#define BAMBOO_PCI_PHY_MEM_BASE 0x00000000a0000000ULL + +#define BAMBOO_PCI_LOWER_IO 0x00000000 +#define BAMBOO_PCI_UPPER_IO 0x0000ffff +#define BAMBOO_PCI_LOWER_MEM 0xa0000000 +#define BAMBOO_PCI_UPPER_MEM 0xafffffff +#define BAMBOO_PCI_MEM_BASE 0xa0000000 + +#define BAMBOO_PCIL0_BASE 0x00000000ef400000ULL +#define BAMBOO_PCIL0_SIZE 0x40 + +#define BAMBOO_PCIL0_PMM0LA 0x000 +#define BAMBOO_PCIL0_PMM0MA 0x004 +#define BAMBOO_PCIL0_PMM0PCILA 0x008 +#define BAMBOO_PCIL0_PMM0PCIHA 0x00C +#define BAMBOO_PCIL0_PMM1LA 0x010 +#define BAMBOO_PCIL0_PMM1MA 0x014 +#define BAMBOO_PCIL0_PMM1PCILA 0x018 +#define BAMBOO_PCIL0_PMM1PCIHA 0x01C +#define BAMBOO_PCIL0_PMM2LA 0x020 +#define BAMBOO_PCIL0_PMM2MA 0x024 +#define BAMBOO_PCIL0_PMM2PCILA 0x028 +#define BAMBOO_PCIL0_PMM2PCIHA 0x02C +#define BAMBOO_PCIL0_PTM1MS 0x030 +#define BAMBOO_PCIL0_PTM1LA 0x034 +#define BAMBOO_PCIL0_PTM2MS 0x038 +#define BAMBOO_PCIL0_PTM2LA 0x03C + +#endif /* __ASM_BAMBOO_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index cd11734ef7c5..509e69a095f0 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -7,7 +7,7 @@ * Copyright 2002-2005 MontaVista Software Inc. * * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> - * Copyright (c) 2003, 2004 Zultys Technologies + * Copyright (c) 2003-2005 Zultys Technologies * * 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 @@ -50,6 +50,7 @@ #include <asm/bootinfo.h> #include <asm/ppc4xx_pic.h> #include <asm/ppcboot.h> +#include <asm/tlbflush.h> #include <syslib/gen550.h> #include <syslib/ibm440gp_common.h> @@ -248,6 +249,9 @@ ebony_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) /* Configure debug serial access */ gen550_init(0, &port); + + /* Purge TLB entry added in head_44x.S for early serial access */ + _tlbie(UART0_IO_BASE); #endif port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index 47c391c9174d..d08faa46a0ae 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -56,9 +56,18 @@ * Serial port defines */ -/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#if defined(__BOOTER__) +/* OpenBIOS defined UART mappings, used by bootloader shim */ #define UART0_IO_BASE 0xE0000200 #define UART1_IO_BASE 0xE0000300 +#else +/* head_44x.S created UART mapping, used before early_serial_setup. + * We cannot use default OpenBIOS UART mappings because they + * don't work for configurations with more than 512M RAM. --ebs + */ +#define UART0_IO_BASE 0xF0000200 +#define UART1_IO_BASE 0xF0000300 +#endif /* external Epson SG-615P */ #define BASE_BAUD 691200 @@ -66,7 +75,7 @@ #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: UART##num##_IO_BASE, \ + iomem_base: (void*)UART##num##_IO_BASE, \ io_type: SERIAL_IO_MEM}, #define SERIAL_PORT_DFNS \ diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c new file mode 100644 index 000000000000..284da01f1ffd --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440ep.c @@ -0,0 +1,220 @@ +/* + * arch/ppc/platforms/4xx/ibm440ep.c + * + * PPC440EP I/O descriptions + * + * Wade Farnsworth <wfarnsworth@mvista.com> + * Copyright 2004 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <platforms/4xx/ibm440ep.h> +#include <asm/ocp.h> +#include <asm/ppc4xx_pic.h> + +static struct ocp_func_emac_data ibm440ep_emac0_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = 0, /* ZMII device index */ + .zmii_mux = 0, /* ZMII input of this EMAC */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 0, /* MAL rx channel number */ + .mal_tx_chan = 0, /* MAL tx channel number */ + .wol_irq = 61, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; + +static struct ocp_func_emac_data ibm440ep_emac1_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = 0, /* ZMII device index */ + .zmii_mux = 1, /* ZMII input of this EMAC */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 1, /* MAL rx channel number */ + .mal_tx_chan = 2, /* MAL tx channel number */ + .wol_irq = 63, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; +OCP_SYSFS_EMAC_DATA() + +static struct ocp_func_mal_data ibm440ep_mal0_def = { + .num_tx_chans = 4, /* Number of TX channels */ + .num_rx_chans = 2, /* Number of RX channels */ + .txeob_irq = 10, /* TX End Of Buffer IRQ */ + .rxeob_irq = 11, /* RX End Of Buffer IRQ */ + .txde_irq = 33, /* TX Descriptor Error IRQ */ + .rxde_irq = 34, /* RX Descriptor Error IRQ */ + .serr_irq = 32, /* MAL System Error IRQ */ +}; +OCP_SYSFS_MAL_DATA() + +static struct ocp_func_iic_data ibm440ep_iic0_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; + +static struct ocp_func_iic_data ibm440ep_iic1_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; +OCP_SYSFS_IIC_DATA() + +struct ocp_def core_ocp[] = { + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_OPB, + .index = 0, + .paddr = 0x0EF600000ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 0, + .paddr = PPC440EP_UART0_ADDR, + .irq = UART0_INT, + .pm = IBM_CPM_UART0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 1, + .paddr = PPC440EP_UART1_ADDR, + .irq = UART1_INT, + .pm = IBM_CPM_UART1, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 2, + .paddr = PPC440EP_UART2_ADDR, + .irq = UART2_INT, + .pm = IBM_CPM_UART2, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 3, + .paddr = PPC440EP_UART3_ADDR, + .irq = UART3_INT, + .pm = IBM_CPM_UART3, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = 0x0EF600700ULL, + .irq = 2, + .pm = IBM_CPM_IIC0, + .additions = &ibm440ep_iic0_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = 0x0EF600800ULL, + .irq = 7, + .pm = IBM_CPM_IIC1, + .additions = &ibm440ep_iic1_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 0, + .paddr = 0x0EF600B00ULL, + .irq = OCP_IRQ_NA, + .pm = IBM_CPM_GPIO0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 1, + .paddr = 0x0EF600C00ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_MAL, + .paddr = OCP_PADDR_NA, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_mal0_def, + .show = &ocp_show_mal_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 0, + .paddr = 0x0EF600E00ULL, + .irq = 60, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_emac0_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 1, + .paddr = 0x0EF600F00ULL, + .irq = 62, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_emac1_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_ZMII, + .paddr = 0x0EF600D00ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_INVALID + } +}; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffbffe03, + .triggering = 0xfffffe00, + .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ + }, + { .polarity = 0xffffc6ef, + .triggering = 0xffffc7ff, + .ext_irq_mask = 0x00003800, /* IRQ7 - IRQ9 */ + }, +}; + +static struct resource usb_gadget_resources[] = { + [0] = { + .start = 0x050000100ULL, + .end = 0x05000017FULL, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 55, + .end = 55, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 dma_mask = 0xffffffffULL; + +static struct platform_device usb_gadget_device = { + .name = "musbhsfc", + .id = 0, + .num_resources = ARRAY_SIZE(usb_gadget_resources), + .resource = usb_gadget_resources, + .dev = { + .dma_mask = &dma_mask, + .coherent_dma_mask = 0xffffffffULL, + } +}; + +static struct platform_device *ibm440ep_devs[] __initdata = { + &usb_gadget_device, +}; + +static int __init +ibm440ep_platform_add_devices(void) +{ + return platform_add_devices(ibm440ep_devs, ARRAY_SIZE(ibm440ep_devs)); +} +arch_initcall(ibm440ep_platform_add_devices); + diff --git a/arch/ppc/platforms/4xx/ibm440ep.h b/arch/ppc/platforms/4xx/ibm440ep.h new file mode 100644 index 000000000000..97c80b8e3e10 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440ep.h @@ -0,0 +1,76 @@ +/* + * arch/ppc/platforms/4xx/ibm440ep.h + * + * PPC440EP definitions + * + * Wade Farnsworth <wfarnsworth@mvista.com> + * + * Copyright 2002 Roland Dreier + * Copyright 2004 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_IBM440EP_H +#define __PPC_PLATFORMS_IBM440EP_H + +#include <linux/config.h> +#include <asm/ibm44x.h> + +/* UART */ +#define PPC440EP_UART0_ADDR 0x0EF600300 +#define PPC440EP_UART1_ADDR 0x0EF600400 +#define PPC440EP_UART2_ADDR 0x0EF600500 +#define PPC440EP_UART3_ADDR 0x0EF600600 +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 3 +#define UART3_INT 4 + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_USB1H 0x08000000 /* USB 1.1 Host */ +#define IBM_CPM_FPU 0x04000000 /* floating point unit */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bus Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB4 0x00040000 /* PLB4 bus arbiter */ +#define IBM_CPM_PLB4x3 0x00020000 /* PLB4 to PLB3 bridge controller */ +#define IBM_CPM_PLB3x4 0x00010000 /* PLB3 to PLB4 bridge controller */ +#define IBM_CPM_PLB3 0x00008000 /* PLB3 bus arbiter */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ +#define IBM_CPM_EMAC0 0x00000020 /* ethernet port 0 */ +#define IBM_CPM_EMAC1 0x00000010 /* ethernet port 1 */ +#define IBM_CPM_UART2 0x00000008 /* serial port 2 */ +#define IBM_CPM_UART3 0x00000004 /* serial port 3 */ +#define IBM_CPM_USB2D 0x00000002 /* USB 2.0 Device */ +#define IBM_CPM_USB2H 0x00000001 /* USB 2.0 Host */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_BGO | IBM_CPM_FPU \ + | IBM_CPM_EBM | IBM_CPM_PLB4 | IBM_CPM_3x4 \ + | IBM_CPM_PLB3 | IBM_CPM_PLB4x3 \ + | IBM_CPM_EMAC0 | IBM_CPM_TMRCLK \ + | IBM_CPM_DMA | IBM_CPM_PCI | IBM_CPM_EMAC1) + + +#endif /* __PPC_PLATFORMS_IBM440EP_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 5f82a6bc7046..8fc34a344769 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -48,6 +48,7 @@ #include <asm/bootinfo.h> #include <asm/ppc4xx_pic.h> #include <asm/ppcboot.h> +#include <asm/tlbflush.h> #include <syslib/gen550.h> #include <syslib/ibm440gx_common.h> @@ -266,6 +267,9 @@ ocotea_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) /* Configure debug serial access */ gen550_init(0, &port); + + /* Purge TLB entry added in head_44x.S for early serial access */ + _tlbie(UART0_IO_BASE); #endif port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h index 202dc8251190..33251153ac5f 100644 --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -55,15 +55,24 @@ */ #define RS_TABLE_SIZE 2 -/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#if defined(__BOOTER__) +/* OpenBIOS defined UART mappings, used by bootloader shim */ #define UART0_IO_BASE 0xE0000200 #define UART1_IO_BASE 0xE0000300 +#else +/* head_44x.S created UART mapping, used before early_serial_setup. + * We cannot use default OpenBIOS UART mappings because they + * don't work for configurations with more than 512M RAM. --ebs + */ +#define UART0_IO_BASE 0xF0000200 +#define UART1_IO_BASE 0xF0000300 +#endif #define BASE_BAUD 11059200/16 #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: UART##num##_IO_BASE, \ + iomem_base: (void*)UART##num##_IO_BASE, \ io_type: SERIAL_IO_MEM}, #define SERIAL_PORT_DFNS \ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index dec5bf4f6879..220a65ab0a51 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_IBM_OCP) += ibm_ocp.o obj-$(CONFIG_44x) += ibm44x_common.o +obj-$(CONFIG_440EP) += ibm440gx_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o obj-$(CONFIG_440GX) += ibm440gx_common.o obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o @@ -44,6 +45,7 @@ obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ todc_time.o +obj-$(CONFIG_BAMBOO) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index 4ad85e0e0234..d4776af6a3ca 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -34,6 +34,10 @@ void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, u32 plld = CPR_READ(DCRN_CPR_PLLD); u32 uart0 = SDR_READ(DCRN_SDR_UART0); u32 uart1 = SDR_READ(DCRN_SDR_UART1); +#ifdef CONFIG_440EP + u32 uart2 = SDR_READ(DCRN_SDR_UART2); + u32 uart3 = SDR_READ(DCRN_SDR_UART3); +#endif /* Dividers */ u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32); @@ -96,6 +100,17 @@ bypass: p->uart1 = ser_clk; else p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256); +#ifdef CONFIG_440EP + if (uart2 & 0x00800000) + p->uart2 = ser_clk; + else + p->uart2 = p->plb / __fix_zero(uart2 & 0xff, 256); + + if (uart3 & 0x00800000) + p->uart3 = ser_clk; + else + p->uart3 = p->plb / __fix_zero(uart3 & 0xff, 256); +#endif } /* Issue L2C diagnostic command */ diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h index b14eb603ce01..c16b6a5ac6ab 100644 --- a/arch/ppc/syslib/ibm44x_common.h +++ b/arch/ppc/syslib/ibm44x_common.h @@ -29,6 +29,10 @@ struct ibm44x_clocks { unsigned int ebc; /* PerClk */ unsigned int uart0; unsigned int uart1; +#ifdef CONFIG_440EP + unsigned int uart2; + unsigned int uart3; +#endif }; /* common 44x platform init */ diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 59f4f9973818..a05b50b738e9 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -1129,6 +1129,9 @@ _GLOBAL(sys_call_table32) .llong .compat_sys_waitid .llong .sys32_ioprio_set .llong .sys32_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch .balign 8 _GLOBAL(sys_call_table) @@ -1407,3 +1410,6 @@ _GLOBAL(sys_call_table) .llong .sys_waitid .llong .sys_ioprio_set .llong .sys_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 47727a6f7346..5aca01ddd81f 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -916,6 +916,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, } } +#ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { @@ -929,6 +930,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } +#endif /* CONFIG_ALTIVEC */ /* * Check for an SMT capable CPU and set the CPU feature. We do diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c index cafd91aef289..0b191f2de016 100644 --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -647,7 +647,12 @@ void __init do_init_bootmem(void) new_range: mem_start = read_n_cells(addr_cells, &memcell_buf); mem_size = read_n_cells(size_cells, &memcell_buf); - numa_domain = numa_enabled ? of_node_numa_domain(memory) : 0; + if (numa_enabled) { + numa_domain = of_node_numa_domain(memory); + if (numa_domain >= MAX_NUMNODES) + numa_domain = 0; + } else + numa_domain = 0; if (numa_domain != nid) continue; diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index 7f6e13a4b71e..05539439e6bc 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -329,13 +329,16 @@ int xmon_core(struct pt_regs *regs, int fromipi) printf("cpu 0x%x: Exception %lx %s in xmon, " "returning to main loop\n", cpu, regs->trap, getvecname(TRAP(regs))); + release_output_lock(); longjmp(xmon_fault_jmp[cpu], 1); } if (setjmp(recurse_jmp) != 0) { if (!in_xmon || !xmon_gate) { + get_output_lock(); printf("xmon: WARNING: bad recursive fault " "on cpu 0x%x\n", cpu); + release_output_lock(); goto waiting; } secondary = !(xmon_taken && cpu == xmon_owner); diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index c067435bae45..c9f2f60cfa58 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -232,7 +232,11 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer, ry = -1; asm volatile( "diag %1,%0,0xDC\n\t" - : "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc"); + : "=d" (ry) + : "d" (&appldata_parameter_list), + "m" (appldata_parameter_list), + "m" (appldata_product_id) + : "cc"); return (int) ry; } /************************ timer, work, DIAG <END> ****************************/ diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 89850b2c27ea..0865251a3f44 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc3 -# Fri Apr 22 15:30:58 2005 +# Linux kernel version: 2.6.13-rc4 +# Fri Jul 29 14:49:30 2005 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -23,10 +23,11 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y @@ -36,6 +37,8 @@ CONFIG_IKCONFIG_PROC=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -51,9 +54,10 @@ CONFIG_BASE_SMALL=0 # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -81,8 +85,15 @@ CONFIG_MARCH_G5=y # CONFIG_MARCH_Z990 is not set CONFIG_PACK_STACK=y # CONFIG_SMALL_STACK is not set -# CONFIG_CHECK_STACK is not set +CONFIG_CHECK_STACK=y +CONFIG_STACK_GUARD=256 # CONFIG_WARN_STACK is not set +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 # # I/O subsystem configuration @@ -95,7 +106,7 @@ CONFIG_QDIO=y # # Misc # -# CONFIG_PREEMPT is not set +CONFIG_PREEMPT=y CONFIG_IPL=y # CONFIG_IPL_TAPE is not set CONFIG_IPL_VM=y @@ -105,9 +116,110 @@ CONFIG_BINFMT_MISC=m CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set # CONFIG_CMM is not set -# CONFIG_VIRT_TIMER is not set +CONFIG_VIRT_TIMER=y +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_APPLDATA_BASE is not set CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y +# CONFIG_KEXEC is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE 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=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL 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 +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set +CONFIG_NET_SCH_CBQ=m +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_INGRESS is not set +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set # CONFIG_PCMCIA is not set # @@ -133,6 +245,7 @@ CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -205,7 +318,13 @@ CONFIG_MD_RAID5=m # CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m # CONFIG_MD_FAULTY is not set -# CONFIG_BLK_DEV_DM is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_MIRROR=y +CONFIG_DM_ZERO=y +CONFIG_DM_MULTIPATH=y +# CONFIG_DM_MULTIPATH_EMC is not set # # Character device drivers @@ -231,7 +350,8 @@ CONFIG_CCW_CONSOLE=y CONFIG_SCLP=y CONFIG_SCLP_TTY=y CONFIG_SCLP_CONSOLE=y -# CONFIG_SCLP_VT220_TTY is not set +CONFIG_SCLP_VT220_TTY=y +CONFIG_SCLP_VT220_CONSOLE=y CONFIG_SCLP_CPI=m CONFIG_S390_TAPE=m @@ -255,105 +375,8 @@ CONFIG_S390_TAPE_34XX=m CONFIG_Z90CRYPT=m # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE 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=y -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_NETFILTER is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER 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=y -CONFIG_NET_SCH_CLK_JIFFIES=y -# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set -# CONFIG_NET_SCH_CLK_CPU is not set -CONFIG_NET_SCH_CBQ=m -# CONFIG_NET_SCH_HTB is not set -# CONFIG_NET_SCH_HFSC is not set -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -# CONFIG_NET_SCH_NETEM is not set -# CONFIG_NET_SCH_INGRESS is not set -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -# CONFIG_NET_CLS_BASIC is not set -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -# CONFIG_CLS_U32_PERF is not set -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -# CONFIG_NET_EMATCH is not set -# CONFIG_NET_CLS_ACT is not set -CONFIG_NET_CLS_POLICE=y - -# -# 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=m CONFIG_BONDING=m @@ -411,12 +434,15 @@ CONFIG_CCWGROUP=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 # # 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 @@ -426,6 +452,7 @@ CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set # # XFS support @@ -433,6 +460,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_XFS_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 @@ -457,7 +485,6 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y # CONFIG_TMPFS_XATTR is not set @@ -486,15 +513,18 @@ CONFIG_RAMFS=y # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set CONFIG_NFSD_TCP=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -544,11 +574,12 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=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 is not set +CONFIG_DEBUG_FS=y # # Security options diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 799a98eac92d..23fe94e58688 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1449,3 +1449,29 @@ compat_sys_kexec_load_wrapper: llgtr %r4,%r4 # struct kexec_segment * llgfr %r5,%r5 # unsigned long jg compat_sys_kexec_load + + .globl sys_ioprio_set_wrapper +sys_ioprio_set_wrapper: + lgfr %r2,%r2 # int + lgfr %r3,%r3 # int + lgfr %r4,%r4 # int + jg sys_ioprio_set + + .globl sys_ioprio_get_wrapper +sys_ioprio_get_wrapper: + lgfr %r2,%r2 # int + lgfr %r3,%r3 # int + jg sys_ioprio_get + + .globl sys_inotify_add_watch_wrapper +sys_inotify_add_watch_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + llgfr %r4,%r4 # u32 + jg sys_inotify_add_watch + + .globl sys_inotify_rm_watch_wrapper +sys_inotify_rm_watch_wrapper: + lgfr %r2,%r2 # int + llgfr %r3,%r3 # u32 + jg sys_inotify_rm_watch diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index d12cff11b4bc..2710e66fefba 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -346,6 +346,13 @@ iplstart: la %r2,.Lreset lhi %r3,26 diag %r2,%r3,8 + la %r5,.Lirb + stsch 0(%r5) # check if irq is pending + tm 30(%r5),0x0f # by verifying if any of the + bnz .Lwaitforirq # activity or status control + tm 31(%r5),0xff # bits is set in the schib + bz .Lnoreset +.Lwaitforirq: mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw .Lwaitrdrirq: lpsw .Lrdrwaitpsw diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 10bc592c3637..9a8263a153cb 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -345,6 +345,13 @@ iplstart: la %r2,.Lreset lhi %r3,26 diag %r2,%r3,8 + la %r5,.Lirb + stsch 0(%r5) # check if irq is pending + tm 30(%r5),0x0f # by verifying if any of the + bnz .Lwaitforirq # activity or status control + tm 31(%r5),0xff # bits is set in the schib + bz .Lnoreset +.Lwaitforirq: mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw .Lwaitrdrirq: lpsw .Lrdrwaitpsw diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 2721c3a32b84..5aa71b05b8ae 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -70,6 +70,8 @@ machine_kexec(struct kimage *image) for (;;); } +extern void pfault_fini(void); + static void kexec_halt_all_cpus(void *kernel_image) { @@ -78,6 +80,11 @@ kexec_halt_all_cpus(void *kernel_image) struct kimage *image; relocate_kernel_t data_mover; +#ifdef CONFIG_PFAULT + if (MACHINE_IS_VM) + pfault_fini(); +#endif + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) signal_processor(smp_processor_id(), sigp_stop); diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S index d5e4a62fbb79..2a25ec7147ff 100644 --- a/arch/s390/kernel/relocate_kernel.S +++ b/arch/s390/kernel/relocate_kernel.S @@ -4,6 +4,7 @@ * (C) Copyright IBM Corp. 2005 * * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com> + * Heiko Carstens <heiko.carstens@de.ibm.com> * */ @@ -25,8 +26,31 @@ relocate_kernel: basr %r13,0 #base address .base: - spx zero64-.base(%r13) #absolute addressing mode stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external) + spx zero64-.base(%r13) #absolute addressing mode + stctl %c0,%c15,ctlregs-.base(%r13) + stm %r0,%r15,gprregs-.base(%r13) + la %r1,load_psw-.base(%r13) + mvc 0(8,%r0),0(%r1) + la %r0,.back-.base(%r13) + st %r0,4(%r0) + oi 4(%r0),0x80 + mvc 0x68(8,%r0),0(%r1) + la %r0,.back_pgm-.base(%r13) + st %r0,0x6c(%r0) + oi 0x6c(%r0),0x80 + lhi %r0,0 + diag %r0,%r0,0x308 + .back: + basr %r13,0 + .back_base: + oi have_diag308-.back_base(%r13),0x01 + lctl %c0,%c15,ctlregs-.back_base(%r13) + lm %r0,%r15,gprregs-.back_base(%r13) + j .start_reloc + .back_pgm: + lm %r0,%r15,gprregs-.base(%r13) + .start_reloc: lhi %r10,-1 #preparing the mask sll %r10,12 #shift it such that it becomes 0xf000 .top: @@ -63,6 +87,10 @@ o %r3,4(%r4) #or load address into psw st %r3,4(%r4) mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0 + tm have_diag308-.base(%r13),0x01 + jno .no_diag308 + diag %r0,%r0,0x308 + .no_diag308: sr %r1,%r1 #clear %r1 sr %r2,%r2 #clear %r2 sigp %r1,%r2,0x12 #set cpuid to zero @@ -75,6 +103,17 @@ .long 0x00080000,0x80000000 sys_msk: .quad 0 + ctlregs: + .rept 16 + .long 0 + .endr + gprregs: + .rept 16 + .long 0 + .endr + have_diag308: + .byte 0 + .align 8 relocate_kernel_end: .globl relocate_kernel_len relocate_kernel_len: diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S index 96290cc4eb3c..8cdb86e8911f 100644 --- a/arch/s390/kernel/relocate_kernel64.S +++ b/arch/s390/kernel/relocate_kernel64.S @@ -4,6 +4,7 @@ * (C) Copyright IBM Corp. 2005 * * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com> + * Heiko Carstens <heiko.carstens@de.ibm.com> * */ @@ -26,8 +27,34 @@ relocate_kernel: basr %r13,0 #base address .base: + stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQs spx zero64-.base(%r13) #absolute addressing mode - stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external) + stctg %c0,%c15,ctlregs-.base(%r13) + stmg %r0,%r15,gprregs-.base(%r13) + lghi %r0,3 + sllg %r0,%r0,31 + stg %r0,0x1d0(%r0) + la %r0,.back_pgm-.base(%r13) + stg %r0,0x1d8(%r0) + la %r1,load_psw-.base(%r13) + mvc 0(8,%r0),0(%r1) + la %r0,.back-.base(%r13) + st %r0,4(%r0) + oi 4(%r0),0x80 + lghi %r0,0 + diag %r0,%r0,0x308 + .back: + lhi %r1,1 #mode 1 = esame + sigp %r1,%r0,0x12 #switch to esame mode + sam64 #switch to 64 bit addressing mode + basr %r13,0 + .back_base: + oi have_diag308-.back_base(%r13),0x01 + lctlg %c0,%c15,ctlregs-.back_base(%r13) + lmg %r0,%r15,gprregs-.back_base(%r13) + j .top + .back_pgm: + lmg %r0,%r15,gprregs-.base(%r13) .top: lghi %r7,4096 #load PAGE_SIZE in r7 lghi %r9,4096 #load PAGE_SIZE in r9 @@ -62,6 +89,10 @@ o %r3,4(%r4) #or load address into psw st %r3,4(%r4) mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0 + tm have_diag308-.base(%r13),0x01 + jno .no_diag308 + diag %r0,%r0,0x308 + .no_diag308: sam31 #31 bit mode sr %r1,%r1 #erase register r1 sr %r2,%r2 #erase register r2 @@ -75,8 +106,18 @@ .long 0x00080000,0x80000000 sys_msk: .quad 0 + ctlregs: + .rept 16 + .quad 0 + .endr + gprregs: + .rept 16 + .quad 0 + .endr + have_diag308: + .byte 0 + .align 8 relocate_kernel_end: .globl relocate_kernel_len relocate_kernel_len: .quad relocate_kernel_end - relocate_kernel - diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index da77f001af8d..85222fee4361 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -537,7 +537,8 @@ int __devinit start_secondary(void *cpuvoid) #endif #ifdef CONFIG_PFAULT /* Enable pfault pseudo page faults on this cpu. */ - pfault_init(); + if (MACHINE_IS_VM) + pfault_init(); #endif /* Mark this cpu as online */ cpu_set(smp_processor_id(), cpu_online_map); @@ -690,7 +691,8 @@ __cpu_disable(void) #ifdef CONFIG_PFAULT /* Disable pfault pseudo page faults on this cpu. */ - pfault_fini(); + if (MACHINE_IS_VM) + pfault_fini(); #endif /* disable all external interrupts */ diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index a8668afb5f87..426d7cafdab3 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -290,3 +290,8 @@ SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper) SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper) SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */ 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_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index bc7b7be7acbe..6b8703ec2ae6 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/kallsyms.h> +#include <linux/reboot.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -675,6 +676,19 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs) panic("Corrupt kernel stack, can't continue."); } +#ifndef CONFIG_ARCH_S390X +static int +pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + if (MACHINE_IS_VM) + cpcmd("SET PAGEX OFF", NULL, 0, NULL); + return NOTIFY_DONE; +} + +static struct notifier_block pagex_reboot_notifier = { + .notifier_call = &pagex_reboot_event, +}; +#endif /* init is done in lowcore.S and head.S */ @@ -735,6 +749,7 @@ void __init trap_init(void) &ext_int_pfault); #endif #ifndef CONFIG_ARCH_S390X + register_reboot_notifier(&pagex_reboot_notifier); cpcmd("SET PAGEX ON", NULL, 0, NULL); #endif } diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index a24932881dbb..f08d0eaf6497 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c @@ -223,13 +223,13 @@ good_area: */ survive: switch (handle_mm_fault(mm, vma, address, writeaccess)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index d6c31a95b887..de17d4c6e02d 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -19,6 +19,8 @@ harddog-objs := harddog_kern.o harddog_user.o LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) +targets := pcap_kern.o pcap_user.o + $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) #XXX: The call below does not work because the flags are added before the @@ -26,7 +28,7 @@ $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o #$(call if_changed,ld) # When the above is fixed, don't forget to add this too! -#targets := $(obj)/pcap.o +#targets += $(obj)/pcap.o obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o obj-$(CONFIG_SSL) += ssl.o diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 404de41a4f67..c190c2414197 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -557,7 +557,7 @@ static int create_proc_mconsole(void) ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); if(ent == NULL){ - printk("create_proc_mconsole : create_proc_entry failed\n"); + printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n"); return(0); } diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 0ea87f24b36f..d21ebad666b4 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -48,7 +48,7 @@ static int make_proc_exitcode(void) ent = create_proc_entry("exitcode", 0600, &proc_root); if(ent == NULL){ - printk("make_proc_exitcode : Failed to register " + printk(KERN_WARNING "make_proc_exitcode : Failed to register " "/proc/exitcode\n"); return(0); } diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 8b01a5584e80..67acd92c5322 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -131,7 +131,7 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack, return(arg.pid); } -static int ptrace_child(void) +static int ptrace_child(void *arg) { int ret; int pid = os_getpid(), ppid = getppid(); @@ -160,16 +160,20 @@ static int ptrace_child(void) _exit(ret); } -static int start_ptraced_child(void) +static int start_ptraced_child(void **stack_out) { + void *stack; + unsigned long sp; int pid, n, status; - pid = fork(); - if(pid == 0) - ptrace_child(); - + stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(stack == MAP_FAILED) + panic("check_ptrace : mmap failed, errno = %d", errno); + sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); + pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); if(pid < 0) - panic("check_ptrace : fork failed, errno = %d", errno); + panic("check_ptrace : clone failed, errno = %d", errno); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); @@ -177,6 +181,7 @@ static int start_ptraced_child(void) panic("check_ptrace : expected SIGSTOP, got status = %d", status); + *stack_out = stack; return(pid); } @@ -184,12 +189,12 @@ static int start_ptraced_child(void) * just avoid using sysemu, not panic, but only if SYSEMU features are broken. * So only for SYSEMU features we test mustpanic, while normal host features * must work anyway!*/ -static int stop_ptraced_child(int pid, int exitcode, int mustexit) +static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic) { int status, n, ret = 0; if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) - panic("stop_ptraced_child : ptrace failed, errno = %d", errno); + panic("check_ptrace : ptrace failed, errno = %d", errno); CATCH_EINTR(n = waitpid(pid, &status, 0)); if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); @@ -200,13 +205,15 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) printk("check_ptrace : child exited with exitcode %d, while " "expecting %d; status 0x%x", exit_with, exitcode, status); - if (mustexit) + if (mustpanic) panic("\n"); else printk("\n"); ret = -1; } + if(munmap(stack, PAGE_SIZE) < 0) + panic("check_ptrace : munmap failed, errno = %d", errno); return ret; } @@ -242,11 +249,12 @@ __uml_setup("nosysemu", nosysemu_cmd_param, static void __init check_sysemu(void) { + void *stack; int pid, syscall, n, status, count=0; printk("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) goto fail; @@ -264,7 +272,7 @@ static void __init check_sysemu(void) panic("check_sysemu : failed to modify system " "call return, errno = %d", errno); - if (stop_ptraced_child(pid, 0, 0) < 0) + if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 1; @@ -272,7 +280,7 @@ static void __init check_sysemu(void) set_using_sysemu(!force_sysemu_disabled); printk("Checking advanced syscall emulation patch for ptrace..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); while(1){ count++; if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) @@ -297,7 +305,7 @@ static void __init check_sysemu(void) break; } } - if (stop_ptraced_child(pid, 0, 0) < 0) + if (stop_ptraced_child(pid, stack, 0, 0) < 0) goto fail_stopped; sysemu_supported = 2; @@ -308,17 +316,18 @@ static void __init check_sysemu(void) return; fail: - stop_ptraced_child(pid, 1, 0); + stop_ptraced_child(pid, stack, 1, 0); fail_stopped: printk("missing\n"); } void __init check_ptrace(void) { + void *stack; int pid, syscall, n, status; printk("Checking that ptrace can change system call numbers..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno); @@ -345,7 +354,7 @@ void __init check_ptrace(void) break; } } - stop_ptraced_child(pid, 0, 1); + stop_ptraced_child(pid, stack, 0, 1); printk("OK\n"); check_sysemu(); } @@ -380,10 +389,11 @@ extern void *__syscall_stub_start, __syscall_stub_end; static inline void check_skas3_ptrace_support(void) { struct ptrace_faultinfo fi; + void *stack; int pid, n; printf("Checking for the skas3 patch in the host..."); - pid = start_ptraced_child(); + pid = start_ptraced_child(&stack); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { @@ -402,7 +412,7 @@ static inline void check_skas3_ptrace_support(void) } init_registers(pid); - stop_ptraced_child(pid, 1, 1); + stop_ptraced_child(pid, stack, 1, 1); } int can_do_skas(void) diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index d4036ed680bc..c23d8a08d0ff 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -412,7 +412,7 @@ int __init make_proc_sysemu(void) if (ent == NULL) { - printk("Failed to register /proc/sysemu\n"); + printk(KERN_WARNING "Failed to register /proc/sysemu\n"); return(0); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index ba671dab8878..6dd9e5bf18ed 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -64,7 +64,7 @@ void wait_stub_done(int pid, int sig, char * fname) (WSTOPSIG(status) == SIGVTALRM)); if((n < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){ + (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ panic("%s : failed to wait for SIGUSR1/SIGTRAP, " "pid = %d, n = %d, errno = %d, status = 0x%x\n", fname, pid, n, errno, status); diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c index 0dee1d95c806..9950a6716fe5 100644 --- a/arch/um/kernel/skas/trap_user.c +++ b/arch/um/kernel/skas/trap_user.c @@ -58,7 +58,6 @@ void user_signal(int sig, union uml_pt_regs *regs, int pid) int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || (sig == SIGILL) || (sig == SIGTRAP)); - regs->skas.is_user = 1; if (segv) get_skas_faultinfo(pid, ®s->skas.faultinfo); info = &sig_info[sig]; diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index a8b4ef601f59..4e08f7545d63 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -137,7 +137,10 @@ long um_stime(int __user *tptr) void timer_handler(int sig, union uml_pt_regs *regs) { local_irq_disable(); - update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), (regs)->skas.is_user)); + irq_enter(); + update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), + (regs)->skas.is_user)); + irq_exit(); local_irq_enable(); if(current_thread->cpu == 0) timer_irq(regs); diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 5423b1ca17c4..9416e1c29926 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -9,9 +9,10 @@ */ #include <elf.h> #include <stddef.h> +#include <asm/elf.h> #include "init.h" #include "elf_user.h" -#include <asm/elf.h> +#include "mem_user.h" #if ELF_CLASS == ELFCLASS32 typedef Elf32_auxv_t elf_auxv_t; @@ -41,6 +42,9 @@ __init void scan_elf_aux( char **envp) break; case AT_SYSINFO_EHDR: vsyscall_ehdr = auxv->a_un.a_val; + /* See if the page is under TASK_SIZE */ + if (vsyscall_ehdr < (unsigned long) envp) + vsyscall_ehdr = 0; break; case AT_HWCAP: elf_aux_hwcap = auxv->a_un.a_val; diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 75d7af9ae1d2..56d3f870926b 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -83,6 +83,9 @@ EXPORT_SYMBOL_PROTO(statfs64); EXPORT_SYMBOL_PROTO(getuid); +EXPORT_SYMBOL_PROTO(fsync); +EXPORT_SYMBOL_PROTO(fdatasync); + /* * 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/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index b251442ad0b1..68aeabe3a654 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -21,10 +21,10 @@ stub_segv_handler(int sig) __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); - /* Pop the frame pointer and return address since we need to leave + /* Load pointer to sigcontext into esp, since we need to leave * the stack in its original form when we do the sigreturn here, by * hand. */ - __asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; " - "int $0x80" : : "g" (__NR_sigreturn)); + __asm__("mov %0,%%esp ; movl %1, %%eax ; " + "int $0x80" : : "a" (sc), "g" (__NR_sigreturn)); } diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4b8326177c52..660a03a89e66 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -329,12 +329,15 @@ config HPET_EMULATE_RTC config GART_IOMMU bool "IOMMU support" + default y depends on PCI help - Support the K8 IOMMU. Needed to run systems with more than 4GB of memory + Support the IOMMU. Needed to run systems with more than 3GB of memory properly with 32-bit PCI devices that do not support DAC (Double Address Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter. Normally the kernel will take the right choice by itself. + This option includes a driver for the AMD Opteron/Athlon64 IOMMU + and a software emulation used on some other systems. If unsure, say Y. # need this always enabled with GART_IOMMU for the VIA workaround diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 428915697675..4c6ed96d5f7c 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -21,18 +21,6 @@ # # $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $ -# -# early bootup linking needs 32bit. You can either use real 32bit tools -# here or 64bit tools in 32bit mode. -# -IA32_CC := $(CC) $(CPPFLAGS) -m32 -O2 -fomit-frame-pointer -IA32_LD := $(LD) -m elf_i386 -IA32_AS := $(CC) $(AFLAGS) -m32 -Wa,--32 -traditional -c -IA32_OBJCOPY := $(CROSS_COMPILE)objcopy -IA32_CPP := $(CROSS_COMPILE)gcc -m32 -E -export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP - - LDFLAGS := -m elf_x86_64 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 569595b74c7c..776f3c866b70 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.12-rc4 -# Fri May 13 06:39:11 2005 +# Linux kernel version: 2.6.13-rc3 +# Fri Jul 22 16:47:31 2005 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -84,14 +84,27 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y CONFIG_SMP=y -# CONFIG_PREEMPT is not set CONFIG_SCHED_SMT=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y CONFIG_K8_NUMA=y # CONFIG_NUMA_EMU is not set -CONFIG_DISCONTIGMEM=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_NUMA=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_DISCONTIGMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_HAVE_DEC_LOCK=y -CONFIG_NR_CPUS=8 +CONFIG_NR_CPUS=32 CONFIG_HPET_TIMER=y CONFIG_X86_PM_TIMER=y CONFIG_HPET_EMULATE_RTC=y @@ -99,7 +112,13 @@ CONFIG_GART_IOMMU=y CONFIG_SWIOTLB=y CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y +CONFIG_PHYSICAL_START=0x100000 +# CONFIG_KEXEC is not set CONFIG_SECCOMP=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_ISA_DMA_API=y @@ -118,12 +137,11 @@ CONFIG_PM_STD_PARTITION="" CONFIG_ACPI=y CONFIG_ACPI_BOOT=y CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SLEEP_PROC_FS=y CONFIG_ACPI_AC=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y # CONFIG_ACPI_VIDEO is not set +CONFIG_ACPI_HOTKEY=m CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y @@ -154,6 +172,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set # # CPUFreq processor drivers @@ -204,6 +223,76 @@ CONFIG_SYSVIPC_COMPAT=y CONFIG_UID16=y # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE 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=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL 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 +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -308,6 +397,7 @@ CONFIG_BLK_DEV_AMD74XX=y # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_SC1200 is not set CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_IT821X is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set CONFIG_BLK_DEV_PDC202XX_NEW=y @@ -338,6 +428,7 @@ CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -372,7 +463,6 @@ CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set # CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_NV is not set @@ -410,14 +500,21 @@ CONFIG_SCSI_QLA2XXX=y # # Multi-device support (RAID and LVM) # -# CONFIG_MD is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set # # Fusion MPT device support # -CONFIG_FUSION=y -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set # # IEEE 1394 (FireWire) support @@ -430,75 +527,8 @@ CONFIG_FUSION_MAX_SGE=40 # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE 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=y -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) +# Network device support # -# 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 -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y -# 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 @@ -517,7 +547,9 @@ CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=y +# CONFIG_TYPHOON is not set # # Tulip family network device support @@ -532,7 +564,7 @@ CONFIG_NET_PCI=y CONFIG_FORCEDETH=y # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set +CONFIG_E100=y # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -553,14 +585,15 @@ CONFIG_8139TOO=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=y -# CONFIG_E1000_NAPI is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y +# CONFIG_BNX2 is not set # # Ethernet (10000 Mbit) @@ -647,7 +680,6 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y # # Character devices @@ -716,6 +748,7 @@ CONFIG_MAX_RAW_DEVS=256 # I2C support # # CONFIG_I2C is not set +# CONFIG_I2C_SENSOR is not set # # Dallas's 1-wire bus @@ -723,6 +756,12 @@ CONFIG_MAX_RAW_DEVS=256 # CONFIG_W1 is not set # +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# # Misc devices # # CONFIG_IBM_ASM is not set @@ -808,6 +847,7 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -846,12 +886,15 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set # # USB Imaging devices @@ -902,10 +945,11 @@ CONFIG_USB_MON=y # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set # -# USB ATM/DSL drivers +# USB DSL modem support # # @@ -924,6 +968,10 @@ CONFIG_USB_MON=y # CONFIG_INFINIBAND is not set # +# SN Devices +# + +# # Firmware Drivers # # CONFIG_EDD is not set @@ -935,6 +983,7 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y # CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y @@ -957,6 +1006,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_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=y @@ -986,7 +1036,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y # CONFIG_TMPFS_XATTR is not set @@ -1016,15 +1065,18 @@ CONFIG_RAMFS=y # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set CONFIG_NFSD_TCP=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index a12b19da4b59..f76217d8f579 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -4,14 +4,14 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o tls32.o \ - ia32_binfmt.o fpu32.o ptrace32.o syscall32.o + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) obj-$(CONFIG_IA32_AOUT) += ia32_aout.o -$(obj)/syscall32.o: $(src)/syscall32.c \ +$(obj)/syscall32_syscall.o: \ $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so) # Teach kbuild about targets diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c index 816a3b89f13d..adbc5f8089e9 100644 --- a/arch/x86_64/ia32/syscall32.c +++ b/arch/x86_64/ia32/syscall32.c @@ -14,16 +14,6 @@ #include <asm/tlbflush.h> #include <asm/ia32_unistd.h> -/* 32bit VDSOs mapped into user space. */ -asm(".section \".init.data\",\"aw\"\n" - "syscall32_syscall:\n" - ".incbin \"arch/x86_64/ia32/vsyscall-syscall.so\"\n" - "syscall32_syscall_end:\n" - "syscall32_sysenter:\n" - ".incbin \"arch/x86_64/ia32/vsyscall-sysenter.so\"\n" - "syscall32_sysenter_end:\n" - ".previous"); - extern unsigned char syscall32_syscall[], syscall32_syscall_end[]; extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[]; extern int sysctl_vsyscall32; diff --git a/arch/x86_64/ia32/syscall32_syscall.S b/arch/x86_64/ia32/syscall32_syscall.S new file mode 100644 index 000000000000..8f8271bdf135 --- /dev/null +++ b/arch/x86_64/ia32/syscall32_syscall.S @@ -0,0 +1,17 @@ +/* 32bit VDSOs mapped into user space. */ + + .section ".init.data","aw" + + .globl syscall32_syscall + .globl syscall32_syscall_end + +syscall32_syscall: + .incbin "arch/x86_64/ia32/vsyscall-syscall.so" +syscall32_syscall_end: + + .globl syscall32_sysenter + .globl syscall32_sysenter_end + +syscall32_sysenter: + .incbin "arch/x86_64/ia32/vsyscall-sysenter.so" +syscall32_sysenter_end: diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 28817490fdc6..096d470e280f 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -76,7 +76,7 @@ .macro FAKE_STACK_FRAME child_rip /* push in order ss, rsp, eflags, cs, rip */ - xorq %rax, %rax + xorl %eax, %eax pushq %rax /* ss */ CFI_ADJUST_CFA_OFFSET 8 pushq %rax /* rsp */ @@ -423,7 +423,7 @@ ENTRY(stub_rt_sigreturn) testl $3,CS(%rdi) je 1f swapgs -1: addl $1,%gs:pda_irqcount # RED-PEN should check preempt count +1: incl %gs:pda_irqcount # RED-PEN should check preempt count movq %gs:pda_irqstackptr,%rax cmoveq %rax,%rsp pushq %rdi # save old stack @@ -436,7 +436,7 @@ ENTRY(common_interrupt) ret_from_intr: popq %rdi cli - subl $1,%gs:pda_irqcount + decl %gs:pda_irqcount #ifdef CONFIG_DEBUG_INFO movq RBP(%rdi),%rbp #endif @@ -494,7 +494,7 @@ retint_signal: sti SAVE_REST movq $-1,ORIG_RAX(%rsp) - xorq %rsi,%rsi # oldset + xorl %esi,%esi # oldset movq %rsp,%rdi # &pt_regs call do_notify_resume RESTORE_REST @@ -752,7 +752,7 @@ child_rip: movq %rsi, %rdi call *%rax # exit - xorq %rdi, %rdi + xorl %edi, %edi call do_exit /* @@ -918,3 +918,15 @@ ENTRY(machine_check) ENTRY(call_debug) zeroentry do_call_debug +ENTRY(call_softirq) + movq %gs:pda_irqstackptr,%rax + pushq %r15 + movq %rsp,%r15 + incl %gs:pda_irqcount + cmove %rax,%rsp + call __do_softirq + movq %r15,%rsp + decl %gs:pda_irqcount + popq %r15 + ret + diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c index 69b9c25a8fc4..30c843a5efdd 100644 --- a/arch/x86_64/kernel/genapic.c +++ b/arch/x86_64/kernel/genapic.c @@ -31,6 +31,7 @@ u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; extern struct genapic apic_cluster; extern struct genapic apic_flat; +extern struct genapic apic_physflat; struct genapic *genapic = &apic_flat; @@ -44,12 +45,7 @@ void __init clustered_apic_check(void) u8 clusters, max_cluster; u8 id; u8 cluster_cnt[NUM_APIC_CLUSTERS]; - - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { - /* AMD always uses flat mode right now */ - genapic = &apic_flat; - goto print; - } + int num_cpus = 0; #if defined(CONFIG_ACPI_BUS) /* @@ -64,15 +60,34 @@ void __init clustered_apic_check(void) #endif memset(cluster_cnt, 0, sizeof(cluster_cnt)); - for (i = 0; i < NR_CPUS; i++) { id = bios_cpu_apicid[i]; - if (id != BAD_APICID) - cluster_cnt[APIC_CLUSTERID(id)]++; + if (id == BAD_APICID) + continue; + num_cpus++; + cluster_cnt[APIC_CLUSTERID(id)]++; } + /* Don't use clustered mode on AMD platforms. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + genapic = &apic_physflat; +#ifndef CONFIG_CPU_HOTPLUG + /* In the CPU hotplug case we cannot use broadcast mode + because that opens a race when a CPU is removed. + Stay at physflat mode in this case. + It is bad to do this unconditionally though. Once + we have ACPI platform support for CPU hotplug + we should detect hotplug capablity from ACPI tables and + only do this when really needed. -AK */ + if (num_cpus <= 8) + genapic = &apic_flat; +#endif + goto print; + } + clusters = 0; max_cluster = 0; + for (i = 0; i < NUM_APIC_CLUSTERS; i++) { if (cluster_cnt[i] > 0) { ++clusters; diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c index 282846965080..adc96282a9e2 100644 --- a/arch/x86_64/kernel/genapic_flat.c +++ b/arch/x86_64/kernel/genapic_flat.c @@ -2,13 +2,11 @@ * Copyright 2004 James Cleverdon, IBM. * Subject to the GNU Public License, v.2 * - * Flat APIC subarch code. Maximum 8 CPUs, logical delivery. + * Flat APIC subarch code. * * Hacked for x86-64 by James Cleverdon from i386 architecture code by * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. - * Ashok Raj <ashok.raj@intel.com> - * Removed IPI broadcast shortcut to support CPU hotplug */ #include <linux/config.h> #include <linux/threads.h> @@ -20,47 +18,6 @@ #include <asm/smp.h> #include <asm/ipi.h> -/* - * The following permit choosing broadcast IPI shortcut v.s sending IPI only - * to online cpus via the send_IPI_mask varient. - * The mask version is my preferred option, since it eliminates a lot of - * other extra code that would need to be written to cleanup intrs sent - * to a CPU while offline. - * - * Sending broadcast introduces lots of trouble in CPU hotplug situations. - * These IPI's are delivered to cpu's irrespective of their offline status - * and could pickup stale intr data when these CPUS are turned online. - * - * Not using broadcast is a cleaner approach IMO, but Andi Kleen disagrees with - * the idea of not using broadcast IPI's anymore. Hence the run time check - * is introduced, on his request so we can choose an alternate mechanism. - * - * Initial wacky performance tests that collect cycle counts show - * no increase in using mask v.s broadcast version. In fact they seem - * identical in terms of cycle counts. - * - * if we need to use broadcast, we need to do the following. - * - * cli; - * hold call_lock; - * clear any pending IPI, just ack and clear all pending intr - * set cpu_online_map; - * release call_lock; - * sti; - * - * The complicated dummy irq processing shown above is not required if - * we didnt sent IPI's to wrong CPU's in the first place. - * - * - Ashok Raj <ashok.raj@intel.com> - */ -#ifdef CONFIG_HOTPLUG_CPU -#define DEFAULT_SEND_IPI (1) -#else -#define DEFAULT_SEND_IPI (0) -#endif - -static int no_broadcast=DEFAULT_SEND_IPI; - static cpumask_t flat_target_cpus(void) { return cpu_online_map; @@ -119,37 +76,15 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector) local_irq_restore(flags); } -static inline void __local_flat_send_IPI_allbutself(int vector) -{ - if (no_broadcast) { - cpumask_t mask = cpu_online_map; - int this_cpu = get_cpu(); - - cpu_clear(this_cpu, mask); - flat_send_IPI_mask(mask, vector); - put_cpu(); - } - else - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL); -} - -static inline void __local_flat_send_IPI_all(int vector) -{ - if (no_broadcast) - flat_send_IPI_mask(cpu_online_map, vector); - else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); -} - static void flat_send_IPI_allbutself(int vector) { if (((num_online_cpus()) - 1) >= 1) - __local_flat_send_IPI_allbutself(vector); + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL); } static void flat_send_IPI_all(int vector) { - __local_flat_send_IPI_all(vector); + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } static int flat_apic_id_registered(void) @@ -170,16 +105,6 @@ static unsigned int phys_pkg_id(int index_msb) return ((ebx >> 24) & 0xFF) >> index_msb; } -static __init int no_ipi_broadcast(char *str) -{ - get_option(&str, &no_broadcast); - printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" : - "IPI Broadcast"); - return 1; -} - -__setup("no_ipi_broadcast", no_ipi_broadcast); - struct genapic apic_flat = { .name = "flat", .int_delivery_mode = dest_LowestPrio, @@ -195,11 +120,62 @@ struct genapic apic_flat = { .phys_pkg_id = phys_pkg_id, }; -static int __init print_ipi_mode(void) +/* + * Physflat mode is used when there are more than 8 CPUs on a AMD system. + * We cannot use logical delivery in this case because the mask + * overflows, so use physical mode. + */ + +static cpumask_t physflat_target_cpus(void) +{ + return cpumask_of_cpu(0); +} + +static void physflat_send_IPI_mask(cpumask_t cpumask, int vector) +{ + send_IPI_mask_sequence(cpumask, vector); +} + +static void physflat_send_IPI_allbutself(int vector) +{ + cpumask_t allbutme = cpu_online_map; + int me = get_cpu(); + cpu_clear(me, allbutme); + physflat_send_IPI_mask(allbutme, vector); + put_cpu(); +} + +static void physflat_send_IPI_all(int vector) { - printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" : - "Shortcut"); - return 0; + physflat_send_IPI_mask(cpu_online_map, vector); } -late_initcall(print_ipi_mode); +static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + cpu = first_cpu(cpumask); + if ((unsigned)cpu < NR_CPUS) + return x86_cpu_to_apicid[cpu]; + else + return BAD_APICID; +} + +struct genapic apic_physflat = { + .name = "physical flat", + .int_delivery_mode = dest_LowestPrio, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST, + .target_cpus = physflat_target_cpus, + .apic_id_registered = flat_apic_id_registered, + .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/ + .send_IPI_all = physflat_send_IPI_all, + .send_IPI_allbutself = physflat_send_IPI_allbutself, + .send_IPI_mask = physflat_send_IPI_mask, + .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, + .phys_pkg_id = phys_pkg_id, +}; diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 8d765aa77a26..98ff5eb32b9a 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -137,14 +137,14 @@ startup_64: wrmsr /* Setup cr0 */ - xorq %rax, %rax - btsq $31, %rax /* Enable paging */ - btsq $0, %rax /* Enable protected mode */ - btsq $1, %rax /* Enable MP */ - btsq $4, %rax /* Enable ET */ - btsq $5, %rax /* Enable NE */ - btsq $16, %rax /* Enable WP */ - btsq $18, %rax /* Enable AM */ +#define CR0_PM 1 /* protected mode */ +#define CR0_MP (1<<1) +#define CR0_ET (1<<4) +#define CR0_NE (1<<5) +#define CR0_WP (1<<16) +#define CR0_AM (1<<18) +#define CR0_PAGING (1<<31) + movl $CR0_PM|CR0_MP|CR0_ET|CR0_NE|CR0_WP|CR0_AM|CR0_PAGING,%eax /* Make changes effective */ movq %rax, %cr0 diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index cc3fb85f5145..849a20aec7ca 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -135,3 +135,22 @@ void fixup_irqs(cpumask_t map) local_irq_disable(); } #endif + +extern void call_softirq(void); + +asmlinkage void do_softirq(void) +{ + __u32 pending; + unsigned long flags; + + if (in_interrupt()) + return; + + local_irq_save(flags); + pending = local_softirq_pending(); + /* Switch to interrupt stack */ + if (pending) + call_softirq(); + local_irq_restore(flags); +} +EXPORT_SYMBOL(do_softirq); diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c index 60d1eff41567..89fab51e20f4 100644 --- a/arch/x86_64/kernel/machine_kexec.c +++ b/arch/x86_64/kernel/machine_kexec.c @@ -8,43 +8,26 @@ #include <linux/mm.h> #include <linux/kexec.h> -#include <linux/delay.h> #include <linux/string.h> #include <linux/reboot.h> -#include <asm/pda.h> #include <asm/pgtable.h> -#include <asm/pgalloc.h> #include <asm/tlbflush.h> #include <asm/mmu_context.h> #include <asm/io.h> -#include <asm/apic.h> -#include <asm/cpufeature.h> -#include <asm/hw_irq.h> - -#define LEVEL0_SIZE (1UL << 12UL) -#define LEVEL1_SIZE (1UL << 21UL) -#define LEVEL2_SIZE (1UL << 30UL) -#define LEVEL3_SIZE (1UL << 39UL) -#define LEVEL4_SIZE (1UL << 48UL) - -#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE) -#define L2_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -#define L3_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) - -static void init_level2_page(u64 *level2p, unsigned long addr) + +static void init_level2_page(pmd_t *level2p, unsigned long addr) { unsigned long end_addr; addr &= PAGE_MASK; - end_addr = addr + LEVEL2_SIZE; + end_addr = addr + PUD_SIZE; while (addr < end_addr) { - *(level2p++) = addr | L1_ATTR; - addr += LEVEL1_SIZE; + set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); + addr += PMD_SIZE; } } -static int init_level3_page(struct kimage *image, u64 *level3p, +static int init_level3_page(struct kimage *image, pud_t *level3p, unsigned long addr, unsigned long last_addr) { unsigned long end_addr; @@ -52,32 +35,32 @@ static int init_level3_page(struct kimage *image, u64 *level3p, result = 0; addr &= PAGE_MASK; - end_addr = addr + LEVEL3_SIZE; + end_addr = addr + PGDIR_SIZE; while ((addr < last_addr) && (addr < end_addr)) { struct page *page; - u64 *level2p; + pmd_t *level2p; page = kimage_alloc_control_pages(image, 0); if (!page) { result = -ENOMEM; goto out; } - level2p = (u64 *)page_address(page); + level2p = (pmd_t *)page_address(page); init_level2_page(level2p, addr); - *(level3p++) = __pa(level2p) | L2_ATTR; - addr += LEVEL2_SIZE; + set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE)); + addr += PUD_SIZE; } /* clear the unused entries */ while (addr < end_addr) { - *(level3p++) = 0; - addr += LEVEL2_SIZE; + pud_clear(level3p++); + addr += PUD_SIZE; } out: return result; } -static int init_level4_page(struct kimage *image, u64 *level4p, +static int init_level4_page(struct kimage *image, pgd_t *level4p, unsigned long addr, unsigned long last_addr) { unsigned long end_addr; @@ -85,28 +68,28 @@ static int init_level4_page(struct kimage *image, u64 *level4p, result = 0; addr &= PAGE_MASK; - end_addr = addr + LEVEL4_SIZE; + end_addr = addr + (PTRS_PER_PGD * PGDIR_SIZE); while ((addr < last_addr) && (addr < end_addr)) { struct page *page; - u64 *level3p; + pud_t *level3p; page = kimage_alloc_control_pages(image, 0); if (!page) { result = -ENOMEM; goto out; } - level3p = (u64 *)page_address(page); + level3p = (pud_t *)page_address(page); result = init_level3_page(image, level3p, addr, last_addr); if (result) { goto out; } - *(level4p++) = __pa(level3p) | L3_ATTR; - addr += LEVEL3_SIZE; + set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); + addr += PGDIR_SIZE; } /* clear the unused entries */ while (addr < end_addr) { - *(level4p++) = 0; - addr += LEVEL3_SIZE; + pgd_clear(level4p++); + addr += PGDIR_SIZE; } out: return result; @@ -115,52 +98,50 @@ out: static int init_pgtable(struct kimage *image, unsigned long start_pgtable) { - u64 *level4p; - level4p = (u64 *)__va(start_pgtable); + pgd_t *level4p; + level4p = (pgd_t *)__va(start_pgtable); return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT); } static void set_idt(void *newidt, u16 limit) { - unsigned char curidt[10]; + struct desc_ptr curidt; /* x86-64 supports unaliged loads & stores */ - (*(u16 *)(curidt)) = limit; - (*(u64 *)(curidt +2)) = (unsigned long)(newidt); + curidt.size = limit; + curidt.address = (unsigned long)newidt; __asm__ __volatile__ ( - "lidt %0\n" - : "=m" (curidt) + "lidtq %0\n" + : : "m" (curidt) ); }; static void set_gdt(void *newgdt, u16 limit) { - unsigned char curgdt[10]; + struct desc_ptr curgdt; /* x86-64 supports unaligned loads & stores */ - (*(u16 *)(curgdt)) = limit; - (*(u64 *)(curgdt +2)) = (unsigned long)(newgdt); + curgdt.size = limit; + curgdt.address = (unsigned long)newgdt; __asm__ __volatile__ ( - "lgdt %0\n" - : "=m" (curgdt) + "lgdtq %0\n" + : : "m" (curgdt) ); }; static void load_segments(void) { __asm__ __volatile__ ( - "\tmovl $"STR(__KERNEL_DS)",%eax\n" - "\tmovl %eax,%ds\n" - "\tmovl %eax,%es\n" - "\tmovl %eax,%ss\n" - "\tmovl %eax,%fs\n" - "\tmovl %eax,%gs\n" + "\tmovl %0,%%ds\n" + "\tmovl %0,%%es\n" + "\tmovl %0,%%ss\n" + "\tmovl %0,%%fs\n" + "\tmovl %0,%%gs\n" + : : "a" (__KERNEL_DS) ); -#undef STR -#undef __STR } typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page, @@ -178,7 +159,7 @@ int machine_kexec_prepare(struct kimage *image) /* Calculate the offsets */ start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; - control_code_buffer = start_pgtable + 4096UL; + control_code_buffer = start_pgtable + PAGE_SIZE; /* Setup the identity mapped 64bit page table */ result = init_pgtable(image, start_pgtable); @@ -214,7 +195,7 @@ NORET_TYPE void machine_kexec(struct kimage *image) /* Calculate the offsets */ page_list = image->head; start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; - control_code_buffer = start_pgtable + 4096UL; + control_code_buffer = start_pgtable + PAGE_SIZE; /* Set the low half of the page table to my identity mapped * page table for kexec. Leave the high half pointing at the diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 21e70625a495..3b267c91bb0c 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -15,6 +15,8 @@ #include <linux/sysdev.h> #include <linux/miscdevice.h> #include <linux/fs.h> +#include <linux/cpu.h> +#include <linux/percpu.h> #include <asm/processor.h> #include <asm/msr.h> #include <asm/mce.h> @@ -514,10 +516,7 @@ static struct sysdev_class mce_sysclass = { set_kset_name("machinecheck"), }; -static struct sys_device device_mce = { - .id = 0, - .cls = &mce_sysclass, -}; +static DEFINE_PER_CPU(struct sys_device, device_mce); /* Why are there no generic functions for this? */ #define ACCESSOR(name, var, start) \ @@ -542,27 +541,83 @@ ACCESSOR(bank4ctl,bank[4],mce_restart()) ACCESSOR(tolerant,tolerant,) ACCESSOR(check_interval,check_interval,mce_restart()) -static __cpuinit int mce_init_device(void) +/* Per cpu sysdev init. All of the cpus still share the same ctl bank */ +static __cpuinit int mce_create_device(unsigned int cpu) { int err; + if (!mce_available(&cpu_data[cpu])) + return -EIO; + + per_cpu(device_mce,cpu).id = cpu; + per_cpu(device_mce,cpu).cls = &mce_sysclass; + + err = sysdev_register(&per_cpu(device_mce,cpu)); + + if (!err) { + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank0ctl); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank1ctl); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank2ctl); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank3ctl); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank4ctl); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant); + sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval); + } + return err; +} + +#ifdef CONFIG_HOTPLUG_CPU +static __cpuinit void mce_remove_device(unsigned int cpu) +{ + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank0ctl); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank1ctl); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank2ctl); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank3ctl); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank4ctl); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant); + sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval); + sysdev_unregister(&per_cpu(device_mce,cpu)); +} +#endif + +/* Get notified when a cpu comes on/off. Be hotplug friendly. */ +static __cpuinit int +mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) { + case CPU_ONLINE: + mce_create_device(cpu); + break; +#ifdef CONFIG_HOTPLUG_CPU + case CPU_DEAD: + mce_remove_device(cpu); + break; +#endif + } + return NOTIFY_OK; +} + +static struct notifier_block mce_cpu_notifier = { + .notifier_call = mce_cpu_callback, +}; + +static __init int mce_init_device(void) +{ + int err; + int i = 0; + if (!mce_available(&boot_cpu_data)) return -EIO; err = sysdev_class_register(&mce_sysclass); - if (!err) - err = sysdev_register(&device_mce); - if (!err) { - /* could create per CPU objects, but it is not worth it. */ - sysdev_create_file(&device_mce, &attr_bank0ctl); - sysdev_create_file(&device_mce, &attr_bank1ctl); - sysdev_create_file(&device_mce, &attr_bank2ctl); - sysdev_create_file(&device_mce, &attr_bank3ctl); - sysdev_create_file(&device_mce, &attr_bank4ctl); - sysdev_create_file(&device_mce, &attr_tolerant); - sysdev_create_file(&device_mce, &attr_check_interval); - } - + + for_each_online_cpu(i) { + mce_create_device(i); + } + + register_cpu_notifier(&mce_cpu_notifier); misc_register(&mce_log_device); return err; - } + device_initcall(mce_init_device); diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 9c5aa2a790c7..79c362d03e2e 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -109,7 +109,7 @@ static int __init mpf_checksum(unsigned char *mp, int len) static void __init MP_processor_info (struct mpc_config_processor *m) { - int ver; + int ver, cpu; static int found_bsp=0; if (!(m->mpc_cpuflag & CPU_ENABLED)) @@ -131,7 +131,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m) return; } - num_processors++; + cpu = num_processors++; if (m->mpc_apicid > MAX_APICS) { printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", @@ -155,13 +155,18 @@ static void __init MP_processor_info (struct mpc_config_processor *m) * in same order as logical cpu numbers. Hence the first * entry is BSP, and so on. */ + cpu = 0; + bios_cpu_apicid[0] = m->mpc_apicid; x86_cpu_to_apicid[0] = m->mpc_apicid; found_bsp = 1; - } else { - bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid; - x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid; - } + } else + cpu = num_processors - found_bsp; + bios_cpu_apicid[cpu] = m->mpc_apicid; + x86_cpu_to_apicid[cpu] = m->mpc_apicid; + + cpu_set(cpu, cpu_possible_map); + cpu_set(cpu, cpu_present_map); } static void __init MP_bus_info (struct mpc_config_bus *m) @@ -965,8 +970,21 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) * due to unused I/O APIC pins. */ int irq = gsi; - gsi = pci_irq++; - gsi_to_irq[irq] = gsi; + if (gsi < MAX_GSI_NUM) { + if (gsi > 15) + gsi = pci_irq++; +#ifdef CONFIG_ACPI_BUS + /* + * Don't assign IRQ used by ACPI SCI + */ + if (gsi == acpi_fadt.sci_int) + gsi = pci_irq++; +#endif + gsi_to_irq[irq] = gsi; + } else { + printk(KERN_ERR "GSI %u is too high\n", gsi); + return gsi; + } } io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 5fd03225058a..0aa526298e92 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -765,8 +765,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) int cpu = smp_processor_id(); int node = 0; unsigned bits; - if (c->x86_num_cores == 1) - return; bits = 0; while ((1 << bits) < c->x86_num_cores) @@ -1081,8 +1079,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) else mtrr_ap_init(); #ifdef CONFIG_NUMA - if (c != &boot_cpu_data) - numa_add_cpu(c - cpu_data); + numa_add_cpu(smp_processor_id()); #endif } diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index f2b9c6bc999a..34082c1cc41e 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -12,6 +12,7 @@ #include <linux/string.h> #include <linux/bootmem.h> #include <linux/bitops.h> +#include <linux/module.h> #include <asm/bootsetup.h> #include <asm/pda.h> #include <asm/pgtable.h> @@ -22,10 +23,8 @@ #include <asm/smp.h> #include <asm/i387.h> #include <asm/percpu.h> -#include <asm/mtrr.h> #include <asm/proto.h> -#include <asm/mman.h> -#include <asm/numa.h> +#include <asm/sections.h> char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,}; @@ -33,11 +32,6 @@ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; -extern struct task_struct init_task; - -extern unsigned char __per_cpu_start[], __per_cpu_end[]; - -extern struct desc_ptr cpu_gdt_descr[]; struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table }; char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); @@ -101,7 +95,7 @@ void __init setup_per_cpu_areas(void) #endif for (i = 0; i < NR_CPUS; i++) { - unsigned char *ptr; + char *ptr; if (!NODE_DATA(cpu_to_node(i))) { printk("cpu with no node %d, num_online_nodes %d\n", @@ -190,11 +184,7 @@ void __cpuinit check_efer(void) */ void __cpuinit cpu_init (void) { -#ifdef CONFIG_SMP int cpu = stack_smp_processor_id(); -#else - int cpu = smp_processor_id(); -#endif struct tss_struct *t = &per_cpu(init_tss, cpu); unsigned long v; char *estacks = NULL; @@ -214,7 +204,7 @@ void __cpuinit cpu_init (void) printk("Initializing CPU#%d\n", cpu); - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); /* * Initialize the per-CPU GDT with the boot GDT, diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index ccae392886af..e5958220d6b8 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -129,10 +129,9 @@ asmlinkage void smp_invalidate_interrupt (void) } else leave_mm(cpu); } +out: ack_APIC_irq(); cpu_clear(cpu, flush_cpumask); - -out: put_cpu_no_resched(); } @@ -294,6 +293,69 @@ void unlock_ipi_call_lock(void) } /* + * this function sends a 'generic call function' IPI to one other CPU + * in the system. + */ +static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + struct call_data_struct data; + int cpus = 1; + + data.func = func; + data.info = info; + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + call_data = &data; + wmb(); + /* Send a message to all other CPUs and wait for them to respond */ + send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR); + + /* Wait for response */ + while (atomic_read(&data.started) != cpus) + cpu_relax(); + + if (!wait) + return; + + while (atomic_read(&data.finished) != cpus) + cpu_relax(); +} + +/* + * smp_call_function_single - Run a function on another CPU + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Currently unused. + * @wait: If true, wait until function has completed on other CPUs. + * + * Retrurns 0 on success, else a negative status code. + * + * Does not return until the remote CPU is nearly ready to execute <func> + * or is or has executed. + */ + +int smp_call_function_single (int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + /* prevent preemption and reschedule on another processor */ + int me = get_cpu(); + if (cpu == me) { + WARN_ON(1); + put_cpu(); + return -EBUSY; + } + spin_lock_bh(&call_lock); + __smp_call_function_single(cpu, func, info, nonatomic, wait); + spin_unlock_bh(&call_lock); + put_cpu(); + return 0; +} + +/* * this function sends a 'generic call function' IPI to all other CPUs * in the system. */ diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index e773a794ec45..6e4807d64d46 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -113,24 +113,6 @@ struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; #define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p)) /* - * cpu_possible_map should be static, it cannot change as cpu's - * are onlined, or offlined. The reason is per-cpu data-structures - * are allocated by some modules at init time, and dont expect to - * do this dynamically on cpu arrival/departure. - * cpu_present_map on the other hand can change dynamically. - * In case when cpu_hotplug is not compiled, then we resort to current - * behaviour, which is cpu_possible == cpu_present. - * If cpu-hotplug is supported, then we need to preallocate for all - * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range. - * - Ashok Raj - */ -#ifdef CONFIG_HOTPLUG_CPU -#define fixup_cpu_possible_map(x) cpu_set((x), cpu_possible_map) -#else -#define fixup_cpu_possible_map(x) -#endif - -/* * Currently trivial. Write the real->protected mode * bootstrap into the page concerned. The caller * has made sure it's suitably aligned. @@ -229,9 +211,6 @@ static __cpuinit void sync_master(void *arg) { unsigned long flags, i; - if (smp_processor_id() != 0) - return; - go[MASTER] = 0; local_irq_save(flags); @@ -280,7 +259,7 @@ get_delta(long *rt, long *master) return tcenter - best_tm; } -static __cpuinit void sync_tsc(void) +static __cpuinit void sync_tsc(unsigned int master) { int i, done = 0; long delta, adj, adjust_latency = 0; @@ -294,9 +273,17 @@ static __cpuinit void sync_tsc(void) } t[NUM_ROUNDS] __cpuinitdata; #endif + printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", + smp_processor_id(), master); + go[MASTER] = 1; - smp_call_function(sync_master, NULL, 1, 0); + /* It is dangerous to broadcast IPI as cpus are coming up, + * as they may not be ready to accept them. So since + * we only need to send the ipi to the boot cpu direct + * the message, and avoid the race. + */ + smp_call_function_single(master, sync_master, NULL, 1, 0); while (go[MASTER]) /* wait for master to be ready */ no_cpu_relax(); @@ -340,16 +327,14 @@ static __cpuinit void sync_tsc(void) printk(KERN_INFO "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, " "maxerr %lu cycles)\n", - smp_processor_id(), boot_cpu_id, delta, rt); + smp_processor_id(), master, delta, rt); } static void __cpuinit tsc_sync_wait(void) { if (notscsync || !cpu_has_tsc) return; - printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(), - boot_cpu_id); - sync_tsc(); + sync_tsc(boot_cpu_id); } static __init int notscsync_setup(char *s) @@ -773,8 +758,9 @@ do_rest: initial_code = start_secondary; clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK); - printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid, - start_rip, init_rsp); + printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu, + cpus_weight(cpu_present_map), + apicid); /* * This grunge runs the startup process for @@ -924,6 +910,27 @@ static __init void enforce_max_cpus(unsigned max_cpus) } } +#ifdef CONFIG_HOTPLUG_CPU +/* + * cpu_possible_map should be static, it cannot change as cpu's + * are onlined, or offlined. The reason is per-cpu data-structures + * are allocated by some modules at init time, and dont expect to + * do this dynamically on cpu arrival/departure. + * cpu_present_map on the other hand can change dynamically. + * In case when cpu_hotplug is not compiled, then we resort to current + * behaviour, which is cpu_possible == cpu_present. + * If cpu-hotplug is supported, then we need to preallocate for all + * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range. + * - Ashok Raj + */ +static void prefill_possible_map(void) +{ + int i; + for (i = 0; i < NR_CPUS; i++) + cpu_set(i, cpu_possible_map); +} +#endif + /* * Various sanity checks. */ @@ -987,25 +994,15 @@ static int __init smp_sanity_check(unsigned max_cpus) */ void __init smp_prepare_cpus(unsigned int max_cpus) { - int i; - nmi_watchdog_default(); current_cpu_data = boot_cpu_data; current_thread_info()->cpu = 0; /* needed? */ enforce_max_cpus(max_cpus); - /* - * Fill in cpu_present_mask - */ - for (i = 0; i < NR_CPUS; i++) { - int apicid = cpu_present_to_apicid(i); - if (physid_isset(apicid, phys_cpu_present_map)) { - cpu_set(i, cpu_present_map); - cpu_set(i, cpu_possible_map); - } - fixup_cpu_possible_map(i); - } +#ifdef CONFIG_HOTPLUG_CPU + prefill_possible_map(); +#endif if (smp_sanity_check(max_cpus) < 0) { printk(KERN_INFO "SMP disabled\n"); @@ -1189,8 +1186,7 @@ void __cpu_die(unsigned int cpu) printk ("CPU %d is now offline\n", cpu); return; } - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); + msleep(100); } printk(KERN_ERR "CPU %u didn't die...\n", cpu); } diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 102736630002..6ead433a3885 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -594,9 +594,6 @@ asmlinkage void default_do_nmi(struct pt_regs *regs) if (!cpu) reason = get_nmi_reason(); - if (!cpu_online(cpu)) - return; - if (!(reason & 0xc0)) { if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) == NOTIFY_STOP) diff --git a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S index 01808ec37836..72fd55ee896e 100644 --- a/arch/x86_64/lib/csum-copy.S +++ b/arch/x86_64/lib/csum-copy.S @@ -188,8 +188,8 @@ csum_partial_copy_generic: source movw (%rdi),%bx adcl %ebx,%eax - dest decl %ecx + dest movw %bx,(%rsi) leaq 2(%rdi),%rdi leaq 2(%rsi),%rsi diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c index 33a873a3c223..841bd738a189 100644 --- a/arch/x86_64/lib/delay.c +++ b/arch/x86_64/lib/delay.c @@ -18,8 +18,6 @@ #include <asm/smp.h> #endif -int x86_udelay_tsc = 0; /* Delay via TSC */ - int read_current_timer(unsigned long *timer_value) { rdtscll(*timer_value); diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 2f187986f940..493819e543a5 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -23,7 +23,6 @@ #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/compiler.h> #include <linux/module.h> -#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -440,13 +439,13 @@ good_area: * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index ac61c186eb02..70cb2904a90f 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -36,34 +36,36 @@ int numa_off __initdata; int __init compute_hash_shift(struct node *nodes, int numnodes) { int i; - int shift = 24; - u64 addr; + int shift = 20; + unsigned long addr,maxend=0; - /* When in doubt use brute force. */ - while (shift < 48) { - memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); - for (i = 0; i < numnodes; i++) { - if (nodes[i].start == nodes[i].end) - continue; - for (addr = nodes[i].start; - addr < nodes[i].end; - addr += (1UL << shift)) { - if (memnodemap[addr >> shift] != 0xff && - memnodemap[addr >> shift] != i) { - printk(KERN_INFO - "node %d shift %d addr %Lx conflict %d\n", - i, shift, addr, memnodemap[addr>>shift]); - goto next; - } - memnodemap[addr >> shift] = i; + for (i = 0; i < numnodes; i++) + if ((nodes[i].start != nodes[i].end) && (nodes[i].end > maxend)) + maxend = nodes[i].end; + + while ((1UL << shift) < (maxend / NODEMAPSIZE)) + shift++; + + printk (KERN_DEBUG"Using %d for the hash shift. Max adder is %lx \n", + shift,maxend); + memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); + for (i = 0; i < numnodes; i++) { + if (nodes[i].start == nodes[i].end) + continue; + for (addr = nodes[i].start; + addr < nodes[i].end; + addr += (1UL << shift)) { + if (memnodemap[addr >> shift] != 0xff) { + printk(KERN_INFO + "Your memory is not aligned you need to rebuild your kernel " + "with a bigger NODEMAPSIZE shift=%d adder=%lu\n", + shift,addr); + return -1; } + memnodemap[addr >> shift] = i; } - return shift; - next: - shift++; } - memset(memnodemap,0,sizeof(*memnodemap) * NODEMAPSIZE); - return -1; + return shift; } #ifdef CONFIG_SPARSEMEM diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 5d01b31472e1..8e3d097a9ddd 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -20,6 +20,9 @@ static struct acpi_table_slit *acpi_slit; +/* Internal processor count */ +static unsigned int __initdata num_processors = 0; + static nodemask_t nodes_parsed __initdata; static nodemask_t nodes_found __initdata; static struct node nodes[MAX_NUMNODES] __initdata; @@ -101,16 +104,18 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) bad_srat(); return; } - if (pa->apic_id >= NR_CPUS) { - printk(KERN_ERR "SRAT: lapic %u too large.\n", - pa->apic_id); + if (num_processors >= NR_CPUS) { + printk(KERN_ERR "SRAT: Processor #%d (lapic %u) INVALID. (Max ID: %d).\n", + num_processors, pa->apic_id, NR_CPUS); bad_srat(); return; } - cpu_to_node[pa->apic_id] = node; + cpu_to_node[num_processors] = node; acpi_numa = 1; - printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", - pxm, pa->apic_id, node); + printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> CPU %u -> Node %u\n", + pxm, pa->apic_id, num_processors, node); + + num_processors++; } /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ @@ -124,7 +129,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) if (srat_disabled() || ma->flags.enabled == 0) return; - /* hotplug bit is ignored for now */ pxm = ma->proximity_domain; node = setup_node(pxm); if (node < 0) { @@ -134,6 +138,10 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) } 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", + start, end); i = conflicting_nodes(start, end); if (i >= 0) { printk(KERN_ERR diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c index 7e7d0c2a0025..c2c38b579939 100644 --- a/arch/x86_64/pci/k8-bus.c +++ b/arch/x86_64/pci/k8-bus.c @@ -29,7 +29,7 @@ __init static int fill_mp_bus_to_cpumask(void) { struct pci_dev *nb_dev = NULL; - int i, j, printed; + int i, j; u32 ldtbus, nid; static int lbnr[3] = { LDT_BUS_NUMBER_REGISTER_0, diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 986410e7b483..ba13896cae40 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -133,9 +133,10 @@ config ACPI_HOTKEY depends on ACPI_INTERPRETER depends on EXPERIMENTAL depends on !IA64_SGI_SN - default m + default n help - ACPI generic hotkey + Experimental consolidated hotkey driver. + If you are unsure, say N. config ACPI_FAN tristate "Fan" diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 0f45d45f05a0..8162fd0c21a7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -26,6 +26,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -33,6 +36,9 @@ #define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" +#define ACPI_BUTTON_FILE_INFO "info" +#define ACPI_BUTTON_FILE_STATE "state" +#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 #define ACPI_BUTTON_NOTIFY_STATUS 0x80 #define ACPI_BUTTON_SUBCLASS_POWER "power" @@ -64,6 +70,8 @@ MODULE_LICENSE("GPL"); static int acpi_button_add (struct acpi_device *device); static int acpi_button_remove (struct acpi_device *device, int type); +static int acpi_button_info_open_fs(struct inode *inode, struct file *file); +static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, @@ -82,6 +90,179 @@ struct acpi_button { unsigned long pushed; }; +static struct file_operations acpi_button_info_fops = { + .open = acpi_button_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_button_state_fops = { + .open = acpi_button_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +static struct proc_dir_entry *acpi_button_dir; + +static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + + ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + seq_printf(seq, "type: %s\n", + acpi_device_name(button->device)); + + return_VALUE(0); +} + +static int acpi_button_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); +} + +static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + acpi_status status; + unsigned long state; + + ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); + if (ACPI_FAILURE(status)) { + seq_printf(seq, "state: unsupported\n"); + } + else{ + seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); + } + + return_VALUE(0); +} + +static int acpi_button_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); +} + +static struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_sleep_dir; +static struct proc_dir_entry *acpi_lid_dir; + +static int +acpi_button_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add_fs"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + if (!acpi_power_dir) + acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + entry = acpi_power_dir; + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + if (!acpi_sleep_dir) + acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + entry = acpi_sleep_dir; + break; + case ACPI_BUTTON_TYPE_LID: + if (!acpi_lid_dir) + acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + entry = acpi_lid_dir; + break; + } + + if (!entry) + return_VALUE(-ENODEV); + entry->owner = THIS_MODULE; + + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + acpi_device_dir(device)->owner = THIS_MODULE; + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + + /* show lid state [R] */ + if (button->type == ACPI_BUTTON_TYPE_LID) { + entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_state_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + } + + return_VALUE(0); +} + + +static int +acpi_button_remove_fs ( + struct acpi_device *device) +{ + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); + + button = acpi_driver_data(device); + if (acpi_device_dir(device)) { + if (button->type == ACPI_BUTTON_TYPE_LID) + remove_proc_entry(ACPI_BUTTON_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BUTTON_FILE_INFO, + acpi_device_dir(device)); + + remove_proc_entry(acpi_device_bid(device), + acpi_device_dir(device)->parent); + acpi_device_dir(device) = NULL; + } + + return_VALUE(0); +} + + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -121,7 +302,8 @@ acpi_button_notify_fixed ( ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); - BUG_ON(!button); + if (!button) + return_ACPI_STATUS(AE_BAD_PARAMETER); acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); @@ -197,6 +379,10 @@ acpi_button_add ( goto end; } + result = acpi_button_add_fs(device); + if (result) + goto end; + switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler ( @@ -240,6 +426,7 @@ acpi_button_add ( end: if (result) { + acpi_button_remove_fs(device); kfree(button); } @@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); + acpi_button_remove_fs(device); + kfree(button); return_VALUE(0); @@ -293,14 +482,20 @@ acpi_button_init (void) ACPI_FUNCTION_TRACE("acpi_button_init"); + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + acpi_button_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&acpi_button_driver); if (result < 0) { + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return_VALUE(-ENODEV); } return_VALUE(0); } + static void __exit acpi_button_exit (void) { @@ -308,8 +503,17 @@ acpi_button_exit (void) acpi_bus_unregister_driver(&acpi_button_driver); + if (acpi_power_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); + if (acpi_sleep_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); + if (acpi_lid_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + return_VOID; } + module_init(acpi_button_init); module_exit(acpi_button_exit); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fca4140a50a9..1ac5731d45e5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -59,76 +59,186 @@ ACPI_MODULE_NAME ("acpi_ec") #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ + #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 -static int acpi_ec_add (struct acpi_device *device); +#define EC_POLLING 0xFF +#define EC_BURST 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 struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_add, + .add = acpi_ec_polling_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, }, }; - -struct acpi_ec { - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - unsigned int expect_event; - atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ - atomic_t pending_gpe; - struct semaphore sem; - wait_queue_head_t wait; +union acpi_ec { + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + } common; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ + atomic_t pending_gpe; + struct semaphore sem; + wait_queue_head_t wait; + }burst; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + spinlock_t lock; + }polling; }; +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 acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval); + +static acpi_status __init +acpi_fake_ecdt_burst_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); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ -static struct acpi_ec *ec_ecdt; +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; /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ -static inline u32 acpi_ec_read_status(struct acpi_ec *ec) +static inline u32 acpi_ec_read_status(union acpi_ec *ec) { u32 status = 0; - acpi_hw_low_level_read(8, &status, &ec->status_addr); + acpi_hw_low_level_read(8, &status, &ec->common.status_addr); return status; } -static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) +static int +acpi_ec_wait ( + union acpi_ec *ec, + u8 event) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_wait (ec, event); + else + return acpi_ec_burst_wait (ec, event); +} + +static int +acpi_ec_polling_wait ( + union acpi_ec *ec, + u8 event) +{ + u32 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; + + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ + switch (event) { + case ACPI_EC_EVENT_OBF: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + case ACPI_EC_EVENT_IBE: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + default: + return -EINVAL; + } + + return -ETIME; +} +static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) { int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_wait"); - ec->expect_event = event; + ec->burst.expect_event = event; smp_mb(); - result = wait_event_interruptible_timeout(ec->wait, - !ec->expect_event, + result = wait_event_interruptible_timeout(ec->burst.wait, + !ec->burst.expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - ec->expect_event = 0; + ec->burst.expect_event = 0; smp_mb(); if (result < 0){ @@ -160,7 +270,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) static int acpi_ec_enter_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { u32 tmp = 0; int status = 0; @@ -170,43 +280,43 @@ acpi_ec_enter_burst_mode ( status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + 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){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); return_VALUE(-EINVAL); } - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if(tmp != 0x90 ) {/* Burst ACK byte*/ return_VALUE(-EINVAL); } } - atomic_set(&ec->leaving_burst , 0); + atomic_set(&ec->burst.leaving_burst , 0); return_VALUE(0); } static int acpi_ec_leave_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { int status =0; ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); - atomic_set(&ec->leaving_burst , 1); + atomic_set(&ec->burst.leaving_burst , 1); status = acpi_ec_read_status(ec); if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); return_VALUE(-EINVAL); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = acpi_ec_read_status(ec); } @@ -215,7 +325,131 @@ acpi_ec_leave_burst_mode ( static int acpi_ec_read ( - struct acpi_ec *ec, + union acpi_ec *ec, + u8 address, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_read(ec, address, data); + else + return acpi_ec_burst_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); + else + return acpi_ec_burst_write(ec, address, data); +} +static int +acpi_ec_polling_read ( + union acpi_ec *ec, + u8 address, + u32 *data) +{ + acpi_status status = AE_OK; + int result = 0; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_polling_write ( + union acpi_ec *ec, + u8 address, + u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_write"); + + if (!ec) + return_VALUE(-EINVAL); + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, data, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", + data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + +static int +acpi_ec_burst_read ( + union acpi_ec *ec, u8 address, u32 *data) { @@ -230,51 +464,51 @@ acpi_ec_read ( retry: *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) { goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -283,8 +517,8 @@ end: static int -acpi_ec_write ( - struct acpi_ec *ec, +acpi_ec_burst_write ( + union acpi_ec *ec, u8 address, u8 data) { @@ -297,14 +531,14 @@ acpi_ec_write ( if (!ec) return_VALUE(-EINVAL); retry: - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; @@ -312,33 +546,33 @@ retry: status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + 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) goto end; - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); if(tmp != 0x90 ) /* Burst ACK byte*/ goto end; } /*Now we are in burst mode*/ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status){ goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_write(8, data, &ec->data_addr); + acpi_hw_low_level_write(8, data, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) goto end; @@ -347,17 +581,17 @@ retry: end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -370,7 +604,7 @@ end: int ec_read(u8 addr, u8 *val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; u32 temp_data; @@ -393,7 +627,7 @@ EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; if (!first_ec) @@ -407,10 +641,66 @@ ec_write(u8 addr, u8 val) } EXPORT_SYMBOL(ec_write); - static int acpi_ec_query ( - struct acpi_ec *ec, + union acpi_ec *ec, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_query(ec, data); + else + return acpi_ec_burst_query(ec, data); +} +static int +acpi_ec_polling_query ( + union acpi_ec *ec, + u32 *data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_query"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * 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); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + if (!*data) + result = -ENODATA; + +end: + spin_unlock_irqrestore(&ec->polling.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) { int status = 0; @@ -422,13 +712,13 @@ acpi_ec_query ( return_VALUE(-EINVAL); *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; /* @@ -436,28 +726,28 @@ acpi_ec_query ( * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (!*data) status = -ENODATA; end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = -ENODATA; } return_VALUE(status); @@ -468,7 +758,7 @@ end: Event Management -------------------------------------------------------------------------- */ -struct acpi_ec_query_data { +union acpi_ec_query_data { acpi_handle handle; u8 data; }; @@ -477,7 +767,59 @@ static void acpi_ec_gpe_query ( void *ec_cxt) { - struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; + if (acpi_ec_polling_mode) + acpi_ec_gpe_polling_query(ec_cxt); + else + acpi_ec_gpe_burst_query(ec_cxt); +} + +static void +acpi_ec_gpe_polling_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; + u32 value = 0; + unsigned long flags = 0; + static char object_name[5] = {'_','Q','0','0','\0'}; + const char hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); + + if (!ec_cxt) + goto end; + + spin_lock_irqsave(&ec->polling.lock, flags); + acpi_hw_low_level_read(8, &value, &ec->common.command_addr); + spin_unlock_irqrestore(&ec->polling.lock, flags); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ + if (!(value & ACPI_EC_FLAG_SCI)) + goto end; + + if (acpi_ec_query(ec, &value)) + goto end; + + object_name[2] = hex[((value >> 4) & 0x0F)]; + object_name[3] = hex[(value & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); + +end: + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); +} +static void +acpi_ec_gpe_burst_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; u32 value; int result = -ENODATA; static char object_name[5] = {'_','Q','0','0','\0'}; @@ -497,9 +839,9 @@ acpi_ec_gpe_query ( ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - acpi_evaluate_object(ec->handle, object_name, NULL, NULL); + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - atomic_dec(&ec->pending_gpe); + atomic_dec(&ec->burst.pending_gpe); return; } @@ -507,48 +849,77 @@ static u32 acpi_ec_gpe_handler ( void *data) { + if (acpi_ec_polling_mode) + return acpi_ec_gpe_polling_handler(data); + else + return acpi_ec_gpe_burst_handler(data); +} +static u32 +acpi_ec_gpe_polling_handler ( + void *data) +{ + acpi_status status = AE_OK; + union acpi_ec *ec = (union acpi_ec *) data; + + if (!ec) + return ACPI_INTERRUPT_NOT_HANDLED; + + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, ec); + + if (status == AE_OK) + return ACPI_INTERRUPT_HANDLED; + else + return ACPI_INTERRUPT_NOT_HANDLED; +} +static u32 +acpi_ec_gpe_burst_handler ( + void *data) +{ acpi_status status = AE_OK; u32 value; - struct acpi_ec *ec = (struct acpi_ec *) data; + union acpi_ec *ec = (union acpi_ec *) data; if (!ec) return ACPI_INTERRUPT_NOT_HANDLED; - acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); if((value & ACPI_EC_FLAG_IBF) && !(value & ACPI_EC_FLAG_BURST) && - (atomic_read(&ec->leaving_burst) == 0)) { + (atomic_read(&ec->burst.leaving_burst) == 0)) { /* * the embedded controller disables * burst mode for any reason other * than the burst disable command * to process critical event. */ - atomic_set(&ec->leaving_burst , 2); /* block current pending transaction + atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction and retry */ - wake_up(&ec->wait); + wake_up(&ec->burst.wait); }else { - if ((ec->expect_event == ACPI_EC_EVENT_OBF && + if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && (value & ACPI_EC_FLAG_OBF)) || - (ec->expect_event == ACPI_EC_EVENT_IBE && + (ec->burst.expect_event == ACPI_EC_EVENT_IBE && !(value & ACPI_EC_FLAG_IBF))) { - ec->expect_event = 0; - wake_up(&ec->wait); + ec->burst.expect_event = 0; + wake_up(&ec->burst.wait); return ACPI_INTERRUPT_HANDLED; } } if (value & ACPI_EC_FLAG_SCI){ - atomic_add(1, &ec->pending_gpe) ; + atomic_add(1, &ec->burst.pending_gpe) ; status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -585,7 +956,7 @@ acpi_ec_space_handler ( void *region_context) { int result = 0; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -600,7 +971,7 @@ acpi_ec_space_handler ( return_VALUE(AE_BAD_PARAMETER); } - ec = (struct acpi_ec *) handler_context; + ec = (union acpi_ec *) handler_context; next_byte: switch (function) { @@ -661,7 +1032,7 @@ static struct proc_dir_entry *acpi_ec_dir; static int acpi_ec_read_info (struct seq_file *seq, void *offset) { - struct acpi_ec *ec = (struct acpi_ec *) seq->private; + union acpi_ec *ec = (union acpi_ec *) seq->private; ACPI_FUNCTION_TRACE("acpi_ec_read_info"); @@ -669,12 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset) goto end; seq_printf(seq, "gpe bit: 0x%02x\n", - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); seq_printf(seq, "ports: 0x%02x, 0x%02x\n", - (u32) ec->status_addr.address, (u32) ec->data_addr.address); + (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address); seq_printf(seq, "use global lock: %s\n", - ec->global_lock?"yes":"no"); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ec->common.global_lock?"yes":"no"); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); end: return_VALUE(0); @@ -697,7 +1068,7 @@ static int acpi_ec_add_fs ( struct acpi_device *device) { - struct proc_dir_entry *entry; + struct proc_dir_entry *entry = NULL; ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); @@ -744,13 +1115,14 @@ acpi_ec_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ + static int -acpi_ec_add ( +acpi_ec_polling_add ( struct acpi_device *device) { - int result; - acpi_status status; - struct acpi_ec *ec; + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -758,39 +1130,107 @@ acpi_ec_add ( if (!device) return_VALUE(-EINVAL); - ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec) return_VALUE(-ENOMEM); - memset(ec, 0, sizeof(struct acpi_ec)); - - ec->handle = device->handle; - ec->uid = -1; - atomic_set(&ec->pending_gpe, 0); - atomic_set(&ec->leaving_burst , 1); - init_MUTEX(&ec->sem); - init_waitqueue_head(&ec->wait); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + spin_lock_init(&ec->polling.lock); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); /* If our UID matches the UID for the ECDT-enumerated EC, we now have the *real* EC info, so kill the makeshift one.*/ - acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->uid == uid) { + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); + + kfree(ec_ecdt); + } + + /* Get GPE bit assignment (EC events). */ + /* TODO: Add support for _GPE returning a package */ + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error obtaining GPE bit assignment\n")); + result = -ENODEV; + goto end; + } - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); + result = acpi_ec_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->common.gpe_bit); + + if (!first_ec) + first_ec = device; + +end: + if (result) + kfree(ec); + + return_VALUE(result); +} +static int +acpi_ec_burst_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; + unsigned long uid; + + ACPI_FUNCTION_TRACE("acpi_ec_add"); + + if (!device) + return_VALUE(-EINVAL); + + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec) + return_VALUE(-ENOMEM); + memset(ec, 0, sizeof(union acpi_ec)); + + 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); + strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); + + /* If our UID matches the UID for the ECDT-enumerated EC, + we now have the *real* EC info, so kill the makeshift one.*/ + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); } /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ - status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error obtaining GPE bit assignment\n")); @@ -804,7 +1244,7 @@ acpi_ec_add ( printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", acpi_device_name(device), acpi_device_bid(device), - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); if (!first_ec) first_ec = device; @@ -822,7 +1262,7 @@ acpi_ec_remove ( struct acpi_device *device, int type) { - struct acpi_ec *ec; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_remove"); @@ -844,7 +1284,7 @@ acpi_ec_io_ports ( struct acpi_resource *resource, void *context) { - struct acpi_ec *ec = (struct acpi_ec *) context; + union acpi_ec *ec = (union acpi_ec *) context; struct acpi_generic_address *addr; if (resource->id != ACPI_RSTYPE_IO) { @@ -856,10 +1296,10 @@ acpi_ec_io_ports ( * the second address region returned is the status/command * port. */ - if (ec->data_addr.register_bit_width == 0) { - addr = &ec->data_addr; - } else if (ec->command_addr.register_bit_width == 0) { - addr = &ec->command_addr; + if (ec->common.data_addr.register_bit_width == 0) { + addr = &ec->common.data_addr; + } else if (ec->common.command_addr.register_bit_width == 0) { + addr = &ec->common.command_addr; } else { return AE_CTRL_TERMINATE; } @@ -877,8 +1317,8 @@ static int acpi_ec_start ( struct acpi_device *device) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_start"); @@ -893,35 +1333,36 @@ acpi_ec_start ( /* * Get I/O port addresses. Convert to GAS format. */ - status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, + status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec); - if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) { + if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); return_VALUE(-ENODEV); } - ec->status_addr = ec->command_addr; + ec->common.status_addr = ec->common.command_addr; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", - (u32) ec->gpe_bit, (u32) ec->command_addr.address, - (u32) ec->data_addr.address)); + (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address, + (u32) ec->common.data_addr.address)); + /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { return_VALUE(-ENODEV); } - acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = acpi_install_address_space_handler (ec->handle, + status = acpi_install_address_space_handler (ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); return_VALUE(-ENODEV); } @@ -934,8 +1375,8 @@ acpi_ec_stop ( struct acpi_device *device, int type) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_stop"); @@ -944,12 +1385,12 @@ acpi_ec_stop ( ec = acpi_driver_data(device); - status = acpi_remove_address_space_handler(ec->handle, + status = acpi_remove_address_space_handler(ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); - status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); @@ -963,26 +1404,76 @@ acpi_fake_ecdt_callback ( void *context, void **retval) { + + if (acpi_ec_polling_mode) + return acpi_fake_ecdt_polling_callback(handle, + Level, context, retval); + else + return acpi_fake_ecdt_burst_callback(handle, + Level, context, retval); +} + +static acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval) +{ acpi_status status; status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) return status; - ec_ecdt->status_addr = ec_ecdt->command_addr; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - ec_ecdt->uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - ec_ecdt->global_lock = TRUE; - ec_ecdt->handle = handle; + spin_lock_init(&ec_ecdt->polling.lock); + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", - (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address, - (u32) ec_ecdt->data_addr.address); + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); + + return AE_CTRL_TERMINATE; +} + +static acpi_status __init +acpi_fake_ecdt_burst_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); + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + acpi_ec_io_ports, ec_ecdt); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; + + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); + + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; + + printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); return AE_CTRL_TERMINATE; } @@ -1005,12 +1496,12 @@ acpi_ec_fake_ecdt(void) printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) { ret = -ENOMEM; goto error; } - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + memset(ec_ecdt, 0, sizeof(union acpi_ec)); status = acpi_get_devices (ACPI_EC_HID, acpi_fake_ecdt_callback, @@ -1031,6 +1522,60 @@ error: static int __init acpi_ec_get_real_ecdt(void) { + if (acpi_ec_polling_mode) + return acpi_ec_polling_get_real_ecdt(); + else + return acpi_ec_burst_get_real_ecdt(); +} + +static int __init +acpi_ec_polling_get_real_ecdt(void) +{ + acpi_status status; + struct acpi_table_ecdt *ecdt_ptr; + + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) &ecdt_ptr); + if (ACPI_FAILURE(status)) + return -ENODEV; + + printk(KERN_INFO PREFIX "Found ECDT\n"); + + /* + * Generate a temporary ec context to use until the namespace is scanned + */ + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec_ecdt) + return -ENOMEM; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + 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; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; + spin_lock_init(&ec_ecdt->polling.lock); + /* use the GL just to be safe */ + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; + + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); + if (ACPI_FAILURE(status)) { + goto error; + } + + return 0; +error: + printk(KERN_ERR PREFIX "Could not use ECDT\n"); + kfree(ec_ecdt); + ec_ecdt = NULL; + + return -ENODEV; +} + + +static int __init +acpi_ec_burst_get_real_ecdt(void) +{ acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1044,22 +1589,22 @@ acpi_ec_get_real_ecdt(void) /* * Generate a temporary ec context to use until the namespace is scanned */ - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) return -ENOMEM; - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); - - init_MUTEX(&ec_ecdt->sem); - init_waitqueue_head(&ec_ecdt->wait); - ec_ecdt->command_addr = ecdt_ptr->ec_control; - ec_ecdt->status_addr = ecdt_ptr->ec_control; - ec_ecdt->data_addr = ecdt_ptr->ec_data; - ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + init_MUTEX(&ec_ecdt->burst.sem); + init_waitqueue_head(&ec_ecdt->burst.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; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ - ec_ecdt->global_lock = TRUE; - ec_ecdt->uid = ecdt_ptr->uid; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; - status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); if (ACPI_FAILURE(status)) { goto error; } @@ -1092,20 +1637,20 @@ acpi_ec_ecdt_probe (void) /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec_ecdt); if (ACPI_FAILURE(status)) { goto error; } - acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec_ecdt); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); goto error; } @@ -1123,7 +1668,7 @@ error: static int __init acpi_ec_init (void) { - int result; + int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_init"); @@ -1166,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str) acpi_fake_ecdt_enabled = 1; return 0; } + __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); +static int __init acpi_ec_set_polling_mode(char *str) +{ + int burst; + + if (!get_option(&str, &burst)) + return 0; + + if (burst) { + acpi_ec_polling_mode = EC_BURST; + acpi_ec_driver.ops.add = acpi_ec_burst_add; + } else { + acpi_ec_polling_mode = EC_POLLING; + acpi_ec_driver.ops.add = acpi_ec_polling_add; + } + printk(KERN_INFO PREFIX "EC %s mode.\n", + burst ? "burst": "polling"); + return 0; +} +__setup("ec_burst=", acpi_ec_set_polling_mode); diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index babdf762eadb..1f76a40badec 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -1,5 +1,5 @@ -/* - * hotkey.c - ACPI Hotkey Driver ($Revision:$) +/* + * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) * * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> * @@ -51,17 +51,18 @@ #define ACPI_HOTKEY_POLLING 0x2 #define ACPI_UNDEFINED_EVENT 0xf -#define MAX_CONFIG_RECORD_LEN 80 -#define MAX_NAME_PATH_LEN 80 -#define MAX_CALL_PARM 80 +#define RESULT_STR_LEN 80 -#define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */ -#define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */ +#define ACTION_METHOD 0 +#define POLL_METHOD 1 +#define IS_EVENT(e) ((e) <= 10000 && (e) >0) +#define IS_POLL(e) ((e) > 10000) +#define IS_OTHERS(e) ((e)<=0 || (e)>=20000) #define _COMPONENT ACPI_HOTKEY_COMPONENT ACPI_MODULE_NAME("acpi_hotkey") - MODULE_AUTHOR("luming.yu@intel.com"); +MODULE_AUTHOR("luming.yu@intel.com"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); MODULE_LICENSE("GPL"); @@ -114,7 +115,7 @@ struct acpi_event_hotkey { char *action_method; /* action method */ }; -/* +/* * There are two ways to poll status * 1. directy call read_xxx method, without any arguments passed in * 2. call write_xxx method, with arguments passed in, you need @@ -131,7 +132,7 @@ struct acpi_polling_hotkey { char *poll_method; /* poll method */ acpi_handle action_handle; /* acpi handle attached action method */ char *action_method; /* action method */ - void *poll_result; /* polling_result */ + union acpi_object *poll_result; /* polling_result */ struct proc_dir_entry *proc; }; @@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = { }, }; +static void free_hotkey_device(union acpi_hotkey *key); +static void free_hotkey_buffer(union acpi_hotkey *key); +static void free_poll_hotkey_buffer(union acpi_hotkey *key); static int hotkey_open_config(struct inode *inode, struct file *file); +static int hotkey_poll_open_config(struct inode *inode, struct file *file); static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data); -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); static int hotkey_info_open_fs(struct inode *inode, struct file *file); static int hotkey_action_open_fs(struct inode *inode, struct file *file); static ssize_t hotkey_execute_aml_method(struct file *file, const char __user * buffer, size_t count, loff_t * data); static int hotkey_config_seq_show(struct seq_file *seq, void *offset); +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); static int hotkey_polling_open_fs(struct inode *inode, struct file *file); +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event); /* event based config */ static struct file_operations hotkey_config_fops = { @@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = { /* polling based config */ static struct file_operations hotkey_poll_config_fops = { - .open = hotkey_open_config, + .open = hotkey_poll_open_config, .read = seq_read, - .write = hotkey_write_poll_config, + .write = hotkey_write_config, .llseek = seq_lseek, .release = single_release, }; @@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset) { ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); - seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION); + seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); return_VALUE(0); } @@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) static char *format_result(union acpi_object *object) { - char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - - memset(buf, 0, sizeof(union acpi_object)); + char *buf = NULL; + + buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); + if (buf) + memset(buf, 0, RESULT_STR_LEN); + else + goto do_fail; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) - sprintf(buf, "%d", (u32) object->integer.value); - - return buf; + sprintf(buf, "%d\n", (u32) object->integer.value); +do_fail: + return (buf); } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) { struct acpi_polling_hotkey *poll_hotkey = (struct acpi_polling_hotkey *)seq->private; + char *buf; ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); - if (poll_hotkey->poll_result) - seq_printf(seq, "%s", format_result(poll_hotkey->poll_result)); - + if (poll_hotkey->poll_result){ + buf = format_result(poll_hotkey->poll_result); + if(buf) + seq_printf(seq, "%s", buf); + kfree(buf); + } return_VALUE(0); } @@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file) /* Mapping external hotkey number to standardized hotkey event num */ static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) { - struct list_head *entries, *next; - int val = 0; + struct list_head *entries; + int val = -1; ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); - list_for_each_safe(entries, next, list->entries) { + list_for_each(entries, list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->event_hotkey.external_hotkey_num == event) + && key->event_hotkey.external_hotkey_num == event){ val = key->link.hotkey_standard_num; - else - val = -1; + break; + } } return_VALUE(val); @@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) return_VOID; internal_event = hotkey_get_internal_event(event, &global_hotkey_list); - acpi_bus_generate_event(device, event, 0); + acpi_bus_generate_event(device, internal_event, 0); return_VOID; } @@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type) static int create_polling_proc(union acpi_hotkey *device) { struct proc_dir_entry *proc; + char proc_name[80]; mode_t mode; ACPI_FUNCTION_TRACE("create_polling_proc"); mode = S_IFREG | S_IRUGO | S_IWUGO; - proc = create_proc_entry(device->poll_hotkey.action_method, - mode, hotkey_proc_dir); + sprintf(proc_name, "%d", device->link.hotkey_standard_num); + /* + strcat(proc_name, device->poll_hotkey.poll_method); + */ + proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); if (!proc) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, @@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device) return_VALUE(0); } -static int is_valid_acpi_path(const char *pathname) -{ - acpi_handle handle; - acpi_status status; - ACPI_FUNCTION_TRACE("is_valid_acpi_path"); - - status = acpi_get_handle(NULL, (char *)pathname, &handle); - return_VALUE(!ACPI_FAILURE(status)); -} - -static int is_valid_hotkey(union acpi_hotkey *device) -{ - ACPI_FUNCTION_TRACE("is_valid_hotkey"); - /* Implement valid check */ - return_VALUE(1); -} - static int hotkey_add(union acpi_hotkey *device) { int status = 0; @@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device) ACPI_FUNCTION_TRACE("hotkey_add"); if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); - if (status) - return_VALUE(status); - + acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); status = acpi_install_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler, - device); + dev); } else /* Add polling hotkey */ create_polling_proc(device); @@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device) if (key->link.hotkey_standard_num == device->link.hotkey_standard_num) { list_del(&key->link.entries); - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_device(key); global_hotkey_list.count--; break; } } + kfree(device); return_VALUE(0); } -static void hotkey_update(union acpi_hotkey *key) +static int hotkey_update(union acpi_hotkey *key) { - struct list_head *entries, *next; + struct list_head *entries; ACPI_FUNCTION_TRACE("hotkey_update"); - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = + list_for_each(entries, global_hotkey_list.entries) { + union acpi_hotkey *tmp= container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == + if (tmp->link.hotkey_standard_num == key->link.hotkey_standard_num) { - key->event_hotkey.bus_handle = - key->event_hotkey.bus_handle; - key->event_hotkey.external_hotkey_num = - key->event_hotkey.external_hotkey_num; - key->event_hotkey.action_handle = - key->event_hotkey.action_handle; - key->event_hotkey.action_method = - key->event_hotkey.action_method; + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { + free_hotkey_buffer(tmp); + tmp->event_hotkey.bus_handle = + key->event_hotkey.bus_handle; + tmp->event_hotkey.external_hotkey_num = + key->event_hotkey.external_hotkey_num; + tmp->event_hotkey.action_handle = + key->event_hotkey.action_handle; + tmp->event_hotkey.action_method = + key->event_hotkey.action_method; + kfree(key); + } else { + /* + char proc_name[80]; + + sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); + strcat(proc_name, tmp->poll_hotkey.poll_method); + remove_proc_entry(proc_name,hotkey_proc_dir); + */ + free_poll_hotkey_buffer(tmp); + tmp->poll_hotkey.poll_handle = + key->poll_hotkey.poll_handle; + tmp->poll_hotkey.poll_method = + key->poll_hotkey.poll_method; + tmp->poll_hotkey.action_handle = + key->poll_hotkey.action_handle; + tmp->poll_hotkey.action_method = + key->poll_hotkey.action_method; + tmp->poll_hotkey.poll_result = + key->poll_hotkey.poll_result; + /* + create_polling_proc(tmp); + */ + kfree(key); + } + return_VALUE(0); break; } } - return_VOID; + return_VALUE(-ENODEV); } static void free_hotkey_device(union acpi_hotkey *key) { struct acpi_device *dev; - int status; ACPI_FUNCTION_TRACE("free_hotkey_device"); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); + acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); if (dev->handle) acpi_remove_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler); - } else - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_buffer(key); + } else { + char proc_name[80]; + + sprintf(proc_name, "%d", key->link.hotkey_standard_num); + /* + strcat(proc_name, key->poll_hotkey.poll_method); + */ + remove_proc_entry(proc_name,hotkey_proc_dir); + free_poll_hotkey_buffer(key); + } kfree(key); return_VOID; } +static void +free_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->event_hotkey.action_method); +} + +static void +free_poll_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->poll_hotkey.action_method); + kfree(key->poll_hotkey.poll_method); + kfree(key->poll_hotkey.poll_result); +} static int init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, char *method, int std_num, int external_num) { + acpi_handle tmp_handle; + acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE("init_hotkey_device"); + if(std_num < 0 || IS_POLL(std_num) || !key ) + goto do_fail; + + if(!bus_str || !action_str || !method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - if (is_valid_acpi_path(bus_str)) - acpi_get_handle((acpi_handle) 0, - bus_str, &(key->event_hotkey.bus_handle)); - else - return_VALUE(-ENODEV); - key->event_hotkey.external_hotkey_num = external_num; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->event_hotkey.action_handle)); - key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL); - strcpy(key->event_hotkey.action_method, method); + key->event_hotkey.action_method = method; - return_VALUE(!is_valid_hotkey(key)); + status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + key->event_hotkey.external_hotkey_num = external_num; + status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->event_hotkey.action_handle, + method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } static int @@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key, char *poll_method, char *action_str, char *action_method, int std_num) { + acpi_status status = AE_OK; + acpi_handle tmp_handle; + ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); + if(std_num < 0 || IS_EVENT(std_num) || !key) + goto do_fail; + + if(!poll_str || !poll_method || !action_str || !action_method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - if (is_valid_acpi_path(poll_str)) - acpi_get_handle((acpi_handle) 0, - poll_str, &(key->poll_hotkey.poll_handle)); - else - return_VALUE(-ENODEV); key->poll_hotkey.poll_method = poll_method; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->poll_hotkey.action_handle)); - key->poll_hotkey.action_method = - kmalloc(sizeof(action_method), GFP_KERNEL); - strcpy(key->poll_hotkey.action_method, action_method); + key->poll_hotkey.action_method = action_method; + + status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.poll_handle, + poll_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle)); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.action_handle, + action_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - return_VALUE(is_valid_hotkey(key)); + if(!key->poll_hotkey.poll_result) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } -static int check_hotkey_valid(union acpi_hotkey *key, - struct acpi_hotkey_list *list) -{ - ACPI_FUNCTION_TRACE("check_hotkey_valid"); - return_VALUE(0); -} static int hotkey_open_config(struct inode *inode, struct file *file) { @@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file) (file, hotkey_config_seq_show, PDE(inode)->data)); } +static int hotkey_poll_open_config(struct inode *inode, struct file *file) +{ + ACPI_FUNCTION_TRACE("hotkey_poll_open_config"); + return_VALUE(single_open + (file, hotkey_poll_config_seq_show, PDE(inode)->data)); +} + static int hotkey_config_seq_show(struct seq_file *seq, void *offset) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries, *next; + struct list_head *entries; char bus_name[ACPI_PATHNAME_MAX] = { 0 }; char action_name[ACPI_PATHNAME_MAX] = { 0 }; struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; @@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); - if (!hotkey_list) - goto end; - - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { @@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->event_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%d:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, action_name, key->event_hotkey.action_method, key->link.hotkey_standard_num, key->event_hotkey.external_hotkey_num); - } /* ACPI_HOTKEY_POLLING */ - else { + } + } + seq_puts(seq, "\n"); + return_VALUE(0); +} + +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + struct list_head *entries; + char bus_name[ACPI_PATHNAME_MAX] = { 0 }; + char action_name[ACPI_PATHNAME_MAX] = { 0 }; + struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; + struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; + + ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); + + list_for_each(entries, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { acpi_get_name(key->poll_hotkey.poll_handle, ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->poll_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%s:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, key->poll_hotkey.poll_method, action_name, key->poll_hotkey.action_method, @@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) } } seq_puts(seq, "\n"); - end: return_VALUE(0); } static int get_parms(char *config_record, int *cmd, - char *bus_handle, - char *bus_method, - char *action_handle, - char *method, int *internal_event_num, int *external_event_num) + char **bus_handle, + char **bus_method, + char **action_handle, + char **method, int *internal_event_num, int *external_event_num) { - char *tmp, *tmp1; + char *tmp, *tmp1, count; ACPI_FUNCTION_TRACE(("get_parms")); sscanf(config_record, "%d", cmd); + if(*cmd == 1){ + if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2) + goto do_fail; + else + return (6); + } tmp = strchr(config_record, ':'); + if (!tmp) + goto do_fail; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_handle, tmp, tmp1 - tmp); - bus_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + + count = tmp1 - tmp; + *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_handle) + goto do_fail; + strncpy(*bus_handle, tmp, count); + *(*bus_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_method, tmp, tmp1 - tmp); - bus_method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *bus_method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_method) + goto do_fail; + strncpy(*bus_method, tmp, count); + *(*bus_method + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(action_handle, tmp, tmp1 - tmp); - action_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *action_handle = (char *) kmalloc(count+1, GFP_KERNEL); + strncpy(*action_handle, tmp, count); + *(*action_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(method, tmp, tmp1 - tmp); - method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*method) + goto do_fail; + strncpy(*method, tmp, count); + *(*method + count) = 0; + + if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0) + goto do_fail; - sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num); return_VALUE(6); +do_fail: + return_VALUE(-1); } /* count is length for one input record */ @@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data) { - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char config_record[MAX_CONFIG_RECORD_LEN]; - char bus_handle[MAX_NAME_PATH_LEN]; - char bus_method[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char method[20]; + char *config_record = NULL; + char *bus_handle = NULL; + char *bus_method = NULL; + char *action_handle = NULL; + char *method = NULL; int cmd, internal_event_num, external_event_num; int ret = 0; union acpi_hotkey *key = NULL; ACPI_FUNCTION_TRACE(("hotkey_write_config")); - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } + config_record = (char *) kmalloc(count+1, GFP_KERNEL); + if(!config_record) + return_VALUE(-ENOMEM); if (copy_from_user(config_record, buffer, count)) { + kfree(config_record); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); return_VALUE(-EINVAL); } - config_record[count] = '\0'; + config_record[count] = 0; ret = get_parms(config_record, &cmd, - bus_handle, - bus_method, - action_handle, - method, &internal_event_num, &external_event_num); + &bus_handle, + &bus_method, + &action_handle, + &method, &internal_event_num, &external_event_num); + + kfree(config_record); + if(IS_OTHERS(internal_event_num)) + goto do_fail; if (ret != 6) { +do_fail: + kfree(bus_handle); + kfree(bus_method); + kfree(action_handle); + kfree(method); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format ret=%d\n", ret)); return_VALUE(-EINVAL); } key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_hotkey_device(key, bus_handle, action_handle, method, + if(!key) + goto do_fail; + memset(key, 0, sizeof(union acpi_hotkey)); + if(cmd == 1) { + union acpi_hotkey *tmp = NULL; + tmp = get_hotkey_by_event(&global_hotkey_list, + internal_event_num); + if(!tmp) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key")); + else + memcpy(key, tmp, sizeof(union acpi_hotkey)); + goto cont_cmd; + } + if (IS_EVENT(internal_event_num)) { + kfree(bus_method); + ret = init_hotkey_device(key, bus_handle, action_handle, method, internal_event_num, external_event_num); - - if (ret || check_hotkey_valid(key, hotkey_list)) { + } else + ret = init_poll_hotkey_device(key, bus_handle, bus_method, + action_handle, method, + internal_event_num); + if (ret) { + kfree(bus_handle); + kfree(action_handle); + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); kfree(key); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); return_VALUE(-EINVAL); } - switch (cmd) { - case 0: - hotkey_add(key); - break; - case 1: - hotkey_remove(key); - free_hotkey_device(key); - break; - case 2: - hotkey_update(key); - break; - default: - break; - } - return_VALUE(count); -} - -/* count is length for one input record */ -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct seq_file *m = (struct seq_file *)file->private_data; - struct acpi_hotkey_list *hotkey_list = - (struct acpi_hotkey_list *)m->private; - - char config_record[MAX_CONFIG_RECORD_LEN]; - char polling_handle[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char poll_method[20], action_method[20]; - int ret, internal_event_num, cmd, external_event_num; - union acpi_hotkey *key = NULL; - - ACPI_FUNCTION_TRACE("hotkey_write_poll_config"); - - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } - - if (copy_from_user(config_record, buffer, count)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); - return_VALUE(-EINVAL); - } - config_record[count] = '\0'; - ret = get_parms(config_record, - &cmd, - polling_handle, - poll_method, - action_handle, - action_method, - &internal_event_num, &external_event_num); - - if (ret != 6) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); - return_VALUE(-EINVAL); - } +cont_cmd: + kfree(bus_handle); + kfree(action_handle); - key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_poll_hotkey_device(key, polling_handle, poll_method, - action_handle, action_method, - internal_event_num); - if (ret || check_hotkey_valid(key, hotkey_list)) { - kfree(key); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); - return_VALUE(-EINVAL); - } switch (cmd) { case 0: - hotkey_add(key); + if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num)) + goto fail_out; + else + hotkey_add(key); break; case 1: hotkey_remove(key); break; case 2: - hotkey_update(key); + if(hotkey_update(key)) + goto fail_out; break; default: + goto fail_out; break; } return_VALUE(count); +fail_out: + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); + kfree(key); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n")); + return_VALUE(-EINVAL); } -/* +/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL @@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, return_VALUE(status == AE_OK); } -static int read_acpi_int(acpi_handle handle, const char *method, int *val) +static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val) { struct acpi_buffer output; union acpi_object out_obj; @@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) output.pointer = &out_obj; status = acpi_evaluate_object(handle, (char *)method, NULL, &output); - *val = out_obj.integer.value; + if(val){ + val->integer.value = out_obj.integer.value; + val->type = out_obj.type; + } else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer")); return_VALUE((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)); } -static acpi_handle -get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num) +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event) { - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->link.hotkey_standard_num == event_num) { - return (key->event_hotkey.action_handle); - } - } - return (NULL); -} - -static -char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, - int event_num) -{ - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT && - key->link.hotkey_standard_num == event_num) - return (key->event_hotkey.action_method); - } - return (NULL); -} - -static struct acpi_polling_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event) -{ - struct list_head *entries, *next; + struct list_head *entries; - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_POLLING - && key->link.hotkey_standard_num == event) { - return (&key->poll_hotkey); + if (key->link.hotkey_standard_num == event) { + return(key); } } - return (NULL); + return(NULL); } -/* +/* * user call AML method interface: * Call convention: * echo "event_num: arg type : value" @@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file, size_t count, loff_t * data) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char arg[MAX_CALL_PARM]; - int event, type, value; - - char *method; - acpi_handle handle; + char *arg; + int event,method_type,type, value; + union acpi_hotkey *key; ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); - if (!hotkey_list || count > MAX_CALL_PARM) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1")); - return_VALUE(-EINVAL); - } + arg = (char *) kmalloc(count+1, GFP_KERNEL); + if(!arg) + return_VALUE(-ENOMEM); + arg[count]=0; if (copy_from_user(arg, buffer, count)) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); return_VALUE(-EINVAL); } - arg[count] = '\0'; - - if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) { + if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); return_VALUE(-EINVAL); } - + kfree(arg); if (type == ACPI_TYPE_INTEGER) { - handle = get_handle_from_hotkeylist(hotkey_list, event); - method = (char *)get_method_from_hotkeylist(hotkey_list, event); + key = get_hotkey_by_event(hotkey_list, event); + if(!key) + goto do_fail; if (IS_EVENT(event)) - write_acpi_int(handle, method, value, NULL); + write_acpi_int(key->event_hotkey.action_handle, + key->event_hotkey.action_method, value, NULL); else if (IS_POLL(event)) { - struct acpi_polling_hotkey *key; - key = (struct acpi_polling_hotkey *) - get_hotkey_by_event(hotkey_list, event); - read_acpi_int(handle, method, key->poll_result); + if ( method_type == POLL_METHOD ) + read_acpi_int(key->poll_hotkey.poll_handle, + key->poll_hotkey.poll_method, + key->poll_hotkey.poll_result); + else if ( method_type == ACTION_METHOD ) + write_acpi_int(key->poll_hotkey.action_handle, + key->poll_hotkey.action_method, value, NULL); + else + goto do_fail; + } } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); return_VALUE(-EINVAL); } - return_VALUE(count); +do_fail: + return_VALUE(-EINVAL); + } static int __init hotkey_init(void) @@ -928,7 +1013,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + goto do_fail1; } else { hotkey_config->proc_fops = &hotkey_config_fops; hotkey_config->data = &global_hotkey_list; @@ -943,7 +1028,8 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + + goto do_fail2; } else { hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; hotkey_poll_config->data = &global_hotkey_list; @@ -957,7 +1043,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_ACTION)); - return (-ENODEV); + goto do_fail3; } else { hotkey_action->proc_fops = &hotkey_action_fops; hotkey_action->owner = THIS_MODULE; @@ -970,7 +1056,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_INFO)); - return (-ENODEV); + goto do_fail4; } else { hotkey_info->proc_fops = &hotkey_info_fops; hotkey_info->owner = THIS_MODULE; @@ -979,23 +1065,33 @@ static int __init hotkey_init(void) } result = acpi_bus_register_driver(&hotkey_driver); - if (result < 0) { - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return (-ENODEV); - } + if (result < 0) + goto do_fail5; global_hotkey_list.count = 0; global_hotkey_list.entries = &hotkey_entries; INIT_LIST_HEAD(&hotkey_entries); return (0); + +do_fail5: + remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); +do_fail4: + remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); +do_fail3: + remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); +do_fail2: + remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); +do_fail1: + remove_proc_entry(HOTKEY_PROC, acpi_root_dir); + return (-ENODEV); } static void __exit hotkey_exit(void) { struct list_head *entries, *next; - ACPI_FUNCTION_TRACE("hotkey_remove"); + ACPI_FUNCTION_TRACE("hotkey_exit"); list_for_each_safe(entries, next, global_hotkey_list.entries) { union acpi_hotkey *key = diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 61ea70742d49..2934475d67d6 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME ("acpi_motherboard") */ #define IS_RESERVED_ADDR(base, len) \ (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > PCIBIOS_MIN_IO)) + && ((base) + (len) > 0x1000)) /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index d1f42b972821..bb973d2109a1 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +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 irq; + + ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); + + if (entry->link.handle) { + irq = acpi_pci_link_allocate_irq(entry->link.handle, + entry->link.index, edge_level, active_high_low, link); + if (irq < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); + return_VALUE(-1); + } + } else { + irq = entry->link.index; + *edge_level = ACPI_LEVEL_SENSITIVE; + *active_high_low = ACPI_ACTIVE_LOW; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); + return_VALUE(irq); +} + +static int +acpi_pci_free_irq(struct acpi_prt_entry *entry, + int *edge_level, + int *active_high_low, + char **link) +{ + int irq; + + ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); + if (entry->link.handle) { + irq = acpi_pci_link_free_irq(entry->link.handle); + } else { + irq = entry->link.index; + } + return_VALUE(irq); +} /* * acpi_pci_irq_lookup * success: return IRQ >= 0 @@ -282,12 +326,13 @@ acpi_pci_irq_lookup ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); int bus_nr = bus->number; - int irq; + int ret; ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); @@ -301,22 +346,8 @@ acpi_pci_irq_lookup ( return_VALUE(-1); } - if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, - entry->link.index, edge_level, active_high_low, link); - if (irq < 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); - return_VALUE(-1); - } - } else { - irq = entry->link.index; - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); - - return_VALUE(irq); + ret = func(entry, edge_level, active_high_low, link); + return_VALUE(ret); } /* @@ -330,7 +361,8 @@ acpi_pci_irq_derive ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct pci_dev *bridge = dev; int irq = -1; @@ -363,7 +395,7 @@ acpi_pci_irq_derive ( } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low, link); + pin, edge_level, active_high_low, link, func); } if (irq < 0) { @@ -415,7 +447,7 @@ acpi_pci_irq_enable ( * 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); + &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the @@ -423,7 +455,7 @@ acpi_pci_irq_enable ( */ if (irq < 0) irq = acpi_pci_irq_derive(dev, pin, &edge_level, - &active_high_low, &link); + &active_high_low, &link, acpi_pci_allocate_irq); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / @@ -462,7 +494,9 @@ acpi_pci_irq_enable ( EXPORT_SYMBOL(acpi_pci_irq_enable); -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ +/* FIXME: implement x86/x86_64 version */ +void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} + void acpi_pci_irq_disable ( struct pci_dev *dev) @@ -489,14 +523,14 @@ acpi_pci_irq_disable ( * 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); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low, NULL); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); if (gsi < 0) return_VOID; @@ -512,4 +546,3 @@ acpi_pci_irq_disable ( return_VOID; } -#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6ad0e77df9b3..65cea07abbc3 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = { }, }; +/* + * If a link is initialized, we never change its active and initialized + * later even the link is disable. Instead, we just repick the active irq + */ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 edge_level; /* All IRQs */ @@ -76,8 +80,7 @@ struct acpi_pci_link_irq { u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; u8 initialized:1; - u8 suspend_resume:1; - u8 reserved:6; + u8 reserved:7; }; struct acpi_pci_link { @@ -85,12 +88,14 @@ struct acpi_pci_link { struct acpi_device *device; acpi_handle handle; struct acpi_pci_link_irq irq; + int refcnt; }; static struct { int count; struct list_head entries; } acpi_link; +DECLARE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- @@ -532,12 +537,12 @@ static int acpi_pci_link_allocate( ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); - if (link->irq.suspend_resume) { - acpi_pci_link_set(link, link->irq.active); - link->irq.suspend_resume = 0; - } - if (link->irq.initialized) + if (link->irq.initialized) { + if (link->refcnt == 0) + /* This means the link is disabled but initialized */ + acpi_pci_link_set(link, link->irq.active); return_VALUE(0); + } /* * search for active IRQ in list of possible IRQs. @@ -596,13 +601,13 @@ static int acpi_pci_link_allocate( } /* - * acpi_pci_link_get_irq + * acpi_pci_link_allocate_irq * success: return IRQ >= 0 * failure: return -1 */ int -acpi_pci_link_get_irq ( +acpi_pci_link_allocate_irq ( acpi_handle handle, int index, int *edge_level, @@ -613,7 +618,7 @@ acpi_pci_link_get_irq ( struct acpi_device *device = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); result = acpi_bus_get_device(handle, &device); if (result) { @@ -633,21 +638,81 @@ acpi_pci_link_get_irq ( return_VALUE(-1); } - if (acpi_pci_link_allocate(link)) + down(&acpi_link_lock); + if (acpi_pci_link_allocate(link)) { + up(&acpi_link_lock); return_VALUE(-1); + } if (!link->irq.active) { + up(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); return_VALUE(-1); } + 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 (name) *name = acpi_device_bid(link->device); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is referenced\n", acpi_device_bid(link->device))); return_VALUE(link->irq.active); } +/* + * We don't change link's irq information here. After it is reenabled, we + * continue use the info + */ +int +acpi_pci_link_free_irq(acpi_handle handle) +{ + struct acpi_device *device = NULL; + struct acpi_pci_link *link = NULL; + acpi_status result; + + ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq"); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); + return_VALUE(-1); + } + + link = (struct acpi_pci_link *) acpi_driver_data(device); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + return_VALUE(-1); + } + + down(&acpi_link_lock); + if (!link->irq.initialized) { + up(&acpi_link_lock); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); + return_VALUE(-1); + } +#ifdef FUTURE_USE + /* + * The Link reference count allows us to _DISable an unused link + * and suspend time, and set it again on resume. + * However, 2.6.12 still has irq_router.resume + * which blindly restores the link state. + * So we disable the reference count method + * to prevent duplicate acpi_pci_link_set() + * which would harm some systems + */ + link->refcnt --; +#endif + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is dereferenced\n", acpi_device_bid(link->device))); + + if (link->refcnt == 0) { + acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + } + up(&acpi_link_lock); + return_VALUE(link->irq.active); +} /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -677,6 +742,7 @@ acpi_pci_link_add ( strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); acpi_driver_data(device) = link; + down(&acpi_link_lock); result = acpi_pci_link_get_possible(link); if (result) goto end; @@ -712,6 +778,7 @@ acpi_pci_link_add ( end: /* disable all links -- to be activated on use */ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + up(&acpi_link_lock); if (result) kfree(link); @@ -720,23 +787,34 @@ end: } static int -irqrouter_suspend( - struct sys_device *dev, - u32 state) +acpi_pci_link_resume( + struct acpi_pci_link *link) +{ + ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); + + if (link->refcnt && link->irq.active && link->irq.initialized) + return_VALUE(acpi_pci_link_set(link, link->irq.active)); + else + return_VALUE(0); +} + +static int +irqrouter_resume( + struct sys_device *dev) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("irqrouter_suspend"); + ACPI_FUNCTION_TRACE("irqrouter_resume"); list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); if (!link) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid link context\n")); continue; } - if (link->irq.active && link->irq.initialized) - link->irq.suspend_resume = 1; + acpi_pci_link_resume(link); } return_VALUE(0); } @@ -756,8 +834,9 @@ acpi_pci_link_remove ( link = (struct acpi_pci_link *) acpi_driver_data(device); - /* TBD: Acquire/release lock */ + down(&acpi_link_lock); list_del(&link->node); + up(&acpi_link_lock); kfree(link); @@ -849,9 +928,10 @@ int __init acpi_irq_balance_set(char *str) __setup("acpi_irq_balance", acpi_irq_balance_set); +/* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), - .suspend = irqrouter_suspend, + .resume = irqrouter_resume, }; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 893b074e3d1a..2c04740c6543 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -81,30 +81,32 @@ module_param(bm_history, uint, 0644); * * To skip this limit, boot/load with a large max_cstate limit. */ -static int no_c2c3(struct dmi_system_id *id) +static int set_max_cstate(struct dmi_system_id *id) { if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; - printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." + printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate." " Override with \"processor.max_cstate=%d\"\n", id->ident, - ACPI_PROCESSOR_MAX_POWER + 1); + (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); - max_cstate = 1; + max_cstate = (long)id->driver_data; return 0; } - - static struct dmi_system_id __initdata processor_power_dmi_table[] = { - { no_c2c3, "IBM ThinkPad R40e", { + { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, - { no_c2c3, "Medion 41700", { + 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,"R01-A1J") }}, + DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") }, + (void*)2}, {}, }; @@ -549,7 +551,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); /* if info is obtained from pblk/fadt, type equals state */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; @@ -580,7 +583,8 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) pr->power.count = 0; for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -763,7 +767,6 @@ static void acpi_processor_power_verify_c3( } if (pr->flags.bm_check) { - printk("Disabling BM access before entering C3\n"); /* bus mastering control is necessary */ if (!pr->flags.bm_control) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -771,7 +774,6 @@ static void acpi_processor_power_verify_c3( return_VOID; } } else { - printk("Invalidating cache before entering C3\n"); /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. @@ -842,7 +844,7 @@ static int acpi_processor_get_power_info ( result = acpi_processor_get_power_info_cst(pr); if ((result) || (acpi_processor_power_verify(pr) < 2)) { result = acpi_processor_get_power_info_fadt(pr); - if (result) + if ((result) || (acpi_processor_power_verify(pr) < 2)) result = acpi_processor_get_power_info_default_c1(pr); } diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index de5746e38af9..2435a7c99b2b 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -1281,6 +1281,7 @@ dispatch: */ if (!cfq_crq_in_driver(crq) && !cfq_cfqq_idle_window(cfqq) && + !blk_barrier_rq(rq) && cfqd->rq_in_driver >= cfqd->cfq_max_depth) return NULL; diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index c1fe013c64f3..b4af87c6f9c8 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -143,6 +143,7 @@ struct agp_bridge_data { char major_version; char minor_version; struct list_head list; + u32 apbase_config; }; #define KB(x) ((x) * 1024) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 51266d6b4d78..1f7d415f432c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1047,9 +1047,15 @@ static int intel_845_configure(void) /* aperture size */ pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); - /* address to map to */ - pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); - agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + if (agp_bridge->apbase_config != 0) { + pci_write_config_dword(agp_bridge->dev, AGP_APBASE, + agp_bridge->apbase_config); + } else { + /* address to map to */ + pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); + agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + agp_bridge->apbase_config = temp; + } /* attbase - aperture base */ pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7b19e02f112f..523fd3c8bbaa 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -198,10 +198,10 @@ int setkeycode(unsigned int scancode, unsigned int keycode) if (scancode >= dev->keycodemax) return -EINVAL; - if (keycode > KEY_MAX) - return -EINVAL; if (keycode < 0 || keycode > KEY_MAX) return -EINVAL; + if (keycode >> (dev->keycodesize * 8)) + return -EINVAL; oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index fd042060809a..cefbe985e55c 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -439,6 +439,11 @@ static struct { { 0, 0 }, }; +struct sonypi_keypress { + struct input_dev *dev; + int key; +}; + static struct sonypi_device { struct pci_dev *dev; struct platform_device *pdev; @@ -710,22 +715,61 @@ static void sonypi_setbluetoothpower(u8 state) static void input_keyrelease(void *data) { - struct input_dev *input_dev; - int key; - - while (1) { - if (kfifo_get(sonypi_device.input_fifo, - (unsigned char *)&input_dev, - sizeof(input_dev)) != sizeof(input_dev)) - return; - if (kfifo_get(sonypi_device.input_fifo, - (unsigned char *)&key, - sizeof(key)) != sizeof(key)) - return; + struct sonypi_keypress kp; + while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp, + sizeof(kp)) == sizeof(kp)) { msleep(10); - input_report_key(input_dev, key, 0); - input_sync(input_dev); + input_report_key(kp.dev, kp.key, 0); + input_sync(kp.dev); + } +} + +static void sonypi_report_input_event(u8 event) +{ + struct input_dev *jog_dev = &sonypi_device.input_jog_dev; + struct input_dev *key_dev = &sonypi_device.input_key_dev; + struct sonypi_keypress kp = { NULL }; + int i; + + switch (event) { + case SONYPI_EVENT_JOGDIAL_UP: + case SONYPI_EVENT_JOGDIAL_UP_PRESSED: + input_report_rel(jog_dev, REL_WHEEL, 1); + input_sync(jog_dev); + break; + + case SONYPI_EVENT_JOGDIAL_DOWN: + case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: + input_report_rel(jog_dev, REL_WHEEL, -1); + input_sync(jog_dev); + break; + + case SONYPI_EVENT_JOGDIAL_PRESSED: + kp.key = BTN_MIDDLE; + kp.dev = jog_dev; + break; + + case SONYPI_EVENT_FNKEY_RELEASED: + /* Nothing, not all VAIOs generate this event */ + break; + + default: + for (i = 0; sonypi_inputkeys[i].sonypiev; i++) + if (event == sonypi_inputkeys[i].sonypiev) { + kp.dev = key_dev; + kp.key = sonypi_inputkeys[i].inputev; + break; + } + break; + } + + if (kp.dev) { + input_report_key(kp.dev, kp.key, 1); + input_sync(kp.dev); + kfifo_put(sonypi_device.input_fifo, + (unsigned char *)&kp, sizeof(kp)); + schedule_work(&sonypi_device.input_work); } } @@ -768,51 +812,8 @@ found: printk(KERN_INFO "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2); - if (useinput) { - struct input_dev *input_jog_dev = &sonypi_device.input_jog_dev; - struct input_dev *input_key_dev = &sonypi_device.input_key_dev; - switch (event) { - case SONYPI_EVENT_JOGDIAL_UP: - case SONYPI_EVENT_JOGDIAL_UP_PRESSED: - input_report_rel(input_jog_dev, REL_WHEEL, 1); - break; - case SONYPI_EVENT_JOGDIAL_DOWN: - case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: - input_report_rel(input_jog_dev, REL_WHEEL, -1); - break; - case SONYPI_EVENT_JOGDIAL_PRESSED: { - int key = BTN_MIDDLE; - input_report_key(input_jog_dev, key, 1); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&input_jog_dev, - sizeof(input_jog_dev)); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&key, sizeof(key)); - break; - } - case SONYPI_EVENT_FNKEY_RELEASED: - /* Nothing, not all VAIOs generate this event */ - break; - } - input_sync(input_jog_dev); - - for (i = 0; sonypi_inputkeys[i].sonypiev; i++) { - int key; - - if (event != sonypi_inputkeys[i].sonypiev) - continue; - - key = sonypi_inputkeys[i].inputev; - input_report_key(input_key_dev, key, 1); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&input_key_dev, - sizeof(input_key_dev)); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&key, sizeof(key)); - } - input_sync(input_key_dev); - schedule_work(&sonypi_device.input_work); - } + if (useinput) + sonypi_report_input_event(event); kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); @@ -1227,14 +1228,7 @@ static int __devinit sonypi_probe(void) sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE); sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL); - sonypi_device.input_jog_dev.name = - kmalloc(sizeof(SONYPI_JOG_INPUTNAME), GFP_KERNEL); - if (!sonypi_device.input_jog_dev.name) { - printk(KERN_ERR "sonypi: kmalloc failed\n"); - ret = -ENOMEM; - goto out_inkmallocinput1; - } - sprintf(sonypi_device.input_jog_dev.name, SONYPI_JOG_INPUTNAME); + sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME; sonypi_device.input_jog_dev.id.bustype = BUS_ISA; sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY; @@ -1248,14 +1242,7 @@ static int __devinit sonypi_probe(void) if (sonypi_inputkeys[i].inputev) set_bit(sonypi_inputkeys[i].inputev, sonypi_device.input_key_dev.keybit); - sonypi_device.input_key_dev.name = - kmalloc(sizeof(SONYPI_KEY_INPUTNAME), GFP_KERNEL); - if (!sonypi_device.input_key_dev.name) { - printk(KERN_ERR "sonypi: kmalloc failed\n"); - ret = -ENOMEM; - goto out_inkmallocinput2; - } - sprintf(sonypi_device.input_key_dev.name, SONYPI_KEY_INPUTNAME); + sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME; sonypi_device.input_key_dev.id.bustype = BUS_ISA; sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY; @@ -1313,11 +1300,7 @@ out_platformdev: kfifo_free(sonypi_device.input_fifo); out_infifo: input_unregister_device(&sonypi_device.input_key_dev); - kfree(sonypi_device.input_key_dev.name); -out_inkmallocinput2: input_unregister_device(&sonypi_device.input_jog_dev); - kfree(sonypi_device.input_jog_dev.name); -out_inkmallocinput1: free_irq(sonypi_device.irq, sonypi_irq); out_reqirq: release_region(sonypi_device.ioport1, sonypi_device.region_size); @@ -1337,13 +1320,14 @@ static void __devexit sonypi_remove(void) { sonypi_disable(); + synchronize_sched(); /* Allow sonypi interrupt to complete. */ + flush_scheduled_work(); + platform_device_unregister(sonypi_device.pdev); if (useinput) { input_unregister_device(&sonypi_device.input_key_dev); - kfree(sonypi_device.input_key_dev.name); input_unregister_device(&sonypi_device.input_jog_dev); - kfree(sonypi_device.input_jog_dev.name); kfifo_free(sonypi_device.input_fifo); } diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 1b2132617dc3..fb88b4041dca 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -36,13 +36,10 @@ #include <asm/uaccess.h> #define OSCR_FREQ CLOCK_TICK_RATE -#define SA1100_CLOSE_MAGIC (0x5afc4453) static unsigned long sa1100wdt_users; -static int expect_close; static int pre_margin; static int boot_status; -static int nowayout = WATCHDOG_NOWAYOUT; /* * Allow only one person to hold it open @@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) } /* - * Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT - * Oddly, the watchdog can only be enabled, but we can turn off - * the interrupt, which appears to prevent the watchdog timing out. + * The watchdog cannot be disabled. + * + * Previous comments suggested that turning off the interrupt by + * clearing OIER[E3] would prevent the watchdog timing out but this + * does not appear to be true (at least on the PXA255). */ static int sa1100dog_release(struct inode *inode, struct file *file) { - OSMR3 = OSCR + pre_margin; - - if (expect_close == SA1100_CLOSE_MAGIC) { - OIER &= ~OIER_E3; - } else { - printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); - } + printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); clear_bit(1, &sa1100wdt_users); - expect_close = 0; return 0; } static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - if (len) { - if (!nowayout) { - size_t i; - - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = SA1100_CLOSE_MAGIC; - } - } + if (len) /* Refresh OSMR3 timer. */ OSMR3 = OSCR + pre_margin; - } return len; } static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | - WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "SA1100 Watchdog", + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SA1100/PXA255 Watchdog", }; static int sa1100dog_ioctl(struct inode *inode, struct file *file, @@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops = static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, - .name = "SA1100/PXA2xx watchdog", + .name = "watchdog", .fops = &sa1100dog_fops, }; @@ -194,7 +169,6 @@ static int __init sa1100dog_init(void) if (ret == 0) printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); - return ret; } @@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7a7859dd0d98..10b014982381 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1130,7 +1130,7 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - unsigned int ret; + int ret; policy = cpufreq_cpu_get(policy->cpu); if (!policy) @@ -1151,7 +1151,7 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { - int ret = -EINVAL; + int ret; if (!try_module_get(policy->governor->owner)) return -EINVAL; diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 3c85fe150cd7..4fa17c76eea2 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -393,7 +393,7 @@ void adm1026_init_client(struct i2c_client *client) value = data->config3; if (data->config3 & CFG3_GPIO16_ENABLE) { - dev_dbg(&client->dev, "GPIO16 enabled. THERM" + dev_dbg(&client->dev, "GPIO16 enabled. THERM " "pin disabled.\n"); } else { dev_dbg(&client->dev, "THERM pin enabled. " diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 0bcf82b4c07b..fca3fc1cef72 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -21,6 +21,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/i2c-sensor.h> #include <linux/i2c-vid.h> @@ -80,9 +81,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) down(&data->update_lock); - if ((jiffies - data->last_updated > HZ) || - (jiffies < data->last_updated) || - !data->valid) { + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { /* Update local register data */ data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID); diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 3beaa6191ef4..270015b626ad 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/slab.h> +#include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/i2c-sensor.h> #include <linux/init.h> @@ -572,8 +573,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev) down(&data->update_lock); - if ((jiffies - data->last_updated > 2 * HZ) || - (jiffies < data->last_updated) || !data->valid) { + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { int i; dev_dbg(&client->dev, "Starting fscpos update\n"); diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index a13a504f5bfa..80ae8d30c2af 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> +#include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/i2c-sensor.h> #include <linux/i2c-vid.h> @@ -678,8 +679,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) down(&data->update_lock); - if ((jiffies - data->last_updated > 2 * HZ) || - (jiffies < data->last_updated) || !data->valid) { + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { dev_dbg(&client->dev, "Starting gl520sm update\n"); diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index bf553dcd97d6..3c159f1d49ee 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -363,7 +363,7 @@ static void __exit sensors_max1619_exit(void) i2c_del_driver(&max1619_driver); } -MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and" +MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and " "Jean Delvare <khali@linux-fr.org>"); MODULE_DESCRIPTION("MAX1619 sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 876c68f3af31..fa4032d53b79 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -1043,7 +1043,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) if (init >= 2 && data->innr) { reg = pc87360_read_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONVRATE); - dev_info(&client->dev, "VLM conversion set to" + dev_info(&client->dev, "VLM conversion set to " "1s period, 160us delay\n"); pc87360_write_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONVRATE, diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 0ab7e37f5b00..1ab41313ce51 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -137,7 +137,7 @@ static int i801_setup(struct pci_dev *dev) pci_read_config_word(I801_dev, SMBBA, &i801_smba); i801_smba &= 0xfff0; if(i801_smba == 0) { - dev_err(&dev->dev, "SMB base address uninitialized" + dev_err(&dev->dev, "SMB base address uninitialized " "- upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } @@ -186,7 +186,7 @@ static int i801_transaction(void) int result = 0; int timeout = 0; - dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x," + dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, " "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); @@ -240,7 +240,7 @@ static int i801_transaction(void) outb_p(inb(SMBHSTSTS), SMBHSTSTS); if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "Failed reset at end of transaction" + dev_dbg(&I801_dev->dev, "Failed reset at end of transaction " "(%02x)\n", temp); } dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 74ece8ac1c23..82cf959989fd 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -165,7 +165,7 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) buf[0] = 0; /* reg offset */ buf[1] = BIN2BCD(dt->tm_sec); buf[2] = BIN2BCD(dt->tm_min); - buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6); + buf[3] = BIN2BCD(dt->tm_hour); buf[4] = BIN2BCD(dt->tm_wday) + 1; buf[5] = BIN2BCD(dt->tm_mday); buf[6] = BIN2BCD(dt->tm_mon) + 1; @@ -344,9 +344,9 @@ static void ds1337_init_client(struct i2c_client *client) /* Ensure that device is set in 24-hour mode */ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); - if ((val >= 0) && (val & (1 << 6)) == 0) + if ((val >= 0) && (val & (1 << 6))) i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, - val | (1 << 6)); + val & 0x3f); } static int ds1337_detach_client(struct i2c_client *client) diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 6ea413f6d5e5..a2da31b0dd7b 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -163,6 +163,11 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) struct eeprom_data *data; int err = 0; + /* prevent 24RF08 corruption */ + if (kind < 0) + i2c_smbus_xfer(adapter, address, 0, 0, 0, + I2C_SMBUS_QUICK, NULL); + /* There are three ways we can read the EEPROM data: (1) I2C block reads (faster, but unsupported by most adapters) (2) Consecutive byte reads (100% overhead) @@ -187,9 +192,6 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) new_client->driver = &eeprom_driver; new_client->flags = 0; - /* prevent 24RF08 corruption */ - i2c_smbus_write_quick(new_client, 0); - /* Fill in the remaining client fields */ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); data->valid = 0; diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index c4f14d9623c4..0230375f72e5 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -343,6 +343,11 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) struct max6875_data *data; int err = 0; + /* Prevent 24RF08 corruption (in case of user error) */ + if (kind < 0) + i2c_smbus_xfer(adapter, address, 0, 0, 0, + I2C_SMBUS_QUICK, NULL); + /* There are three ways we can read the EEPROM data: (1) I2C block reads (faster, but unsupported by most adapters) (2) Consecutive byte reads (100% overhead) @@ -370,9 +375,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) new_client->driver = &max6875_driver; new_client->flags = 0; - /* Prevent 24RF08 corruption */ - i2c_smbus_write_quick(new_client, 0); - /* Setup the user section */ data->blocks[max6875_eeprom_user].type = max6875_eeprom_user; data->blocks[max6875_eeprom_user].slices = USER_EEPROM_SLICES; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 4fd4f52c8e9b..4a9ead277596 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -231,8 +231,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) if (driver->detach_adapter) if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "can't detach adapter " - "while detaching driver %s: driver not " - "detached!", driver->name); + "while detaching driver %s: driver " + "not detached!\n", driver->name); goto out_unlock; } } @@ -456,8 +456,8 @@ int i2c_detach_client(struct i2c_client *client) res = adapter->client_unregister(client); if (res) { dev_err(&client->dev, - "client_unregister [%s] failed, " - "client not detached", client->name); + "client_unregister [%s] failed, " + "client not detached\n", client->name); goto out; } } diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 03747439ac9c..f1d1ec4e9677 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -508,5 +508,5 @@ static void __exit exit_ide_cs(void) BUG_ON(dev_list != NULL); } -module_init(init_ide_cs); +late_initcall(init_ide_cs); module_exit(exit_ide_cs); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 374f404e81da..20e3a165989f 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -320,6 +320,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; if (get_user(v, ip + 1)) return -EFAULT; if (v < 0 || v > KEY_MAX) return -EINVAL; + if (v >> (dev->keycodesize * 8)) return -EINVAL; u = SET_INPUT_KEYCODE(dev, t, v); clear_bit(u, dev->keybit); set_bit(v, dev->keybit); diff --git a/drivers/input/input.c b/drivers/input/input.c index 7c4b4d37b3e6..a275211c8e1e 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -48,12 +48,6 @@ static LIST_HEAD(input_handler_list); static struct input_handler *input_table[8]; -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_bus_input_dir; -static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait); -static int input_devices_state; -#endif - void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handle; @@ -312,6 +306,7 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st return NULL; } + /* * Input hotplugging interface - loading event handlers based on * device bitfields. @@ -428,6 +423,177 @@ static void input_call_hotplug(char *verb, struct input_dev *dev) #endif +#ifdef CONFIG_PROC_FS + +static struct proc_dir_entry *proc_bus_input_dir; +static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait); +static int input_devices_state; + +static inline void input_wakeup_procfs_readers(void) +{ + input_devices_state++; + wake_up(&input_devices_poll_wait); +} + +static unsigned int input_devices_poll(struct file *file, poll_table *wait) +{ + int state = input_devices_state; + poll_wait(file, &input_devices_poll_wait, wait); + if (state != input_devices_state) + return POLLIN | POLLRDNORM; + return 0; +} + +#define SPRINTF_BIT_B(bit, name, max) \ + do { \ + len += sprintf(buf + len, "B: %s", name); \ + for (i = NBITS(max) - 1; i >= 0; i--) \ + if (dev->bit[i]) break; \ + for (; i >= 0; i--) \ + len += sprintf(buf + len, "%lx ", dev->bit[i]); \ + len += sprintf(buf + len, "\n"); \ + } while (0) + +#define SPRINTF_BIT_B2(bit, name, max, ev) \ + do { \ + if (test_bit(ev, dev->evbit)) \ + SPRINTF_BIT_B(bit, name, max); \ + } while (0) + +static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) +{ + struct input_dev *dev; + struct input_handle *handle; + + off_t at = 0; + int i, len, cnt = 0; + + list_for_each_entry(dev, &input_dev_list, node) { + + len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", + dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); + + len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); + len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); + len += sprintf(buf + len, "H: Handlers="); + + list_for_each_entry(handle, &dev->h_list, d_node) + len += sprintf(buf + len, "%s ", handle->name); + + len += sprintf(buf + len, "\n"); + + SPRINTF_BIT_B(evbit, "EV=", EV_MAX); + SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY); + SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL); + SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS); + SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC); + SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); + SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); + SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); + + len += sprintf(buf + len, "\n"); + + at += len; + + if (at >= pos) { + if (!*start) { + *start = buf + (pos - (at - len)); + cnt = at - pos; + } else cnt += len; + buf += len; + if (cnt >= count) + break; + } + } + + if (&dev->node == &input_dev_list) + *eof = 1; + + return (count > cnt) ? cnt : count; +} + +static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) +{ + struct input_handler *handler; + + off_t at = 0; + int len = 0, cnt = 0; + int i = 0; + + list_for_each_entry(handler, &input_handler_list, node) { + + if (handler->fops) + len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", + i++, handler->name, handler->minor); + else + len = sprintf(buf, "N: Number=%d Name=%s\n", + i++, handler->name); + + at += len; + + if (at >= pos) { + if (!*start) { + *start = buf + (pos - (at - len)); + cnt = at - pos; + } else cnt += len; + buf += len; + if (cnt >= count) + break; + } + } + if (&handler->node == &input_handler_list) + *eof = 1; + + return (count > cnt) ? cnt : count; +} + +static struct file_operations input_fileops; + +static int __init input_proc_init(void) +{ + struct proc_dir_entry *entry; + + proc_bus_input_dir = proc_mkdir("input", proc_bus); + if (!proc_bus_input_dir) + return -ENOMEM; + + proc_bus_input_dir->owner = THIS_MODULE; + + entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); + if (!entry) + goto fail1; + + entry->owner = THIS_MODULE; + input_fileops = *entry->proc_fops; + entry->proc_fops = &input_fileops; + entry->proc_fops->poll = input_devices_poll; + + entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); + if (!entry) + goto fail2; + + entry->owner = THIS_MODULE; + + return 0; + + fail2: remove_proc_entry("devices", proc_bus_input_dir); + fail1: remove_proc_entry("input", proc_bus); + return -ENOMEM; +} + +static void input_proc_exit(void) +{ + remove_proc_entry("devices", proc_bus_input_dir); + remove_proc_entry("handlers", proc_bus_input_dir); + remove_proc_entry("input", proc_bus); +} + +#else /* !CONFIG_PROC_FS */ +static inline void input_wakeup_procfs_readers(void) { } +static inline int input_proc_init(void) { return 0; } +static inline void input_proc_exit(void) { } +#endif + void input_register_device(struct input_dev *dev) { struct input_handle *handle; @@ -464,10 +630,7 @@ void input_register_device(struct input_dev *dev) input_call_hotplug("add", dev); #endif -#ifdef CONFIG_PROC_FS - input_devices_state++; - wake_up(&input_devices_poll_wait); -#endif + input_wakeup_procfs_readers(); } void input_unregister_device(struct input_dev *dev) @@ -491,10 +654,7 @@ void input_unregister_device(struct input_dev *dev) list_del_init(&dev->node); -#ifdef CONFIG_PROC_FS - input_devices_state++; - wake_up(&input_devices_poll_wait); -#endif + input_wakeup_procfs_readers(); } void input_register_handler(struct input_handler *handler) @@ -518,10 +678,7 @@ void input_register_handler(struct input_handler *handler) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); -#ifdef CONFIG_PROC_FS - input_devices_state++; - wake_up(&input_devices_poll_wait); -#endif + input_wakeup_procfs_readers(); } void input_unregister_handler(struct input_handler *handler) @@ -540,10 +697,7 @@ void input_unregister_handler(struct input_handler *handler) if (handler->fops != NULL) input_table[handler->minor >> 5] = NULL; -#ifdef CONFIG_PROC_FS - input_devices_state++; - wake_up(&input_devices_poll_wait); -#endif + input_wakeup_procfs_readers(); } static int input_open_file(struct inode *inode, struct file *file) @@ -582,190 +736,43 @@ static struct file_operations input_fops = { .open = input_open_file, }; -#ifdef CONFIG_PROC_FS - -#define SPRINTF_BIT_B(bit, name, max) \ - do { \ - len += sprintf(buf + len, "B: %s", name); \ - for (i = NBITS(max) - 1; i >= 0; i--) \ - if (dev->bit[i]) break; \ - for (; i >= 0; i--) \ - len += sprintf(buf + len, "%lx ", dev->bit[i]); \ - len += sprintf(buf + len, "\n"); \ - } while (0) - -#define SPRINTF_BIT_B2(bit, name, max, ev) \ - do { \ - if (test_bit(ev, dev->evbit)) \ - SPRINTF_BIT_B(bit, name, max); \ - } while (0) - - -static unsigned int input_devices_poll(struct file *file, poll_table *wait) -{ - int state = input_devices_state; - poll_wait(file, &input_devices_poll_wait, wait); - if (state != input_devices_state) - return POLLIN | POLLRDNORM; - return 0; -} +struct class *input_class; -static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) +static int __init input_init(void) { - struct input_dev *dev; - struct input_handle *handle; - - off_t at = 0; - int i, len, cnt = 0; - - list_for_each_entry(dev, &input_dev_list, node) { - - len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", - dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); - - len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); - len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); - len += sprintf(buf + len, "H: Handlers="); - - list_for_each_entry(handle, &dev->h_list, d_node) - len += sprintf(buf + len, "%s ", handle->name); - - len += sprintf(buf + len, "\n"); - - SPRINTF_BIT_B(evbit, "EV=", EV_MAX); - SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY); - SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL); - SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS); - SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC); - SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); - SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); - SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); - - len += sprintf(buf + len, "\n"); - - at += len; + int err; - if (at >= pos) { - if (!*start) { - *start = buf + (pos - (at - len)); - cnt = at - pos; - } else cnt += len; - buf += len; - if (cnt >= count) - break; - } + input_class = class_create(THIS_MODULE, "input"); + if (IS_ERR(input_class)) { + printk(KERN_ERR "input: unable to register input class\n"); + return PTR_ERR(input_class); } - if (&dev->node == &input_dev_list) - *eof = 1; - - return (count > cnt) ? cnt : count; -} - -static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) -{ - struct input_handler *handler; - - off_t at = 0; - int len = 0, cnt = 0; - int i = 0; - - list_for_each_entry(handler, &input_handler_list, node) { - - if (handler->fops) - len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", - i++, handler->name, handler->minor); - else - len = sprintf(buf, "N: Number=%d Name=%s\n", - i++, handler->name); - - at += len; + err = input_proc_init(); + if (err) + goto fail1; - if (at >= pos) { - if (!*start) { - *start = buf + (pos - (at - len)); - cnt = at - pos; - } else cnt += len; - buf += len; - if (cnt >= count) - break; - } + err = register_chrdev(INPUT_MAJOR, "input", &input_fops); + if (err) { + printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); + goto fail2; } - if (&handler->node == &input_handler_list) - *eof = 1; - - return (count > cnt) ? cnt : count; -} - -static struct file_operations input_fileops; -static int __init input_proc_init(void) -{ - struct proc_dir_entry *entry; + err = devfs_mk_dir("input"); + if (err) + goto fail3; - proc_bus_input_dir = proc_mkdir("input", proc_bus); - if (proc_bus_input_dir == NULL) - return -ENOMEM; - proc_bus_input_dir->owner = THIS_MODULE; - entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); - if (entry == NULL) { - remove_proc_entry("input", proc_bus); - return -ENOMEM; - } - entry->owner = THIS_MODULE; - input_fileops = *entry->proc_fops; - entry->proc_fops = &input_fileops; - entry->proc_fops->poll = input_devices_poll; - entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); - if (entry == NULL) { - remove_proc_entry("devices", proc_bus_input_dir); - remove_proc_entry("input", proc_bus); - return -ENOMEM; - } - entry->owner = THIS_MODULE; return 0; -} -#else /* !CONFIG_PROC_FS */ -static inline int input_proc_init(void) { return 0; } -#endif -struct class *input_class; - -static int __init input_init(void) -{ - int retval = -ENOMEM; - - input_class = class_create(THIS_MODULE, "input"); - if (IS_ERR(input_class)) - return PTR_ERR(input_class); - input_proc_init(); - retval = register_chrdev(INPUT_MAJOR, "input", &input_fops); - if (retval) { - printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); - remove_proc_entry("devices", proc_bus_input_dir); - remove_proc_entry("handlers", proc_bus_input_dir); - remove_proc_entry("input", proc_bus); - class_destroy(input_class); - return retval; - } - - retval = devfs_mk_dir("input"); - if (retval) { - remove_proc_entry("devices", proc_bus_input_dir); - remove_proc_entry("handlers", proc_bus_input_dir); - remove_proc_entry("input", proc_bus); - unregister_chrdev(INPUT_MAJOR, "input"); - class_destroy(input_class); - } - return retval; + fail3: unregister_chrdev(INPUT_MAJOR, "input"); + fail2: input_proc_exit(); + fail1: class_destroy(input_class); + return err; } static void __exit input_exit(void) { - remove_proc_entry("devices", proc_bus_input_dir); - remove_proc_entry("handlers", proc_bus_input_dir); - remove_proc_entry("input", proc_bus); - + input_proc_exit(); devfs_remove("input"); unregister_chrdev(INPUT_MAJOR, "input"); class_destroy(input_class); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index ff8e1bbd0e13..e0938d1d3ad7 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -37,8 +37,6 @@ MODULE_LICENSE("GPL"); #define JOYDEV_MINORS 16 #define JOYDEV_BUFFER_SIZE 64 -#define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ) - struct joydev { int exist; int open; @@ -117,7 +115,7 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne return; } - event.time = MSECS(jiffies); + event.time = jiffies_to_msecs(jiffies); list_for_each_entry(list, &joydev->list, node) { @@ -245,7 +243,7 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo struct js_event event; - event.time = MSECS(jiffies); + event.time = jiffies_to_msecs(jiffies); if (list->startup < joydev->nkey) { event.type = JS_EVENT_BUTTON | JS_EVENT_INIT; diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 98710997aaaa..d5c5b32045af 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -36,16 +36,6 @@ #include <linux/miscdevice.h> #include <linux/uinput.h> -static int uinput_dev_open(struct input_dev *dev) -{ - return 0; -} - -static void uinput_dev_close(struct input_dev *dev) -{ - -} - static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct uinput_device *udev; @@ -63,22 +53,24 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i return 0; } -static int uinput_request_alloc_id(struct input_dev *dev, struct uinput_request *request) +static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) { /* Atomically allocate an ID for the given request. Returns 0 on success. */ - struct uinput_device *udev = dev->private; int id; + int err = -1; + + spin_lock(&udev->requests_lock); - down(&udev->requests_sem); - for (id=0; id<UINPUT_NUM_REQUESTS; id++) + for (id = 0; id < UINPUT_NUM_REQUESTS; id++) if (!udev->requests[id]) { - udev->requests[id] = request; request->id = id; - up(&udev->requests_sem); - return 0; + udev->requests[id] = request; + err = 0; + break; } - up(&udev->requests_sem); - return -1; + + spin_unlock(&udev->requests_lock); + return err; } static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id) @@ -86,70 +78,78 @@ static struct uinput_request* uinput_request_find(struct uinput_device *udev, in /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ if (id >= UINPUT_NUM_REQUESTS || id < 0) return NULL; - if (udev->requests[id]->completed) - return NULL; return udev->requests[id]; } -static void uinput_request_init(struct input_dev *dev, struct uinput_request *request, int code) +static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request) { - struct uinput_device *udev = dev->private; + /* Allocate slot. If none are available right away, wait. */ + return wait_event_interruptible(udev->requests_waitq, + !uinput_request_alloc_id(udev, request)); +} - memset(request, 0, sizeof(struct uinput_request)); - request->code = code; - init_waitqueue_head(&request->waitq); +static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request) +{ + complete(&request->done); - /* Allocate an ID. If none are available right away, wait. */ - request->retval = wait_event_interruptible(udev->requests_waitq, - !uinput_request_alloc_id(dev, request)); + /* Mark slot as available */ + udev->requests[request->id] = NULL; + wake_up_interruptible(&udev->requests_waitq); } -static void uinput_request_submit(struct input_dev *dev, struct uinput_request *request) +static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request) { - struct uinput_device *udev = dev->private; int retval; /* Tell our userspace app about this new request by queueing an input event */ uinput_dev_event(dev, EV_UINPUT, request->code, request->id); /* Wait for the request to complete */ - retval = wait_event_interruptible(request->waitq, request->completed); - if (retval) - request->retval = retval; + retval = wait_for_completion_interruptible(&request->done); + if (!retval) + retval = request->retval; - /* Release this request's ID, let others know it's available */ - udev->requests[request->id] = NULL; - wake_up_interruptible(&udev->requests_waitq); + return retval; } static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect) { struct uinput_request request; + int retval; if (!test_bit(EV_FF, dev->evbit)) return -ENOSYS; - uinput_request_init(dev, &request, UI_FF_UPLOAD); - if (request.retval) - return request.retval; + request.id = -1; + init_completion(&request.done); + request.code = UI_FF_UPLOAD; request.u.effect = effect; - uinput_request_submit(dev, &request); - return request.retval; + + retval = uinput_request_reserve_slot(dev->private, &request); + if (!retval) + retval = uinput_request_submit(dev, &request); + + return retval; } static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) { struct uinput_request request; + int retval; if (!test_bit(EV_FF, dev->evbit)) return -ENOSYS; - uinput_request_init(dev, &request, UI_FF_ERASE); - if (request.retval) - return request.retval; + request.id = -1; + init_completion(&request.done); + request.code = UI_FF_ERASE; request.u.effect_id = effect_id; - uinput_request_submit(dev, &request); - return request.retval; + + retval = uinput_request_reserve_slot(dev->private, &request); + if (!retval) + retval = uinput_request_submit(dev, &request); + + return retval; } static int uinput_create_device(struct uinput_device *udev) @@ -159,32 +159,30 @@ static int uinput_create_device(struct uinput_device *udev) return -EINVAL; } - udev->dev->open = uinput_dev_open; - udev->dev->close = uinput_dev_close; udev->dev->event = uinput_dev_event; udev->dev->upload_effect = uinput_dev_upload_effect; udev->dev->erase_effect = uinput_dev_erase_effect; udev->dev->private = udev; - init_waitqueue_head(&(udev->waitq)); + init_waitqueue_head(&udev->waitq); input_register_device(udev->dev); - set_bit(UIST_CREATED, &(udev->state)); + set_bit(UIST_CREATED, &udev->state); return 0; } static int uinput_destroy_device(struct uinput_device *udev) { - if (!test_bit(UIST_CREATED, &(udev->state))) { + if (!test_bit(UIST_CREATED, &udev->state)) { printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME); return -EINVAL; } input_unregister_device(udev->dev); - clear_bit(UIST_CREATED, &(udev->state)); + clear_bit(UIST_CREATED, &udev->state); return 0; } @@ -198,7 +196,7 @@ static int uinput_open(struct inode *inode, struct file *file) if (!newdev) goto error; memset(newdev, 0, sizeof(struct uinput_device)); - init_MUTEX(&newdev->requests_sem); + spin_lock_init(&newdev->requests_lock); init_waitqueue_head(&newdev->requests_waitq); newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL); @@ -253,15 +251,16 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz struct uinput_user_dev *user_dev; struct input_dev *dev; struct uinput_device *udev; - int size, - retval; + char *name; + int size; + int retval; retval = count; udev = file->private_data; dev = udev->dev; - user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL); + user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); if (!user_dev) { retval = -ENOMEM; goto exit; @@ -272,17 +271,17 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz goto exit; } - if (NULL != dev->name) + if (dev->name) kfree(dev->name); size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; - dev->name = kmalloc(size, GFP_KERNEL); - if (!dev->name) { + dev->name = name = kmalloc(size, GFP_KERNEL); + if (!name) { retval = -ENOMEM; goto exit; } + strlcpy(name, user_dev->name, size); - strlcpy(dev->name, user_dev->name, size); dev->id.bustype = user_dev->id.bustype; dev->id.vendor = user_dev->id.vendor; dev->id.product = user_dev->id.product; @@ -314,14 +313,13 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t { struct uinput_device *udev = file->private_data; - if (test_bit(UIST_CREATED, &(udev->state))) { + if (test_bit(UIST_CREATED, &udev->state)) { struct input_event ev; if (copy_from_user(&ev, buffer, sizeof(struct input_event))) return -EFAULT; input_event(udev->dev, ev.type, ev.code, ev.value); - } - else + } else count = uinput_alloc_device(file, buffer, count); return count; @@ -332,26 +330,24 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, struct uinput_device *udev = file->private_data; int retval = 0; - if (!test_bit(UIST_CREATED, &(udev->state))) + if (!test_bit(UIST_CREATED, &udev->state)) return -ENODEV; - if ((udev->head == udev->tail) && (file->f_flags & O_NONBLOCK)) + if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK)) return -EAGAIN; retval = wait_event_interruptible(udev->waitq, - (udev->head != udev->tail) || - !test_bit(UIST_CREATED, &(udev->state))); - + udev->head != udev->tail || !test_bit(UIST_CREATED, &udev->state)); if (retval) return retval; - if (!test_bit(UIST_CREATED, &(udev->state))) + if (!test_bit(UIST_CREATED, &udev->state)) return -ENODEV; while ((udev->head != udev->tail) && (retval + sizeof(struct input_event) <= count)) { - if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]), - sizeof(struct input_event))) return -EFAULT; + if (copy_to_user(buffer + retval, &udev->buff[udev->tail], sizeof(struct input_event))) + return -EFAULT; udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; retval += sizeof(struct input_event); } @@ -373,12 +369,12 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait) static int uinput_burn_device(struct uinput_device *udev) { - if (test_bit(UIST_CREATED, &(udev->state))) + if (test_bit(UIST_CREATED, &udev->state)) uinput_destroy_device(udev); - if (NULL != udev->dev->name) + if (udev->dev->name) kfree(udev->dev->name); - if (NULL != udev->dev->phys) + if (udev->dev->phys) kfree(udev->dev->phys); kfree(udev->dev); @@ -389,7 +385,8 @@ static int uinput_burn_device(struct uinput_device *udev) static int uinput_close(struct inode *inode, struct file *file) { - return uinput_burn_device(file->private_data); + uinput_burn_device(file->private_data); + return 0; } static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -401,6 +398,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct uinput_ff_erase ff_erase; struct uinput_request *req; int length; + char *phys; udev = file->private_data; @@ -415,7 +413,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd case UI_SET_SNDBIT: case UI_SET_FFBIT: case UI_SET_PHYS: - if (test_bit(UIST_CREATED, &(udev->state))) + if (test_bit(UIST_CREATED, &udev->state)) return -EINVAL; } @@ -498,20 +496,19 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd retval = -EFAULT; break; } - if (NULL != udev->dev->phys) - kfree(udev->dev->phys); - udev->dev->phys = kmalloc(length, GFP_KERNEL); - if (!udev->dev->phys) { + kfree(udev->dev->phys); + udev->dev->phys = phys = kmalloc(length, GFP_KERNEL); + if (!phys) { retval = -ENOMEM; break; } - if (copy_from_user(udev->dev->phys, p, length)) { - retval = -EFAULT; - kfree(udev->dev->phys); + if (copy_from_user(phys, p, length)) { udev->dev->phys = NULL; + kfree(phys); + retval = -EFAULT; break; } - udev->dev->phys[length-1] = '\0'; + phys[length - 1] = '\0'; break; case UI_BEGIN_FF_UPLOAD: @@ -520,7 +517,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd break; } req = uinput_request_find(udev, ff_up.request_id); - if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) { + if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { retval = -EINVAL; break; } @@ -538,7 +535,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd break; } req = uinput_request_find(udev, ff_erase.request_id); - if (!(req && req->code==UI_FF_ERASE)) { + if (!(req && req->code == UI_FF_ERASE)) { retval = -EINVAL; break; } @@ -556,14 +553,13 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd break; } req = uinput_request_find(udev, ff_up.request_id); - if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) { + if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { retval = -EINVAL; break; } req->retval = ff_up.retval; memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect)); - req->completed = 1; - wake_up_interruptible(&req->waitq); + uinput_request_done(udev, req); break; case UI_END_FF_ERASE: @@ -572,13 +568,12 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd break; } req = uinput_request_find(udev, ff_erase.request_id); - if (!(req && req->code==UI_FF_ERASE)) { + if (!(req && req->code == UI_FF_ERASE)) { retval = -EINVAL; break; } req->retval = ff_erase.retval; - req->completed = 1; - wake_up_interruptible(&req->waitq); + uinput_request_done(udev, req); break; default: diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a12e98158a75..0d68e5e0182a 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -2,7 +2,7 @@ * ALPS touchpad PS/2 mouse driver * * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> - * Copyright (c) 2003 Peter Osterlund <petero2@telia.com> + * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> * @@ -350,7 +350,6 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) static int alps_reconnect(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - unsigned char param[4]; int version; psmouse_reset(psmouse); @@ -358,21 +357,20 @@ static int alps_reconnect(struct psmouse *psmouse) if (!(priv->i = alps_get_model(psmouse, &version))) return -1; - if (priv->i->flags & ALPS_PASS && alps_passthrough_mode(psmouse, 1)) + if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) return -1; - if (alps_get_status(psmouse, param)) + if (alps_tap_mode(psmouse, 1)) { + printk(KERN_WARNING "alps.c: Failed to reenable hardware tapping\n"); return -1; - - if (!(param[0] & 0x04)) - alps_tap_mode(psmouse, 1); + } if (alps_absolute_mode(psmouse)) { - printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + printk(KERN_ERR "alps.c: Failed to reenable absolute mode\n"); return -1; } - if (priv->i->flags == ALPS_PASS && alps_passthrough_mode(psmouse, 0)) + if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) return -1; return 0; @@ -389,7 +387,6 @@ static void alps_disconnect(struct psmouse *psmouse) int alps_init(struct psmouse *psmouse) { struct alps_data *priv; - unsigned char param[4]; int version; psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL); @@ -403,16 +400,8 @@ int alps_init(struct psmouse *psmouse) if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) goto init_fail; - if (alps_get_status(psmouse, param)) { - printk(KERN_ERR "alps.c: touchpad status report request failed\n"); - goto init_fail; - } - - if (param[0] & 0x04) { - printk(KERN_INFO "alps.c: Enabling hardware tapping\n"); - if (alps_tap_mode(psmouse, 1)) - printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); - } + if (alps_tap_mode(psmouse, 1)) + printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); if (alps_absolute_mode(psmouse)) { printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 5ab1bd7d529d..48d2b20d2642 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -385,8 +385,6 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) if (buttons < 3) clear_bit(BTN_MIDDLE, psmouse->dev.keybit); - if (buttons < 2) - clear_bit(BTN_RIGHT, psmouse->dev.keybit); if (model_info) ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 19785a6c5abd..2bb2fe78bdca 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -344,6 +344,7 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) return -1; if (set_properties) { + set_bit(BTN_MIDDLE, psmouse->dev.keybit); set_bit(REL_WHEEL, psmouse->dev.relbit); if (!psmouse->vendor) psmouse->vendor = "Generic"; @@ -376,6 +377,7 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) return -1; if (set_properties) { + set_bit(BTN_MIDDLE, psmouse->dev.keybit); set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_EXTRA, psmouse->dev.keybit); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 36c721227b68..029309422409 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -219,7 +219,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet serio_interrupt(ptport, packet[1], 0, NULL); serio_interrupt(ptport, packet[4], 0, NULL); serio_interrupt(ptport, packet[5], 0, NULL); - if (child->type >= PSMOUSE_GENPS) + if (child->pktsize == 4) serio_interrupt(ptport, packet[2], 0, NULL); } else serio_interrupt(ptport, packet[1], 0, NULL); @@ -233,7 +233,7 @@ static void synaptics_pt_activate(struct psmouse *psmouse) /* adjust the touchpad to child's choice of protocol */ if (child) { - if (child->type >= PSMOUSE_GENPS) + if (child->pktsize == 4) priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT; else priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; @@ -608,6 +608,13 @@ static struct dmi_system_id toshiba_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"), }, }, + { + .ident = "Toshiba Dynabook", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME , "dynabook"), + }, + }, { } }; #endif @@ -656,7 +663,8 @@ int synaptics_init(struct psmouse *psmouse) * thye same as rate of standard PS/2 mouse. */ if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) { - printk(KERN_INFO "synaptics: Toshiba Satellite detected, limiting rate to 40pps.\n"); + printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", + dmi_get_system_info(DMI_PRODUCT_NAME)); psmouse->rate = 40; } #endif diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index b3710733b36b..98acf170252c 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -175,7 +175,7 @@ config SERIO_RAW allocating minor 1 (that historically corresponds to /dev/psaux) first. To bind this driver to a serio port use sysfs interface: - echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver + echo -n "serio_raw" > /sys/bus/serio/devices/serioX/drvctl To compile this driver as a module, choose M here: the module will be called serio_raw. diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 0487ecbb8a49..03877c84e6ff 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -131,12 +131,26 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, }, { + .ident = "Fujitsu-Siemens Lifebook T3010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), + }, + }, + { .ident = "Toshiba P10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), }, }, + { + .ident = "Alienware Sentia", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), + }, + }, { } }; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index a9bf549c8dc5..708a1d3beab9 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -100,7 +100,7 @@ struct i8042_port { static struct i8042_port i8042_ports[I8042_NUM_PORTS] = { { .disable = I8042_CTR_KBDDIS, - .irqen = I8042_CTR_KBDINT, + .irqen = I8042_CTR_KBDINT, .mux = -1, .name = "KBD", }, @@ -191,41 +191,45 @@ static int i8042_flush(void) static int i8042_command(unsigned char *param, int command) { unsigned long flags; - int retval = 0, i = 0; + int i, retval, auxerr = 0; if (i8042_noloop && command == I8042_CMD_AUX_LOOP) return -1; spin_lock_irqsave(&i8042_lock, flags); - retval = i8042_wait_write(); - if (!retval) { - dbg("%02x -> i8042 (command)", command & 0xff); - i8042_write_command(command & 0xff); + if ((retval = i8042_wait_write())) + goto out; + + dbg("%02x -> i8042 (command)", command & 0xff); + i8042_write_command(command & 0xff); + + for (i = 0; i < ((command >> 12) & 0xf); i++) { + if ((retval = i8042_wait_write())) + goto out; + dbg("%02x -> i8042 (parameter)", param[i]); + i8042_write_data(param[i]); } - if (!retval) - for (i = 0; i < ((command >> 12) & 0xf); i++) { - if ((retval = i8042_wait_write())) break; - dbg("%02x -> i8042 (parameter)", param[i]); - i8042_write_data(param[i]); - } + for (i = 0; i < ((command >> 8) & 0xf); i++) { + if ((retval = i8042_wait_read())) + goto out; - if (!retval) - for (i = 0; i < ((command >> 8) & 0xf); i++) { - if ((retval = i8042_wait_read())) break; - if (i8042_read_status() & I8042_STR_AUXDATA) - param[i] = ~i8042_read_data(); - else - param[i] = i8042_read_data(); - dbg("%02x <- i8042 (return)", param[i]); + if (command == I8042_CMD_AUX_LOOP && + !(i8042_read_status() & I8042_STR_AUXDATA)) { + retval = auxerr = -1; + goto out; } - spin_unlock_irqrestore(&i8042_lock, flags); + param[i] = i8042_read_data(); + dbg("%02x <- i8042 (return)", param[i]); + } if (retval) - dbg(" -- i8042 (timeout)"); + dbg(" -- i8042 (%s)", auxerr ? "auxerr" : "timeout"); + out: + spin_unlock_irqrestore(&i8042_lock, flags); return retval; } @@ -507,17 +511,17 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) */ param = 0xf0; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x0f) + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) return -1; param = mode ? 0x56 : 0xf6; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0xa9 : 0x09)) + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) return -1; param = mode ? 0xa4 : 0xa5; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0x5b : 0x5a)) + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) return -1; if (mux_version) - *mux_version = ~param; + *mux_version = param; return 0; } @@ -619,7 +623,7 @@ static int __init i8042_check_aux(void) */ param = 0x5a; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa5) { + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x5a) { /* * External connection test - filters out AT-soldered PS/2 i8042's @@ -630,7 +634,7 @@ static int __init i8042_check_aux(void) */ if (i8042_command(¶m, I8042_CMD_AUX_TEST) - || (param && param != 0xfa && param != 0xff)) + || (param && param != 0xfa && param != 0xff)) return -1; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index f367695e69b5..edd15db17715 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -389,6 +389,14 @@ static ssize_t serio_show_description(struct device *dev, struct device_attribut return sprintf(buf, "%s\n", serio->name); } +static ssize_t serio_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct serio *serio = to_serio_port(dev); + + return sprintf(buf, "serio:ty%02Xpr%02Xid%02Xex%02X\n", + serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); +} + static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf) { struct serio *serio = to_serio_port(dev); @@ -487,6 +495,7 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute * static struct device_attribute serio_device_attrs[] = { __ATTR(description, S_IRUGO, serio_show_description, NULL), + __ATTR(modalias, S_IRUGO, serio_show_modalias, NULL), __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver), __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode), __ATTR_NULL @@ -785,36 +794,37 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) #ifdef CONFIG_HOTPLUG -#define PUT_ENVP(fmt, val) \ -do { \ - envp[i++] = buffer; \ - length += snprintf(buffer, buffer_size - length, fmt, val); \ - if (buffer_size - length <= 0 || i >= num_envp) \ - return -ENOMEM; \ - length++; \ - buffer += length; \ -} while (0) +#define SERIO_ADD_HOTPLUG_VAR(fmt, val...) \ + do { \ + int err = add_hotplug_env_var(envp, num_envp, &i, \ + buffer, buffer_size, &len, \ + fmt, val); \ + if (err) \ + return err; \ + } while (0) + static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct serio *serio; int i = 0; - int length = 0; + int len = 0; if (!dev) return -ENODEV; serio = to_serio_port(dev); - PUT_ENVP("SERIO_TYPE=%02x", serio->id.type); - PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto); - PUT_ENVP("SERIO_ID=%02x", serio->id.id); - PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra); - + SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type); + SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto); + SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id); + SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra); + SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", + serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); envp[i] = NULL; return 0; } -#undef PUT_ENVP +#undef SERIO_ADD_HOTPLUG_VAR #else diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index d914e7e93db4..47e08de18d07 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -299,6 +299,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) serio_raw->dev.minor = PSMOUSE_MINOR; serio_raw->dev.name = serio_raw->name; + serio_raw->dev.dev = &serio->dev; serio_raw->dev.fops = &serio_raw_fops; err = misc_register(&serio_raw->dev); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 7e991274ea40..0489af5a80c9 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -58,7 +58,7 @@ config TOUCHSCREEN_ELO If unsure, say N. To compile this driver as a module, choose M here: the - module will be called gunze. + module will be called elo. config TOUCHSCREEN_MTOUCH tristate "MicroTouch serial touchscreens" diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a5a4c0ed8a14..a6d3baa46f61 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -869,11 +869,17 @@ static void suspend_targets(struct dm_table *t, unsigned postsuspend) void dm_table_presuspend_targets(struct dm_table *t) { + if (!t) + return; + return suspend_targets(t, 0); } void dm_table_postsuspend_targets(struct dm_table *t) { + if (!t) + return; + return suspend_targets(t, 1); } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 54fabbf06678..d487d9deb98e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -55,10 +55,10 @@ union map_info *dm_get_mapinfo(struct bio *bio) */ #define DMF_BLOCK_IO 0 #define DMF_SUSPENDED 1 -#define DMF_FS_LOCKED 2 struct mapped_device { - struct rw_semaphore lock; + struct rw_semaphore io_lock; + struct semaphore suspend_lock; rwlock_t map_lock; atomic_t holders; @@ -248,16 +248,16 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) */ static int queue_io(struct mapped_device *md, struct bio *bio) { - down_write(&md->lock); + down_write(&md->io_lock); if (!test_bit(DMF_BLOCK_IO, &md->flags)) { - up_write(&md->lock); + up_write(&md->io_lock); return 1; } bio_list_add(&md->deferred, bio); - up_write(&md->lock); + up_write(&md->io_lock); return 0; /* deferred successfully */ } @@ -568,14 +568,14 @@ static int dm_request(request_queue_t *q, struct bio *bio) int r; struct mapped_device *md = q->queuedata; - down_read(&md->lock); + down_read(&md->io_lock); /* * If we're suspended we have to queue * this io for later. */ while (test_bit(DMF_BLOCK_IO, &md->flags)) { - up_read(&md->lock); + up_read(&md->io_lock); if (bio_rw(bio) == READA) { bio_io_error(bio, bio->bi_size); @@ -594,11 +594,11 @@ static int dm_request(request_queue_t *q, struct bio *bio) * We're in a while loop, because someone could suspend * before we get to the following read lock. */ - down_read(&md->lock); + down_read(&md->io_lock); } __split_bio(md, bio); - up_read(&md->lock); + up_read(&md->io_lock); return 0; } @@ -610,7 +610,7 @@ static int dm_flush_all(request_queue_t *q, struct gendisk *disk, int ret = -ENXIO; if (map) { - ret = dm_table_flush_all(md->map); + ret = dm_table_flush_all(map); dm_table_put(map); } @@ -747,7 +747,8 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) goto bad1; memset(md, 0, sizeof(*md)); - init_rwsem(&md->lock); + init_rwsem(&md->io_lock); + init_MUTEX(&md->suspend_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->event_nr, 0); @@ -825,18 +826,13 @@ static void event_callback(void *context) wake_up(&md->eventq); } -static void __set_size(struct gendisk *disk, sector_t size) +static void __set_size(struct mapped_device *md, sector_t size) { - struct block_device *bdev; - - set_capacity(disk, size); - bdev = bdget_disk(disk, 0); - if (bdev) { - down(&bdev->bd_inode->i_sem); - i_size_write(bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); - up(&bdev->bd_inode->i_sem); - bdput(bdev); - } + set_capacity(md->disk, size); + + down(&md->frozen_bdev->bd_inode->i_sem); + i_size_write(md->frozen_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); + up(&md->frozen_bdev->bd_inode->i_sem); } static int __bind(struct mapped_device *md, struct dm_table *t) @@ -845,17 +841,18 @@ static int __bind(struct mapped_device *md, struct dm_table *t) sector_t size; size = dm_table_get_size(t); - __set_size(md->disk, size); + __set_size(md, size); if (size == 0) return 0; + dm_table_get(t); + dm_table_event_callback(t, event_callback, md); + write_lock(&md->map_lock); md->map = t; + dm_table_set_restrictions(t, q); write_unlock(&md->map_lock); - dm_table_get(t); - dm_table_event_callback(md->map, event_callback, md); - dm_table_set_restrictions(t, q); return 0; } @@ -935,7 +932,7 @@ void dm_put(struct mapped_device *md) struct dm_table *map = dm_get_table(md); if (atomic_dec_and_test(&md->holders)) { - if (!test_bit(DMF_SUSPENDED, &md->flags) && map) { + if (!dm_suspended(md)) { dm_table_presuspend_targets(map); dm_table_postsuspend_targets(map); } @@ -968,17 +965,17 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) { int r = -EINVAL; - down_write(&md->lock); + down(&md->suspend_lock); /* device must be suspended */ - if (!test_bit(DMF_SUSPENDED, &md->flags)) + if (!dm_suspended(md)) goto out; __unbind(md); r = __bind(md, table); out: - up_write(&md->lock); + up(&md->suspend_lock); return r; } @@ -986,16 +983,13 @@ out: * Functions to lock and unlock any filesystem running on the * device. */ -static int __lock_fs(struct mapped_device *md) +static int lock_fs(struct mapped_device *md) { - int error = -ENOMEM; - - if (test_and_set_bit(DMF_FS_LOCKED, &md->flags)) - return 0; + int r = -ENOMEM; md->frozen_bdev = bdget_disk(md->disk, 0); if (!md->frozen_bdev) { - DMWARN("bdget failed in __lock_fs"); + DMWARN("bdget failed in lock_fs"); goto out; } @@ -1003,13 +997,13 @@ static int __lock_fs(struct mapped_device *md) md->frozen_sb = freeze_bdev(md->frozen_bdev); if (IS_ERR(md->frozen_sb)) { - error = PTR_ERR(md->frozen_sb); + r = PTR_ERR(md->frozen_sb); goto out_bdput; } /* don't bdput right now, we don't want the bdev * to go away while it is locked. We'll bdput - * in __unlock_fs + * in unlock_fs */ return 0; @@ -1018,15 +1012,11 @@ out_bdput: md->frozen_sb = NULL; md->frozen_bdev = NULL; out: - clear_bit(DMF_FS_LOCKED, &md->flags); - return error; + return r; } -static void __unlock_fs(struct mapped_device *md) +static void unlock_fs(struct mapped_device *md) { - if (!test_and_clear_bit(DMF_FS_LOCKED, &md->flags)) - return; - thaw_bdev(md->frozen_bdev, md->frozen_sb); bdput(md->frozen_bdev); @@ -1043,50 +1033,37 @@ static void __unlock_fs(struct mapped_device *md) */ int dm_suspend(struct mapped_device *md) { - struct dm_table *map; + struct dm_table *map = NULL; DECLARE_WAITQUEUE(wait, current); - int error = -EINVAL; + int r = -EINVAL; - /* Flush I/O to the device. */ - down_read(&md->lock); - if (test_bit(DMF_BLOCK_IO, &md->flags)) - goto out_read_unlock; + down(&md->suspend_lock); + + if (dm_suspended(md)) + goto out; map = dm_get_table(md); - if (map) - /* This does not get reverted if there's an error later. */ - dm_table_presuspend_targets(map); - error = __lock_fs(md); - if (error) { - dm_table_put(map); - goto out_read_unlock; - } + /* This does not get reverted if there's an error later. */ + dm_table_presuspend_targets(map); - up_read(&md->lock); + /* Flush I/O to the device. */ + r = lock_fs(md); + if (r) + goto out; /* * First we set the BLOCK_IO flag so no more ios will be mapped. - * - * If the flag is already set we know another thread is trying to - * suspend as well, so we leave the fs locked for this thread. */ - error = -EINVAL; - down_write(&md->lock); - if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) { - if (map) - dm_table_put(map); - goto out_write_unlock; - } + down_write(&md->io_lock); + set_bit(DMF_BLOCK_IO, &md->flags); add_wait_queue(&md->wait, &wait); - up_write(&md->lock); + up_write(&md->io_lock); /* unplug */ - if (map) { + if (map) dm_table_unplug_all(map); - dm_table_put(map); - } /* * Then we wait for the already mapped ios to @@ -1102,62 +1079,67 @@ int dm_suspend(struct mapped_device *md) } set_current_state(TASK_RUNNING); - down_write(&md->lock); + down_write(&md->io_lock); remove_wait_queue(&md->wait, &wait); /* were we interrupted ? */ - error = -EINTR; - if (atomic_read(&md->pending)) - goto out_unfreeze; - - set_bit(DMF_SUSPENDED, &md->flags); + r = -EINTR; + if (atomic_read(&md->pending)) { + up_write(&md->io_lock); + unlock_fs(md); + clear_bit(DMF_BLOCK_IO, &md->flags); + goto out; + } + up_write(&md->io_lock); - map = dm_get_table(md); - if (map) - dm_table_postsuspend_targets(map); - dm_table_put(map); - up_write(&md->lock); + dm_table_postsuspend_targets(map); - return 0; + set_bit(DMF_SUSPENDED, &md->flags); -out_unfreeze: - __unlock_fs(md); - clear_bit(DMF_BLOCK_IO, &md->flags); -out_write_unlock: - up_write(&md->lock); - return error; + r = 0; -out_read_unlock: - up_read(&md->lock); - return error; +out: + dm_table_put(map); + up(&md->suspend_lock); + return r; } int dm_resume(struct mapped_device *md) { + int r = -EINVAL; struct bio *def; - struct dm_table *map = dm_get_table(md); + struct dm_table *map = NULL; - down_write(&md->lock); - if (!map || - !test_bit(DMF_SUSPENDED, &md->flags) || - !dm_table_get_size(map)) { - up_write(&md->lock); - dm_table_put(map); - return -EINVAL; - } + down(&md->suspend_lock); + if (!dm_suspended(md)) + goto out; + + map = dm_get_table(md); + if (!map || !dm_table_get_size(map)) + goto out; dm_table_resume_targets(map); - clear_bit(DMF_SUSPENDED, &md->flags); + + down_write(&md->io_lock); clear_bit(DMF_BLOCK_IO, &md->flags); def = bio_list_get(&md->deferred); __flush_deferred_io(md, def); - up_write(&md->lock); - __unlock_fs(md); + up_write(&md->io_lock); + + unlock_fs(md); + + clear_bit(DMF_SUSPENDED, &md->flags); + dm_table_unplug_all(map); + + r = 0; + +out: dm_table_put(map); + up(&md->suspend_lock); - return 0; + return r; } /*----------------------------------------------------------------- diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4698d5f79575..43f231a467d5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (!conf->chunk_size || conf->chunk_size % 4) { printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f5ee16805111..495dee1d1e83 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (conf->raid_disks < 4) { printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 51a0f6d68e73..67f331eeeb19 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1,5 +1,5 @@ /* - $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $ + $Id: bttv-driver.c,v 1.45 2005/07/20 19:43:24 mkrufky Exp $ bttv - Bt848 frame grabber driver @@ -3869,11 +3869,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - if (!pci_dma_supported(dev,0xffffffff)) { - printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr); - result = -EIO; - goto fail1; - } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 191eaf1714ba..f2af9e1454f0 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -1,5 +1,5 @@ /* - * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $ + * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $ * * bttv - Bt848 frame grabber driver * @@ -135,7 +135,9 @@ #define BTTV_DVICO_DVBT_LITE 0x80 #define BTTV_TIBET_CS16 0x83 #define BTTV_KODICOM_4400R 0x84 -#define BTTV_ADLINK_RTV24 0x85 +#define BTTV_ADLINK_RTV24 0x86 +#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_ACORP_Y878F 0x88 /* i2c address list */ #define I2C_TSA5522 0xc2 diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index f3293e4a15ad..aab094bc243d 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -1,5 +1,5 @@ /* - $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $ + $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $ bttv - Bt848 frame grabber driver @@ -27,7 +27,7 @@ #define _BTTVP_H_ #include <linux/version.h> -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) #include <linux/types.h> #include <linux/wait.h> diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3d0c784b376f..ebf02a7f81e8 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $ + * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * card-specific stuff. @@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, }, [CX88_BOARD_PIXELVIEW] = { @@ -496,6 +499,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, .dvb = 1, }, @@ -753,6 +759,27 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { + .name = "DViCO FusionHDTV 5 Gold", + .tuner_type = TUNER_LG_TDVS_H062F, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0f0d, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0f00, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0f00, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -880,6 +907,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd500, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5588a3aeecb4..5f58c103198a 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $ + * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * video4linux video interface @@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file) struct cx88_core *core = dev->core; int board = core->board; dprintk(1,"video_open: setting radio device\n"); + cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); - cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); dev->core->tvaudio = WW_FM; cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b008f7db6dfd..da65dc92787c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -1,5 +1,5 @@ /* - * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $ + * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $ * * v4l2 device driver for cx2388x based TV cards * @@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 6239254db27e..62f1b8ddb98b 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -741,11 +741,9 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) schedule_timeout(msecs_to_jiffies(timeout)); } } - if (current->flags & PF_FREEZE) { - refrigerator (); - } remove_wait_queue(&msp->wq, &wait); + try_to_freeze(); return msp->restart; } diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 93dd61978541..1203b93a572c 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $ + * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $ * * device driver for philips saa7134 based TV cards * i2c interface support @@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; + /* ensure that the bus is idle for at least one bit slot */ + msleep(1); d1printk("\n"); return num; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 6836c07794fc..2af0cb2a731b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -1,5 +1,5 @@ /* - * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $ + * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $ * * v4l2 device driver for philips saa7134 based TV cards * @@ -21,7 +21,7 @@ */ #include <linux/version.h> -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14) #include <linux/pci.h> #include <linux/i2c.h> diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 4d27ac1b7fb8..cebcc1fa68d1 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -2,7 +2,7 @@ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview * I2C address is allways 0xC0. * - * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $ * * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) * This code is placed under the terms of the GNU General Public License @@ -15,7 +15,6 @@ #include <linux/videodev.h> #include <linux/delay.h> #include <media/tuner.h> -#include <media/tuner.h> #define PREFIX "TEA5767 " @@ -293,16 +292,16 @@ static int tea5767_stereo(struct i2c_client *c) int tea5767_autodetection(struct i2c_client *c) { - unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; + unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int rc; struct tuner *t = i2c_get_clientdata(c); - if (5 != (rc = i2c_master_recv(c, buffer, 5))) { + if (7 != (rc = i2c_master_recv(c, buffer, 7))) { tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); return EINVAL; } - /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */ + /* If all bytes are the same then it's a TV tuner and not a tea5767 */ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && buffer[0] == buffer[3] && buffer[0] == buffer[4]) { tuner_warn("All bytes are equal. It is not a TEA5767\n"); @@ -318,6 +317,17 @@ int tea5767_autodetection(struct i2c_client *c) tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); return EINVAL; } + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } + + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } tuner_warn("TEA5767 detected.\n"); return 0; @@ -327,10 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - if (tea5767_autodetection(c) == EINVAL) - return EINVAL; - - tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); + tuner_info("type set to %d (%s)\n", t->type, + "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); t->tv_freq = set_tv_freq; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index b25a9c08ac02..f0a579827a24 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -23,6 +23,8 @@ #include <media/tuner.h> #include <media/audiochip.h> +#include "msp3400.h" + #define UNSET (-1U) /* standard i2c insmod options */ @@ -42,6 +44,9 @@ module_param(addr, int, 0444); static unsigned int no_autodetect = 0; module_param(no_autodetect, int, 0444); +static unsigned int show_i2c = 0; +module_param(show_i2c, int, 0444); + /* insmod options used at runtime => read/write */ unsigned int tuner_debug = 0; module_param(tuner_debug, int, 0644); @@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + if (show_i2c) { + unsigned char buffer[16]; + int i,rc; + + memset(buffer, 0, sizeof(buffer)); + rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + printk("tuner-%04x I2C RECV = ",addr); + for (i=0;i<rc;i++) + printk("%02x ",buffer[i]); + printk("\n"); + } /* TEA5767 autodetection code - only for addr = 0xc0 */ if (!no_autodetect) { if (addr == 0x60) { @@ -451,6 +467,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } break; + case VIDIOCSAUDIO: + if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + /* Should be implemented, since bttv calls it */ + tuner_dbg("VIDIOCSAUDIO not implemented.\n"); + + break; + case MSP_SET_MATRIX: case TDA9887_SET_CONFIG: break; /* --- v4l ioctls --- */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index a3f8e83f5314..de0c93aeb75d 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-simple.c,v 1.39 2005/07/07 01:49:30 mkrufky Exp $ + * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $ * * i2c tv tuner chip device driver * controls all those simple 4-control-bytes style tuners. @@ -245,6 +245,12 @@ static struct tunertype tuners[] = { /* see tea5767.c for details */}, { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, + + { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC, + 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, + + { "Ymec TVF66T5-B/DFF", Philips, PAL, + 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 62b03ef091e0..127ec38ebd60 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -189,7 +189,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1236 MK3"}, { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, - { TUNER_ABSENT, "TCL MFPE05 2"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, /* 90-99 */ { TUNER_ABSENT, "LG TALN H202T"}, { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"}, diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 2c6dc24c3728..b780307093eb 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -417,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; + int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; @@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out2; } } -printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", + ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); ioaddr &= ~3; outw(PP_ChipID, ioaddr + ADD_PORT); - if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { - printk(KERN_ERR "%s: incorrect signature 0x%x\n", - dev->name, inw(ioaddr + DATA_PORT)); + tmp = inw(ioaddr + DATA_PORT); + if (tmp != CHIP_EISA_ID_SIG) { + printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" + CHIP_EISA_ID_SIG_STR "\n", + dev->name, ioaddr + DATA_PORT, tmp); retval = -ENODEV; goto out2; } diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index bd3ad8e6cce9..decea264f121 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h @@ -93,6 +93,7 @@ #endif #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ +#define CHIP_EISA_ID_SIG_STR "0x630E" #ifdef IBMEIPKT #define EISA_ID_SIG 0x4D24 /* IBM */ diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig index 7cdebe1a0b61..0cd54306e636 100644 --- a/drivers/net/hamradio/Kconfig +++ b/drivers/net/hamradio/Kconfig @@ -17,7 +17,7 @@ config MKISS config 6PACK tristate "Serial port 6PACK driver" - depends on AX25 && BROKEN_ON_SMP + depends on AX25 ---help--- 6pack is a transmission protocol for the data exchange between your PC and your TNC (the Terminal Node Controller acts as a kind of diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 82570ec44d8e..6ee4771addf1 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5133,6 +5133,84 @@ static void __devexit skge_remove_one(struct pci_dev *pdev) kfree(pAC); } +#ifdef CONFIG_PM +static int skge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + + if (netif_running(dev)) { + netif_carrier_off(dev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + netif_device_detach(dev); + } + if (otherdev != dev) { + if (netif_running(otherdev)) { + netif_carrier_off(otherdev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + netif_device_detach(otherdev); + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + if (pAC->AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int skge_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); + if (pAC->GIni.GIMacsFound == 2) + ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + else + ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + if (ret) { + printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); + pAC->AllocFlag &= ~SK_ALLOC_IRQ; + dev->irq = 0; + pci_disable_device(pdev); + return -EBUSY; + } + + netif_device_attach(dev); + if (netif_running(dev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 0); /* first device */ + } + if (otherdev != dev) { + netif_device_attach(otherdev); + if (netif_running(otherdev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* second device */ + } + } + + return 0; +} +#else +#define skge_suspend NULL +#define skge_resume NULL +#endif + static struct pci_device_id skge_pci_tbl[] = { { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, @@ -5158,6 +5236,8 @@ static struct pci_driver skge_driver = { .id_table = skge_pci_tbl, .probe = skge_probe_one, .remove = __devexit_p(skge_remove_one), + .suspend = skge_suspend, + .resume = skge_resume, }; static int __init skge_init(void) diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c index df4483429a77..6cb49dd02251 100644 --- a/drivers/net/sk98lin/skgeinit.c +++ b/drivers/net/sk98lin/skgeinit.c @@ -2016,7 +2016,7 @@ SK_IOC IoC) /* IO context */ * we set the PHY to coma mode and switch to D3 power state. */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* for all ports switch PHY to coma mode */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c index 94a09deecb32..42d2d963150a 100644 --- a/drivers/net/sk98lin/skxmac2.c +++ b/drivers/net/sk98lin/skxmac2.c @@ -1065,7 +1065,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; @@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5cacc7ad9e79..f15739481d62 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -42,7 +42,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "0.7" +#define DRV_VERSION "0.8" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -55,7 +55,7 @@ #define ETH_JUMBO_MTU 9000 #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 -#define BLINK_HZ (HZ/4) +#define BLINK_MS 250 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); @@ -75,7 +75,6 @@ static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ @@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else { u32 setting; - switch(ecmd->speed) { + switch (ecmd->speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev, return 0; } -static void skge_led_on(struct skge_hw *hw, int port) +enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; +static void skge_led(struct skge_port *skge, enum led_mode mode) { + struct skge_hw *hw = skge->hw; + int port = skge->port; + + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, B0_LED, LED_STAT_ON); + switch (mode) { + case LED_MODE_OFF: + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + break; - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + case LED_MODE_ON: + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - /* For Broadcom Phy only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); - } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - } -} + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); -static void skge_led_off(struct skge_hw *hw, int port) -{ - if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - skge_write8(hw, B0_LED, LED_STAT_OFF); + break; - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + case LED_MODE_TST: + skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - /* Broadcom only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); + break; + } } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); + switch (mode) { + case LED_MODE_OFF: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_OFF) | + PHY_M_LED_MO_10(MO_LED_OFF) | + PHY_M_LED_MO_100(MO_LED_OFF) | + PHY_M_LED_MO_1000(MO_LED_OFF) | + PHY_M_LED_MO_RX(MO_LED_OFF)); + break; + case LED_MODE_ON: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, + PHY_M_LED_PULS_DUR(PULS_170MS) | + PHY_M_LED_BLINK_RT(BLINK_84MS) | + PHY_M_LEDC_TX_CTRL | + PHY_M_LEDC_DP_CTRL); + + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_RX(MO_LED_OFF) | + (skge->speed == SPEED_100 ? + PHY_M_LED_MO_100(MO_LED_ON) : 0)); + break; + case LED_MODE_TST: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_ON) | + PHY_M_LED_MO_10(MO_LED_ON) | + PHY_M_LED_MO_100(MO_LED_ON) | + PHY_M_LED_MO_1000(MO_LED_ON) | + PHY_M_LED_MO_RX(MO_LED_ON)); + } } -} - -static void skge_blink_timer(unsigned long data) -{ - struct skge_port *skge = (struct skge_port *) data; - struct skge_hw *hw = skge->hw; - unsigned long flags; - - spin_lock_irqsave(&hw->phy_lock, flags); - if (skge->blink_on) - skge_led_on(hw, skge->port); - else - skge_led_off(hw, skge->port); - spin_unlock_irqrestore(&hw->phy_lock, flags); - - skge->blink_on = !skge->blink_on; - mod_timer(&skge->led_blink, jiffies + BLINK_HZ); + spin_unlock_bh(&hw->phy_lock); } /* blink LED's for finding board */ static int skge_phys_id(struct net_device *dev, u32 data) { struct skge_port *skge = netdev_priv(dev); + unsigned long ms; + enum led_mode mode = LED_MODE_TST; if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; + else + ms = data * 1000; - /* start blinking */ - skge->blink_on = 1; - mod_timer(&skge->led_blink, jiffies+1); + while (ms > 0) { + skge_led(skge, mode); + mode ^= LED_MODE_TST; - msleep_interruptible(data * 1000); - del_timer_sync(&skge->led_blink); + if (msleep_interruptible(BLINK_MS)) + break; + ms -= BLINK_MS; + } - skge_led_off(skge->hw, skge->port); + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); return 0; } @@ -1028,7 +1041,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) } /* Check Duplex mismatch */ - switch(aux & PHY_B_AS_AN_RES_MSK) { + switch (aux & PHY_B_AS_AN_RES_MSK) { case PHY_B_RES_1000FD: skge->duplex = DUPLEX_FULL; break; @@ -1099,7 +1112,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) r |= XM_MMU_NO_PRE; xm_write16(hw, port, XM_MMU_CMD,r); - switch(id1) { + switch (id1) { case PHY_BCOM_ID1_C0: /* * Workaround BCOM Errata for the C0 type. @@ -1194,13 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) xm_write16(hw, port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* initialize Rx, Tx and Link LED */ - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - /* Unreset the XMAC. */ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); @@ -1209,7 +1215,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * namely for the 1000baseTX cards that use the XMAC's * GMII mode. */ - spin_lock_bh(&hw->phy_lock); /* Take external Phy out of reset */ r = skge_read32(hw, B2_GP_IO); if (port == 0) @@ -1219,7 +1224,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) skge_write32(hw, B2_GP_IO, r); skge_read32(hw, B2_GP_IO); - spin_unlock_bh(&hw->phy_lock); /* Enable GMII interfac */ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); @@ -1569,7 +1573,6 @@ static void yukon_init(struct skge_hw *hw, int port) { struct skge_port *skge = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv; - u16 ledctrl, ledover; pr_debug("yukon_init\n"); if (skge->autoneg == AUTONEG_ENABLE) { @@ -1641,32 +1644,11 @@ static void yukon_init(struct skge_hw *hw, int port) gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - /* Setup Phy LED's */ - ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); - ledover = 0; - - ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; - - /* turn off the Rx LED (LED_RX) */ - ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); - - /* disable blink mode (LED_DUPLEX) on collisions */ - ctrl |= PHY_M_LEDC_DP_CTRL; - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); - - if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) { - /* turn on 100 Mbps LED (LED_LINK100) */ - ledover |= PHY_M_LED_MO_100(MO_LED_ON); - } - - if (ledover) - gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); - /* Enable phy interrupt on autonegotiation complete (or link up) */ if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); } static void yukon_reset(struct skge_hw *hw, int port) @@ -1691,7 +1673,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- set PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); @@ -1701,7 +1683,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- clear PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9) & ~GP_IO_9); @@ -1745,9 +1727,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) gma_write16(hw, port, GM_GP_CTRL, reg); skge_read16(hw, GMAC_IRQ_SRC); - spin_lock_bh(&hw->phy_lock); yukon_init(hw, port); - spin_unlock_bh(&hw->phy_lock); /* MIB clear */ reg = gma_read16(hw, port, GM_PHY_ADDR); @@ -1796,7 +1776,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) reg &= ~GMF_RX_F_FL_ON; skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); @@ -1813,19 +1793,19 @@ static void yukon_stop(struct skge_port *skge) int port = skge->port; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) { + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { skge_write32(hw, B2_GP_IO, skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); } gma_write16(hw, port, GM_GP_CTRL, gma_read16(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA)); + & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); gma_read16(hw, port, GM_GP_CTRL); /* set GPHY Control reset */ - gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); - gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); + skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); } static void yukon_get_stats(struct skge_port *skge, u64 *data) @@ -1856,11 +1836,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port) if (status & GM_IS_RX_FF_OR) { ++skge->net_stats.rx_fifo_errors; - gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); } + if (status & GM_IS_TX_FF_UR) { ++skge->net_stats.tx_fifo_errors; - gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); } } @@ -1896,7 +1877,7 @@ static void yukon_link_up(struct skge_port *skge) reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; gma_write16(hw, port, GM_GP_CTRL, reg); - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); skge_link_up(skge); } @@ -1904,12 +1885,14 @@ static void yukon_link_down(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; + u16 ctrl; pr_debug("yukon_link_down\n"); gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); - gm_phy_write(hw, port, GM_GP_CTRL, - gm_phy_read(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); + + ctrl = gma_read16(hw, port, GM_GP_CTRL); + ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + gma_write16(hw, port, GM_GP_CTRL, ctrl); if (skge->flow_control == FLOW_MODE_REM_SEND) { /* restore Asymmetric Pause bit */ @@ -2097,10 +2080,12 @@ static int skge_up(struct net_device *dev) skge_write32(hw, B0_IMSK, hw->intr_mask); /* Initialze MAC */ + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); + spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); @@ -2116,6 +2101,7 @@ static int skge_up(struct net_device *dev) /* Start receiver BMU */ wmb(); skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); + skge_led(skge, LED_MODE_ON); pr_debug("skge_up completed\n"); return 0; @@ -2140,8 +2126,6 @@ static int skge_down(struct net_device *dev) netif_stop_queue(dev); - del_timer_sync(&skge->led_blink); - /* Stop transmitter */ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), @@ -2175,15 +2159,12 @@ static int skge_down(struct net_device *dev) if (hw->chip_id == CHIP_ID_GENESIS) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP); } else { skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); } - /* turn off led's */ - skge_write16(hw, B0_LED, LED_STAT_OFF); + skge_led(skge, LED_MODE_OFF); skge_tx_clean(skge); skge_rx_clean(skge); @@ -2633,11 +2614,17 @@ static inline void skge_tx_intr(struct net_device *dev) spin_unlock(&skge->tx_lock); } +/* Parity errors seem to happen when Genesis is connected to a switch + * with no other ports present. Heartbeat error?? + */ static void skge_mac_parity(struct skge_hw *hw, int port) { - printk(KERN_ERR PFX "%s: mac data parity error\n", - hw->dev[port] ? hw->dev[port]->name - : (port == 0 ? "(port A)": "(port B")); + struct net_device *dev = hw->dev[port]; + + if (dev) { + struct skge_port *skge = netdev_priv(dev); + ++skge->net_stats.tx_heartbeat_errors; + } if (hw->chip_id == CHIP_ID_GENESIS) skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), @@ -3083,10 +3070,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, spin_lock_init(&skge->tx_lock); - init_timer(&skge->led_blink); - skge->led_blink.function = skge_blink_timer; - skge->led_blink.data = (unsigned long) skge; - if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; skge->rx_csum = 1; diff --git a/drivers/net/skge.h b/drivers/net/skge.h index fced3d2bc072..b432f1bb8168 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -1449,10 +1449,12 @@ enum { PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ PHY_M_IS_JABBER = 1<<0, /* Jabber */ -}; -#define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) + PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, + + PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, +}; /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ enum { @@ -1509,7 +1511,7 @@ enum { PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ }; -#define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK) +#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) enum { PULS_NO_STR = 0,/* no pulse stretching */ @@ -1522,7 +1524,7 @@ enum { PULS_1300MS = 7,/* 1.3 s to 2.7 s */ }; -#define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK) +#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { BLINK_42MS = 0,/* 42 ms */ @@ -1602,9 +1604,9 @@ enum { PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ }; -#define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK) +#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) enum { LED_PAR_CTRL_COLX = 0x00, @@ -1640,7 +1642,7 @@ enum { PHY_M_MAC_MD_COPPER = 5,/* Copper only */ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ }; -#define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK) +#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ enum { @@ -1650,10 +1652,10 @@ enum { PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ }; -#define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK) -#define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK) -#define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK) -#define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK) +#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) +#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) +#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) +#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) /* GMAC registers */ /* Port Registers */ @@ -2505,8 +2507,6 @@ struct skge_port { dma_addr_t dma; unsigned long mem_size; unsigned int rx_buf_size; - - struct timer_list led_blink; }; @@ -2606,17 +2606,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) skge_write16(hw, SK_GMAC_REG(port,r), v); } -static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v) -{ - skge_write16(hw, SK_GMAC_REG(port, r), (u16) v); - skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16)); -} - -static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v) -{ - skge_write8(hw, SK_GMAC_REG(port,r), v); -} - static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, const u8 *addr) { diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 7089d86e857a..a9b06b8d8e3f 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -188,7 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_IRQ_TRIGGER_TYPE (( \ machine_is_omap_h2() \ || machine_is_omap_h3() \ - || (machine_is_omap_innovator() && !cpu_is_omap150()) \ + || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ ) ? IRQT_FALLING : IRQT_RISING) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index fedae89d8f7d..fb9a11243d2a 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -60,7 +60,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, continue; /* Ok, try it out.. */ - ret = allocate_resource(r, res, size, min, -1, align, + ret = allocate_resource(r, res, size, + r->start ? : min, + -1, align, alignf, alignf_data); if (ret == 0) break; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index df3bdae2040f..93e8a878ea95 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -507,7 +507,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); if (!is_cardbus) { - child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; + child->bridge_ctl = bctl | PCI_BRIDGE_CTL_NO_ISA; /* * Adjust subordinate busnr in parent buses. * We do this before scanning for children because diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1521fd5d95cc..8d0968bd527e 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -820,6 +820,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x0001: /* Toshiba Satellite A40 */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) + switch(dev->subsystem_device) { + case 0x0001: /* Toshiba Tecra M2 */ + asus_hides_smbus = 1; + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch(dev->subsystem_device) { diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 838575e3fac6..713c78f3a65d 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -125,7 +125,9 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) image += readw(pds + 16) * 512; } while (!last_image); - *size = image - rom; + /* never return a size larger than the PCI resource window */ + /* there are known ROMs that get the size wrong */ + *size = min((size_t)(image - rom), *size); return rom; } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 9fe48f712be9..a2eebc6eaacc 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -51,8 +51,6 @@ pbus_assign_resources_sorted(struct pci_bus *bus) struct resource_list head, *list, *tmp; int idx; - bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA; - head.next = NULL; list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; @@ -62,10 +60,6 @@ pbus_assign_resources_sorted(struct pci_bus *bus) class == PCI_CLASS_BRIDGE_HOST) continue; - if (class == PCI_CLASS_DISPLAY_VGA || - class == PCI_CLASS_NOT_DEFINED_VGA) - bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; - pdev_sort_resources(dev, &head); } @@ -509,12 +503,6 @@ pci_bus_assign_resources(struct pci_bus *bus) pbus_assign_resources_sorted(bus); - if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) { - /* Propagate presence of the VGA to upstream bridges */ - for (b = bus; b->parent; b = b->parent) { - b->bridge_ctl |= PCI_BRIDGE_CTL_VGA; - } - } list_for_each_entry(dev, &bus->devices, bus_list) { b = dev->subordinate; if (!b) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index d63f22a5bf7e..43da2e92d50f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data) static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) { if (!s->pcmcia_state.device_add_pending) { - schedule_work(&s->device_add); s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); } return; } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 744e469a9eda..91e7457d5b04 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -642,6 +642,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } else { if (type & IORESOURCE_PREFETCH) { @@ -650,6 +651,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } /* Approximating prefetchable by non-prefetchable */ res->flags = IORESOURCE_MEM; @@ -659,6 +661,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } @@ -1107,8 +1110,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); pci_disable_device(dev); - free_irq(dev->irq, socket); - /* * Some laptops (IBM T22) do not like us putting the Cardbus * bridge into D3. At a guess, some other laptop will @@ -1134,13 +1135,6 @@ static int yenta_dev_resume (struct pci_dev *dev) pci_enable_device(dev); pci_set_master(dev); - if (socket->cb_irq) - if (request_irq(socket->cb_irq, yenta_interrupt, - SA_SHIRQ, "yenta", socket)) { - printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n"); - socket->cb_irq = 0; - } - if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 9b7f6f548b1d..ee7a05e0c3ba 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -235,6 +235,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) sch->schib.pmcw.pam & sch->schib.pmcw.pom & sch->opm; + /* Check since device may again have become not operational. */ + if (!sch->schib.pmcw.dnv) + state = DEV_STATE_NOT_OPER; if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) /* Force reprobe on all chpids. */ old_lpm = 0; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 96df148ed969..f1e8c4223ed1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -424,7 +424,7 @@ config SCSI_IN2000 source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_SATA - bool "Serial ATA (SATA) support" + tristate "Serial ATA (SATA) support" depends on SCSI help This driver family supports Serial ATA host controllers diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 3a11a536c0da..4ab07861b457 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -15,11 +15,7 @@ #define AAC_MAX_LUN (8) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) -/* - * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512 - * Linux has starvation problems if we permit larger than 4MB I/O ... - */ -#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192) +#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512) /* * These macros convert from physical channels to virtual channels diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c1a4f978fcba..562da90480a1 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -374,7 +374,8 @@ static int aac_slave_configure(struct scsi_device *sdev) else scsi_adjust_queue_depth(sdev, 0, 1); - if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT) + if (!(((struct aac_dev *)host->hostdata)->adapter_info.options + & AAC_OPT_NEW_COMM)) blk_queue_max_segment_size(sdev->request_queue, 65536); return 0; diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c index c34639481904..f936b691232f 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c @@ -369,7 +369,7 @@ output_code() fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], @@ -613,7 +613,7 @@ output_listing(char *ifilename) line++; } fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h index 3e80f07df49c..e64f802bbaaa 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h @@ -42,8 +42,10 @@ * $FreeBSD$ */ +#include <asm/byteorder.h> + struct ins_format1 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t immediate : 8, source : 9, destination : 9, @@ -61,7 +63,7 @@ struct ins_format1 { }; struct ins_format2 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t shift_control : 8, source : 9, destination : 9, @@ -79,7 +81,7 @@ struct ins_format2 { }; struct ins_format3 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t immediate : 8, source : 9, address : 10, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 3be546439252..a2cfade2c1c6 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -38,6 +38,7 @@ enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ ICH5_PMR = 0x90, /* port mapping register */ ICH5_PCS = 0x92, /* port control and status */ + PIIX_SCC = 0x0A, /* sub-class code register */ PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ @@ -62,6 +63,8 @@ enum { ich6_sata_rm = 4, ich7_sata = 5, esb2_sata = 6, + + PIIX_AHCI_DEVICE = 6, }; static int piix_init_one (struct pci_dev *pdev, @@ -574,11 +577,11 @@ static int piix_disable_ahci(struct pci_dev *pdev) addr = pci_resource_start(pdev, AHCI_PCI_BAR); if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR)) return 0; - + mmio = ioremap(addr, 64); if (!mmio) return -ENOMEM; - + tmp = readl(mmio + AHCI_GLOBAL_CTL); if (tmp & AHCI_ENABLE) { tmp &= ~AHCI_ENABLE; @@ -588,7 +591,7 @@ static int piix_disable_ahci(struct pci_dev *pdev) if (tmp & AHCI_ENABLE) rc = -EIO; } - + iounmap(mmio); return rc; } @@ -626,9 +629,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port_info[1] = NULL; if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { - int rc = piix_disable_ahci(pdev); - if (rc) - return rc; + u8 tmp; + pci_read_config_byte(pdev, PIIX_SCC, &tmp); + if (tmp == PIIX_AHCI_DEVICE) { + int rc = piix_disable_ahci(pdev); + if (rc) + return rc; + } } if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 18c58fb73899..6b321e82cafb 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -394,7 +394,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) } static int __devinit -serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { struct uart_port port; int ret, line, flags = dev_id->driver_data; @@ -406,15 +406,23 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) } memset(&port, 0, sizeof(struct uart_port)); - port.irq = pnp_irq(dev,0); - port.iobase = pnp_port_start(dev, 0); + port.irq = pnp_irq(dev, 0); + if (pnp_port_valid(dev, 0)) { + port.iobase = pnp_port_start(dev, 0); + port.iotype = UPIO_PORT; + } else if (pnp_mem_valid(dev, 0)) { + port.mapbase = pnp_mem_start(dev, 0); + port.iotype = UPIO_MEM; + port.flags = UPF_IOREMAP; + } else + return -ENODEV; #ifdef SERIAL_DEBUG_PNP - printk("Setup PNP port: port %x, irq %d, type %d\n", - port.iobase, port.irq, port.iotype); + printk("Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", + port.iobase, port.mapbase, port.irq, port.iotype); #endif - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; port.uartclk = 1843200; port.dev = &dev->dev; @@ -426,7 +434,7 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) } -static void __devexit serial_pnp_remove(struct pnp_dev * dev) +static void __devexit serial_pnp_remove(struct pnp_dev *dev) { long line = (long)pnp_get_drvdata(dev); if (line) diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index cd329dd7fb86..85dacc92545a 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -20,6 +20,7 @@ config USB_ARCH_HAS_OHCI default y if SA1111 default y if ARCH_OMAP default y if ARCH_LH7A404 + default y if ARCH_S3C2410 default y if PXA27x # PPC: default y if STB03xxx diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index adff5a77e31f..16ecad30e29c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -980,6 +980,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 787c27a63c51..f86bf1454e21 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -569,8 +569,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) free_page((unsigned long)tbuf); return -EINVAL; } - snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", - ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + snoop(&dev->dev, "control read: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); usb_unlock_device(dev); i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, @@ -579,11 +582,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) if ((i > 0) && ctrl.wLength) { if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); - for (j = 0; j < ctrl.wLength; ++j) + for (j = 0; j < i; ++j) printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } - if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) { + if (copy_to_user(ctrl.data, tbuf, i)) { free_page((unsigned long)tbuf); return -EFAULT; } @@ -595,8 +598,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) return -EFAULT; } } - snoop(&dev->dev, "control write: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", - ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + snoop(&dev->dev, "control write: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); if (usbfs_snoop) { dev_info(&dev->dev, "control write: data: "); for (j = 0; j < ctrl.wLength; ++j) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8616356f55e8..79422a3b07bc 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -939,9 +939,9 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) case USB_SPEED_HIGH: /* ISOC or INTR */ // FIXME adjust for input vs output if (isoc) - tmp = HS_USECS (bytecount); + tmp = HS_NSECS_ISO (bytecount); else - tmp = HS_USECS_ISO (bytecount); + tmp = HS_NSECS (bytecount); return tmp; default: pr_debug ("%s: bogus device speed!\n", usbcore_name); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 67db4a999b93..28055f95645b 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -334,17 +334,19 @@ extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); /* - * Ceiling microseconds (typical) for that many bytes at high speed + * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed * to preallocate bandwidth) */ #define USB2_HOST_DELAY 5 /* nsec, guess */ -#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ +#define HS_NSECS(bytes) ( ((55 * 8 * 2083)/1000) \ + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + USB2_HOST_DELAY) -#define HS_USECS_ISO(bytes) NS_TO_US ( ((38 * 8 * 2083)/1000) \ +#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083)/1000) \ + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + USB2_HOST_DELAY) +#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes)) +#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes)) extern long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index a428ef479bd7..88d1b376f67c 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -985,8 +985,10 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *interface; - /* remove this interface */ + /* remove this interface if it has been registered */ interface = dev->actconfig->interface[i]; + if (!klist_node_attached(&interface->dev.knode_bus)) + continue; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); usb_remove_sysfs_intf_files(interface); @@ -1439,7 +1441,7 @@ free_interfaces: } } - return ret; + return 0; } // synchronous request completion model diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index d74b2d68a50e..4f97a4ad1ed3 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -657,8 +657,8 @@ qh_make ( * For control/bulk requests, the HC or TT handles these. */ if (type == PIPE_INTERRUPT) { - qh->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, - hb_mult (maxp) * max_packet (maxp)); + qh->usecs = NS_TO_US (usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, + hb_mult (maxp) * max_packet (maxp))); qh->start = NO_FRAME; if (urb->dev->speed == USB_SPEED_HIGH) { diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 68decab280dd..56b43f2a0e52 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -887,6 +887,10 @@ MODULE_LICENSE ("GPL"); #include "ohci-sa1111.c" #endif +#ifdef CONFIG_ARCH_S3C2410 +#include "ohci-s3c2410.c" +#endif + #ifdef CONFIG_ARCH_OMAP #include "ohci-omap.c" #endif @@ -909,6 +913,7 @@ MODULE_LICENSE ("GPL"); #if !(defined(CONFIG_PCI) \ || defined(CONFIG_SA1111) \ + || defined(CONFIG_ARCH_S3C2410) \ || defined(CONFIG_ARCH_OMAP) \ || defined (CONFIG_ARCH_LH7A404) \ || defined (CONFIG_PXA27x) \ diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c new file mode 100644 index 000000000000..e9401662503c --- /dev/null +++ b/drivers/usb/host/ohci-s3c2410.c @@ -0,0 +1,496 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> + * (C) Copyright 2002 Hewlett-Packard Company + * + * USB Bus Glue for Samsung S3C2410 + * + * Written by Christopher Hoover <ch@hpl.hp.com> + * Based on fragments of previous driver by Rusell King et al. + * + * Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c + * by Ben Dooks, <ben@simtec.co.uk> + * Copyright (C) 2004 Simtec Electronics + * + * Thanks to basprog@mail.ru for updates to newer kernels + * + * This file is licenced under the GPL. +*/ + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/hardware/clock.h> +#include <asm/arch/usb-control.h> + +#define valid_port(idx) ((idx) == 1 || (idx) == 2) + +/* clock device associated with the hcd */ + +static struct clk *clk; + +/* forward definitions */ + +static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); + +/* conversion functions */ + +struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) +{ + return hcd->self.controller->platform_data; +} + +static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) +{ + struct s3c2410_hcd_info *info = dev->dev.platform_data; + + dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); + clk_enable(clk); + + if (info != NULL) { + info->hcd = hcd; + info->report_oc = s3c2410_hcd_oc; + + if (info->enable_oc != NULL) { + (info->enable_oc)(info, 1); + } + } +} + +static void s3c2410_stop_hc(struct platform_device *dev) +{ + struct s3c2410_hcd_info *info = dev->dev.platform_data; + + dev_dbg(&dev->dev, "s3c2410_stop_hc:\n"); + + if (info != NULL) { + info->report_oc = NULL; + info->hcd = NULL; + + if (info->enable_oc != NULL) { + (info->enable_oc)(info, 0); + } + } + + clk_disable(clk); +} + +/* ohci_s3c2410_hub_status_data + * + * update the status data from the hub with anything that + * has been detected by our system +*/ + +static int +ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf) +{ + struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); + struct s3c2410_hcd_port *port; + int orig; + int portno; + + orig = ohci_hub_status_data (hcd, buf); + + if (info == NULL) + return orig; + + port = &info->port[0]; + + /* mark any changed port as changed */ + + for (portno = 0; portno < 2; port++, portno++) { + if (port->oc_changed == 1 && + port->flags & S3C_HCDFLG_USED) { + dev_dbg(hcd->self.controller, + "oc change on port %d\n", portno); + + if (orig < 1) + orig = 1; + + buf[0] |= 1<<(portno+1); + } + } + + return orig; +} + +/* s3c2410_usb_set_power + * + * configure the power on a port, by calling the platform device + * routine registered with the platform device +*/ + +static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info, + int port, int to) +{ + if (info == NULL) + return; + + if (info->power_control != NULL) { + info->port[port-1].power = to; + (info->power_control)(port, to); + } +} + +/* ohci_s3c2410_hub_control + * + * look at control requests to the hub, and see if we need + * to take any action or over-ride the results from the + * request. +*/ + +static int ohci_s3c2410_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength) +{ + struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); + struct usb_hub_descriptor *desc; + int ret = -EINVAL; + u32 *data = (u32 *)buf; + + dev_dbg(hcd->self.controller, + "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", + hcd, typeReq, wValue, wIndex, buf, wLength); + + /* if we are only an humble host without any special capabilites + * process the request straight away and exit */ + + if (info == NULL) { + ret = ohci_hub_control(hcd, typeReq, wValue, + wIndex, buf, wLength); + goto out; + } + + /* check the request to see if it needs handling */ + + switch (typeReq) { + case SetPortFeature: + if (wValue == USB_PORT_FEAT_POWER) { + dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); + s3c2410_usb_set_power(info, wIndex, 1); + goto out; + } + break; + + case ClearPortFeature: + switch (wValue) { + case USB_PORT_FEAT_C_OVER_CURRENT: + dev_dbg(hcd->self.controller, + "ClearPortFeature: C_OVER_CURRENT\n"); + + if (valid_port(wIndex)) { + info->port[wIndex-1].oc_changed = 0; + info->port[wIndex-1].oc_status = 0; + } + + goto out; + + case USB_PORT_FEAT_OVER_CURRENT: + dev_dbg(hcd->self.controller, + "ClearPortFeature: OVER_CURRENT\n"); + + if (valid_port(wIndex)) { + info->port[wIndex-1].oc_status = 0; + } + + goto out; + + case USB_PORT_FEAT_POWER: + dev_dbg(hcd->self.controller, + "ClearPortFeature: POWER\n"); + + if (valid_port(wIndex)) { + s3c2410_usb_set_power(info, wIndex, 0); + return 0; + } + } + break; + } + + ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + if (ret) + goto out; + + switch (typeReq) { + case GetHubDescriptor: + + /* update the hub's descriptor */ + + desc = (struct usb_hub_descriptor *)buf; + + if (info->power_control == NULL) + return ret; + + dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n", + desc->wHubCharacteristics); + + /* remove the old configurations for power-switching, and + * over-current protection, and insert our new configuration + */ + + desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM); + desc->wHubCharacteristics |= cpu_to_le16(0x0001); + + if (info->enable_oc) { + desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); + desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001); + } + + dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", + desc->wHubCharacteristics); + + return ret; + + case GetPortStatus: + /* check port status */ + + dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); + + if (valid_port(wIndex)) { + if (info->port[wIndex-1].oc_changed) { + *data |= cpu_to_le32(RH_PS_OCIC); + } + + if (info->port[wIndex-1].oc_status) { + *data |= cpu_to_le32(RH_PS_POCI); + } + } + } + + out: + return ret; +} + +/* s3c2410_hcd_oc + * + * handle an over-current report +*/ + +static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) +{ + struct s3c2410_hcd_port *port; + struct usb_hcd *hcd; + unsigned long flags; + int portno; + + if (info == NULL) + return; + + port = &info->port[0]; + hcd = info->hcd; + + local_irq_save(flags); + + for (portno = 0; portno < 2; port++, portno++) { + if (port_oc & (1<<portno) && + port->flags & S3C_HCDFLG_USED) { + port->oc_status = 1; + port->oc_changed = 1; + + /* ok, once over-current is detected, + the port needs to be powered down */ + s3c2410_usb_set_power(info, portno+1, 0); + } + } + + local_irq_restore(flags); +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/* + * usb_hcd_s3c2410_remove - shutdown processing for HCD + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_3c2410_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * +*/ + +void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) +{ + usb_remove_hcd(hcd); + s3c2410_stop_hc(dev); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +/** + * usb_hcd_s3c2410_probe - initialize S3C2410-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ +int usb_hcd_s3c2410_probe (const struct hc_driver *driver, + struct platform_device *dev) +{ + struct usb_hcd *hcd = NULL; + int retval; + + s3c2410_usb_set_power(dev->dev.platform_data, 0, 1); + s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); + + hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); + if (hcd == NULL) + return -ENOMEM; + + hcd->rsrc_start = dev->resource[0].start; + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_err(&dev->dev, "request_mem_region failed"); + retval = -EBUSY; + goto err0; + } + + clk = clk_get(NULL, "usb-host"); + if (IS_ERR(clk)) { + dev_err(&dev->dev, "cannot get usb-host clock\n"); + retval = -ENOENT; + goto err1; + } + + clk_use(clk); + s3c2410_start_hc(dev, hcd); + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&dev->dev, "ioremap failed\n"); + retval = -ENOMEM; + goto err2; + } + + ohci_hcd_init(hcd_to_ohci(hcd)); + + retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); + if (retval != 0) + goto err2; + + return 0; + + err2: + s3c2410_stop_hc(dev); + iounmap(hcd->regs); + clk_unuse(clk); + clk_put(clk); + + err1: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + err0: + usb_put_hcd(hcd); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +static int +ohci_s3c2410_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if ((ret = ohci_init(ohci)) < 0) + return ret; + + if ((ret = ohci_run (ohci)) < 0) { + err ("can't start %s", hcd->self.bus_name); + ohci_stop (hcd); + return ret; + } + + return 0; +} + + +static const struct hc_driver ohci_s3c2410_hc_driver = { + .description = hcd_name, + .product_desc = "S3C24XX OHCI", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = ohci_s3c2410_start, + .stop = ohci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_s3c2410_hub_status_data, + .hub_control = ohci_s3c2410_hub_control, + +#if defined(CONFIG_USB_SUSPEND) && 0 + .hub_suspend = ohci_hub_suspend, + .hub_resume = ohci_hub_resume, +#endif +}; + +/* device driver */ + +static int ohci_hcd_s3c2410_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); +} + +static int ohci_hcd_s3c2410_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_hcd_s3c2410_remove(hcd, pdev); + return 0; +} + +static struct device_driver ohci_hcd_s3c2410_driver = { + .name = "s3c2410-ohci", + .bus = &platform_bus_type, + .probe = ohci_hcd_s3c2410_drv_probe, + .remove = ohci_hcd_s3c2410_drv_remove, + /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ + /*.resume = ohci_hcd_s3c2410_drv_resume, */ +}; + +static int __init ohci_hcd_s3c2410_init (void) +{ + return driver_register(&ohci_hcd_s3c2410_driver); +} + +static void __exit ohci_hcd_s3c2410_cleanup (void) +{ + driver_unregister(&ohci_hcd_s3c2410_driver); +} + +module_init (ohci_hcd_s3c2410_init); +module_exit (ohci_hcd_s3c2410_cleanup); diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index ebcf7c955800..13532f3e3efc 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -31,6 +31,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -87,8 +88,8 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) if (prox) { int x = data[1] | (data[2] << 8); int y = data[3] | (data[4] << 8); - /*Pressure should compute the same way for flair and 302*/ - int pressure = data[5] | ((int)data[6] << 8); + /* Pressure should compute the same way for flair and 302 */ + int pressure = data[5] | (data[6] << 8); int touch = data[0] & 0x01; int stylus = (data[0] & 0x10) >> 4; int stylus2 = (data[0] & 0x20) >> 5; @@ -104,9 +105,9 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) input_sync(dev); resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", + err("can't resubmit intr, %s-%s/input0, status %d", acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); } @@ -212,10 +213,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ acecad->dev.name = acecad->name; acecad->dev.phys = acecad->phys; - acecad->dev.id.bustype = BUS_USB; - acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &acecad->dev.id); acecad->dev.dev = &intf->dev; usb_fill_int_urb(acecad->irq, dev, pipe, diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index 6bb0f25e8e93..cd0cbfe20723 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -77,6 +77,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <linux/sched.h> #include <asm/uaccess.h> #include <asm/unaligned.h> @@ -2125,10 +2126,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) aiptek->inputdev.absflat[ABS_WHEEL] = 0; aiptek->inputdev.name = "Aiptek"; aiptek->inputdev.phys = aiptek->features.usbPath; - aiptek->inputdev.id.bustype = BUS_USB; - aiptek->inputdev.id.vendor = le16_to_cpu(usbdev->descriptor.idVendor); - aiptek->inputdev.id.product = le16_to_cpu(usbdev->descriptor.idProduct); - aiptek->inputdev.id.version = le16_to_cpu(usbdev->descriptor.bcdDevice); + usb_to_input_id(usbdev, &aiptek->inputdev.id); aiptek->inputdev.dev = &intf->dev; aiptek->usbdev = usbdev; diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 654ac454744d..fd99681ee483 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -94,6 +94,7 @@ #include <linux/moduleparam.h> #include <linux/input.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <linux/wait.h> /* @@ -635,11 +636,8 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) idev->name = ati_remote->name; idev->phys = ati_remote->phys; - idev->id.bustype = BUS_USB; - idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); - idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); - idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); - idev->dev = &(ati_remote->udev->dev); + usb_to_input_id(ati_remote->udev, &idev->id); + idev->dev = &ati_remote->udev->dev; } static int ati_remote_initialize(struct ati_remote *ati_remote) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2350e7a5ad70..b2cb2b35892e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -789,12 +789,12 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n) return -1; } -static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) +static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs) { hid_dump_input(usage, value); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_hid_event(hid, field, usage, value, regs); - if (hid->claimed & HID_CLAIMED_HIDDEV) + if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt) hiddev_hid_event(hid, field, usage, value, regs); } @@ -804,7 +804,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s * reporting to the layer). */ -static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, struct pt_regs *regs) +static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt, struct pt_regs *regs) { unsigned n; unsigned count = field->report_count; @@ -831,19 +831,19 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u for (n = 0; n < count; n++) { if (HID_MAIN_ITEM_VARIABLE & field->flags) { - hid_process_event(hid, field, &field->usage[n], value[n], regs); + hid_process_event(hid, field, &field->usage[n], value[n], interrupt, regs); continue; } if (field->value[n] >= min && field->value[n] <= max && field->usage[field->value[n] - min].hid && search(value, field->value[n], count)) - hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, regs); + hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs); if (value[n] >= min && value[n] <= max && field->usage[value[n] - min].hid && search(field->value, value[n], count)) - hid_process_event(hid, field, &field->usage[value[n] - min], 1, regs); + hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt, regs); } memcpy(field->value, value, count * sizeof(__s32)); @@ -851,7 +851,7 @@ exit: kfree(value); } -static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs) +static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_regs *regs) { struct hid_device *hid = urb->context; struct hid_report_enum *report_enum = hid->report_enum + type; @@ -899,7 +899,7 @@ static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs) hiddev_report_event(hid, report); for (n = 0; n < report->maxfield; n++) - hid_input_field(hid, report->field[n], data, regs); + hid_input_field(hid, report->field[n], data, interrupt, regs); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_report_event(hid, report); @@ -918,7 +918,7 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs) switch (urb->status) { case 0: /* success */ - hid_input_report(HID_INPUT_REPORT, urb, regs); + hid_input_report(HID_INPUT_REPORT, urb, 1, regs); break; case -ECONNRESET: /* unlink */ case -ENOENT: @@ -1142,7 +1142,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs) switch (urb->status) { case 0: /* success */ if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); + hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); case -ESHUTDOWN: /* unplug */ case -EILSEQ: /* unplug timectrl on uhci */ unplug = 1; @@ -1372,6 +1372,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_A4TECH 0x09da #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 +#define USB_VENDOR_ID_AASHIMA 0x06D6 +#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 + #define USB_VENDOR_ID_CYPRESS 0x04b4 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 @@ -1548,6 +1551,7 @@ static struct hid_blacklist { { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, + { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 9ac1e9095334..63a4db721f7e 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/input.h> #include <linux/usb.h> +#include <linux/usb_input.h> #undef DEBUG @@ -397,11 +398,12 @@ ignore: void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) { - struct input_dev *input = &field->hidinput->input; + struct input_dev *input; int *quirks = &hid->quirks; - if (!input) + if (!field->hidinput) return; + input = &field->hidinput->input; input_regs(input, regs); @@ -581,10 +583,7 @@ int hidinput_connect(struct hid_device *hid) hidinput->input.name = hid->name; hidinput->input.phys = hid->phys; hidinput->input.uniq = hid->uniq; - hidinput->input.id.bustype = BUS_USB; - hidinput->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct); - hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &hidinput->input.id); hidinput->input.dev = &hid->intf->dev; } diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 47dec6a1b344..0dc439f10823 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* only an 8 byte buffer necessary for a single packet */ #define ITM_BUFSIZE 8 @@ -184,10 +185,7 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id itmtouch->inputdev.name = itmtouch->name; itmtouch->inputdev.phys = itmtouch->phys; - itmtouch->inputdev.id.bustype = BUS_USB; - itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; - itmtouch->inputdev.id.product = udev->descriptor.idProduct; - itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; + usb_to_input_id(udev, &itmtouch->inputdev.id); itmtouch->inputdev.dev = &intf->dev; if (!strlen(itmtouch->name)) diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index d2f0f90a9bcd..b6f6ac8d9c2f 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -4,6 +4,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <asm/unaligned.h> #include <asm/byteorder.h> @@ -167,10 +168,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i kbtab->dev.name = "KB Gear Tablet"; kbtab->dev.phys = kbtab->phys; - kbtab->dev.id.bustype = BUS_USB; - kbtab->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - kbtab->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - kbtab->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &kbtab->dev.id); kbtab->dev.dev = &intf->dev; kbtab->usbdev = dev; diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index 09b5cc7c66de..ff9275057a18 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define MTOUCHUSB_MIN_XC 0x0 #define MTOUCHUSB_MAX_RAW_XC 0x4000 @@ -232,10 +233,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i mtouch->input.name = mtouch->name; mtouch->input.phys = mtouch->phys; - mtouch->input.id.bustype = BUS_USB; - mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &mtouch->input.id); mtouch->input.dev = &intf->dev; mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 3975b309d55f..ad4afe7e5897 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -35,6 +35,7 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ @@ -389,10 +390,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0); pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); - pm->input.id.bustype = BUS_USB; - pm->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - pm->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &pm->input.id); pm->input.event = powermate_input_event; pm->input.dev = &intf->dev; pm->input.phys = pm->phys; diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 386595ee21c0..4276c24a5080 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -35,7 +35,7 @@ #define DEBUG #endif #include <linux/usb.h> - +#include <linux/usb_input.h> #define TOUCHKIT_MIN_XC 0x0 #define TOUCHKIT_MAX_XC 0x07ff @@ -202,10 +202,7 @@ static int touchkit_probe(struct usb_interface *intf, touchkit->input.name = touchkit->name; touchkit->input.phys = touchkit->phys; - touchkit->input.id.bustype = BUS_USB; - touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &touchkit->input.id); touchkit->input.dev = &intf->dev; touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index f35db1974c42..28987f15eeee 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -32,6 +32,7 @@ #include <linux/input.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -288,10 +289,7 @@ static int usb_kbd_probe(struct usb_interface *iface, kbd->dev.name = kbd->name; kbd->dev.phys = kbd->phys; - kbd->dev.id.bustype = BUS_USB; - kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &kbd->dev.id); kbd->dev.dev = &iface->dev; if (dev->manufacturer) diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 1ec41b5effe6..4104dec847fb 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -171,10 +172,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ mouse->dev.name = mouse->name; mouse->dev.phys = mouse->phys; - mouse->dev.id.bustype = BUS_USB; - mouse->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - mouse->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &mouse->dev.id); mouse->dev.dev = &intf->dev; if (dev->manufacturer) diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index f6b34af66b3d..02412e31a46b 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -69,6 +69,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <asm/unaligned.h> #include <asm/byteorder.h> @@ -823,10 +824,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->dev.name = wacom->features->name; wacom->dev.phys = wacom->phys; - wacom->dev.id.bustype = BUS_USB; - wacom->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - wacom->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - wacom->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &wacom->dev.id); wacom->dev.dev = &intf->dev; wacom->usbdev = dev; diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index a7fa1b17dcfe..18125e0bffa2 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -62,6 +62,7 @@ #include <linux/module.h> #include <linux/smp_lock.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define DRIVER_VERSION "v0.0.5" #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" @@ -256,10 +257,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->udev = udev; - xpad->dev.id.bustype = BUS_USB; - xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); - xpad->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &xpad->dev.id); xpad->dev.dev = &intf->dev; xpad->dev.private = xpad; xpad->dev.name = xpad_device[i].name; diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c index 08521a2b4f3d..20ac9e1069d4 100644 --- a/drivers/usb/media/konicawc.c +++ b/drivers/usb/media/konicawc.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/usb_input.h> #include "usbvideo.h" @@ -845,10 +846,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id cam->input.private = cam; cam->input.evbit[0] = BIT(EV_KEY); cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0); - cam->input.id.bustype = BUS_USB; - cam->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - cam->input.id.product = le16_to_cpu(dev->descriptor.idProduct); - cam->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &cam->input.id); input_register_device(&cam->input); usb_make_path(dev, cam->input_physname, 56); diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 66ec88354b93..ad17892aac9e 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -23,6 +23,7 @@ * * V0.1 (mh) Initial version * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint) + * V0.12 (mh) Added kmalloc check for string buffer */ #include <linux/config.h> @@ -84,7 +85,7 @@ static struct usb_device_id ld_usb_table [] = { { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); -MODULE_VERSION("V0.11"); +MODULE_VERSION("V0.12"); MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>"); MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); @@ -635,6 +636,10 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) && (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) { buffer = kmalloc(256, GFP_KERNEL); + if (buffer == NULL) { + dev_err(&intf->dev, "Couldn't allocate string buffer\n"); + goto error; + } /* usb_string makes SETUP+STALL to leave always ControlReadLoop */ usb_string(udev, 255, buffer, 256); kfree(buffer); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 5f4496d8dbac..fcd6d3ccef44 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -59,7 +59,6 @@ static const char driver_name[] = "pegasus"; static int loopback = 0; static int mii_mode = 0; -static int multicast_filter_limit = 32; static struct usb_eth_dev usb_dev_id[] = { #define PEGASUS_DEV(pn, vid, pid, flags) \ diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 626b016addff..59ab40ebb394 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -167,8 +167,6 @@ struct rtl8150 { typedef struct rtl8150 rtl8150_t; -static unsigned long multicast_filter_limit = 32; - static void fill_skb_pool(rtl8150_t *); static void free_skb_pool(rtl8150_t *); static inline struct sk_buff *pull_skb(rtl8150_t *); diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index 3b387b005739..29cd801eb958 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -29,6 +29,7 @@ static struct usb_device_id zd1201_table[] = { {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ {} }; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0b03ddab53d9..d1964a0c4168 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -429,6 +429,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { } /* Terminating entry */ }; @@ -545,6 +548,7 @@ static struct usb_serial_device_type ftdi_sio_device = { #define WDR_TIMEOUT 5000 /* default urb timeout */ +#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ /* High and low are for DTR, RTS etc etc */ #define HIGH 1 @@ -593,62 +597,59 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud) return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); } -static int set_rts(struct usb_serial_port *port, int high_or_low) +#define set_mctrl(port, set) update_mctrl((port), (set), 0) +#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) + +static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); char *buf; - unsigned ftdi_high_or_low; + unsigned urb_value; int rv; - - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - - if (high_or_low) { - ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH; - priv->last_dtr_rts |= TIOCM_RTS; - } else { - ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW; - priv->last_dtr_rts &= ~TIOCM_RTS; - } - rv = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, priv->interface, - buf, 0, WDR_TIMEOUT); - - kfree(buf); - return rv; -} + if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { + dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__); + return 0; /* no change */ + } -static int set_dtr(struct usb_serial_port *port, int high_or_low) -{ - struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; - unsigned ftdi_high_or_low; - int rv; - buf = kmalloc(1, GFP_NOIO); - if (!buf) + if (!buf) { return -ENOMEM; - - if (high_or_low) { - ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH; - priv->last_dtr_rts |= TIOCM_DTR; - } else { - ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW; - priv->last_dtr_rts &= ~TIOCM_DTR; } + + clear &= ~set; /* 'set' takes precedence over 'clear' */ + urb_value = 0; + if (clear & TIOCM_DTR) + urb_value |= FTDI_SIO_SET_DTR_LOW; + if (clear & TIOCM_RTS) + urb_value |= FTDI_SIO_SET_RTS_LOW; + if (set & TIOCM_DTR) + urb_value |= FTDI_SIO_SET_DTR_HIGH; + if (set & TIOCM_RTS) + urb_value |= FTDI_SIO_SET_RTS_HIGH; rv = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, priv->interface, + urb_value, priv->interface, buf, 0, WDR_TIMEOUT); kfree(buf); + if (rv < 0) { + err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", + __FUNCTION__, + (set & TIOCM_DTR) ? "HIGH" : + (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : + (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + } else { + dbg("%s - DTR %s, RTS %s", __FUNCTION__, + (set & TIOCM_DTR) ? "HIGH" : + (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : + (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; + } return rv; } @@ -681,7 +682,7 @@ static int change_speed(struct usb_serial_port *port) FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, urb_value, urb_index, - buf, 0, 100); + buf, 0, WDR_SHORT_TIMEOUT); kfree(buf); return rv; @@ -1219,12 +1220,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ /* Turn on RTS and DTR since we are not flow controlling by default */ - if (set_dtr(port, HIGH) < 0) { - err("%s Error from DTR HIGH urb", __FUNCTION__); - } - if (set_rts(port, HIGH) < 0){ - err("%s Error from RTS HIGH urb", __FUNCTION__); - } + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); /* Not throttled */ spin_lock_irqsave(&priv->rx_lock, flags); @@ -1274,14 +1270,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) err("error from flowcontrol urb"); } - /* drop DTR */ - if (set_dtr(port, LOW) < 0){ - err("Error from DTR LOW urb"); - } - /* drop RTS */ - if (set_rts(port, LOW) < 0) { - err("Error from RTS LOW urb"); - } + /* drop RTS and DTR */ + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* Note change no line if hupcl is off */ /* cancel any scheduled reading */ @@ -1797,7 +1787,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, 100) < 0) { + buf, 0, WDR_SHORT_TIMEOUT) < 0) { err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); } @@ -1812,25 +1802,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ err("%s error from disable flowcontrol urb", __FUNCTION__); } /* Drop RTS and DTR */ - if (set_dtr(port, LOW) < 0){ - err("%s Error from DTR LOW urb", __FUNCTION__); - } - if (set_rts(port, LOW) < 0){ - err("%s Error from RTS LOW urb", __FUNCTION__); - } - + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* set the baudrate determined before */ if (change_speed(port)) { err("%s urb failed to set baurdrate", __FUNCTION__); } /* Ensure RTS and DTR are raised */ - else if (set_dtr(port, HIGH) < 0){ - err("%s Error from DTR HIGH urb", __FUNCTION__); - } - else if (set_rts(port, HIGH) < 0){ - err("%s Error from RTS HIGH urb", __FUNCTION__); - } + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* Set flow control */ @@ -1942,35 +1921,8 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) { - int ret; - dbg("%s TIOCMSET", __FUNCTION__); - if (set & TIOCM_DTR){ - if ((ret = set_dtr(port, HIGH)) < 0) { - err("Urb to set DTR failed"); - return(ret); - } - } - if (set & TIOCM_RTS) { - if ((ret = set_rts(port, HIGH)) < 0){ - err("Urb to set RTS failed"); - return(ret); - } - } - - if (clear & TIOCM_DTR){ - if ((ret = set_dtr(port, LOW)) < 0){ - err("Urb to unset DTR failed"); - return(ret); - } - } - if (clear & TIOCM_RTS) { - if ((ret = set_rts(port, LOW)) < 0){ - err("Urb to unset RTS failed"); - return(ret); - } - } - return(0); + return update_mctrl(port, set, clear); } diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 8866376823a5..9f4342093e8b 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -265,10 +265,24 @@ #define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ /* + * microHAM product IDs (http://www.microham.com). + * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>. + */ +#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ +#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ + +/* * Active Robots product ids. */ #define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ +/* + * Evolution Robotics products (http://www.evolution.com/). + * Submitted by Shawn M. Lavelle. + */ +#define EVOLUTION_VID 0xDEEE /* Vendor ID */ +#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ + /* 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/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 6051a646fe69..353f24d45bc1 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -257,7 +257,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i endpoint = &iface_desc->endpoint[i].desc; if (!dev->bulk_in_endpointAddr && - (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ @@ -272,7 +273,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i } if (!dev->bulk_out_endpointAddr && - !(endpoint->bEndpointAddress & USB_DIR_OUT) && + ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk out endpoint */ diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 40784a944d05..d2e19f6dd72c 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -80,10 +80,12 @@ EXPORT_SYMBOL(fb_get_color_depth); */ void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) { - int i; + int i, j; for (i = height; i--; ) { - memcpy(dst, src, s_pitch); + /* s_pitch is a few bytes at the most, memcpy is suboptimal */ + for (j = 0; j < s_pitch; j++) + dst[j] = src[j]; src += s_pitch; dst += d_pitch; } diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 63b505cce4ec..1147b899f007 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -244,15 +244,15 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf) /* Format for cmap is "%02x%c%4x%4x%4x\n" */ /* %02x entry %c transp %4x red %4x blue %4x green \n */ -/* 255 rows at 16 chars equals 4096 */ -/* PAGE_SIZE can be 4096 or larger */ +/* 256 rows at 16 chars equals 4096, the normal page size */ +/* the code will automatically adjust for different page sizes */ static ssize_t store_cmap(struct class_device *class_device, const char *buf, size_t count) { struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); int rc, i, start, length, transp = 0; - if ((count > 4096) || ((count % 16) != 0) || (PAGE_SIZE < 4096)) + if ((count > PAGE_SIZE) || ((count % 16) != 0)) return -EINVAL; if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap) @@ -317,18 +317,18 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf) !fb_info->cmap.green) return -EINVAL; - if (PAGE_SIZE < 4096) + if (fb_info->cmap.len > PAGE_SIZE / 16) return -EINVAL; /* don't mess with the format, the buffer is PAGE_SIZE */ - /* 255 entries at 16 chars per line equals 4096 = PAGE_SIZE */ + /* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */ for (i = 0; i < fb_info->cmap.len; i++) { - sprintf(&buf[ i * 16], "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start, + snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start, ((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '), fb_info->cmap.red[i], fb_info->cmap.blue[i], fb_info->cmap.green[i]); } - return 4096; + return 16 * fb_info->cmap.len; } static ssize_t store_blank(struct class_device *class_device, const char * buf, @@ -414,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf) fb_info->var.xoffset); } +static ssize_t show_name(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); +} + static struct class_device_attribute class_device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), @@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), + __ATTR(name, S_IRUGO, show_name, NULL), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index da8004e5d03d..698ca9232e73 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -454,13 +454,16 @@ static struct accel_switch accel_image = { static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr) { int bpp = info->var.bits_per_pixel; - int col; + int col = 0; switch (bpp) { default: - case 8: col = fr->color; + case 8: col |= fr->color; + col |= col << 8; + col |= col << 16; break; case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; + break; case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; break; @@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(GraphEngReg, 0x80); //enable GE for text acceleration -// if (info->var.accel_flags & FB_ACCELF_TEXT) -//FIXME acc->init_accel(info->var.xres,bpp); +#ifdef CONFIG_FB_TRIDENT_ACCEL + acc->init_accel(info->var.xres,bpp); +#endif switch (bpp) { case 8: tmp = 0x00; break; @@ -900,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(DRAMControl, tmp); //both IO,linear enable write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); - write3X4(Performance,0x20); + write3X4(Performance,0x92); write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable /* convert from picoseconds to MHz */ @@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, t_outb(green>>10,0x3C9); t_outb(blue>>10,0x3C9); - } else - if (bpp == 16) /* RGB 565 */ - ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) | - ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); - else - if (bpp == 32) /* ARGB 8888 */ + } else if (bpp == 16) { /* RGB 565 */ + u32 col; + + col = (red & 0xF800) | ((green & 0xFC00) >> 5) | + ((blue & 0xF800) >> 11); + col |= col << 16; + ((u32 *)(info->pseudo_palette))[regno] = col; + } else if (bpp == 32) /* ARGB 8888 */ ((u32*)info->pseudo_palette)[regno] = ((transp & 0xFF00) <<16) | ((red & 0xFF00) << 8) | diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 9ed1a931dd31..a272592b0373 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -45,7 +45,7 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { }; static int inverse = 0; -static int mtrr = 1; +static int mtrr = 3; /* default to write-combining */ static int vram_remap __initdata = 0; /* Set amount of memory to be used */ static int vram_total __initdata = 0; /* Set total amount of memory */ static int pmi_setpal = 0; /* pmi for palette changes ??? */ @@ -204,8 +204,8 @@ static int __init vesafb_setup(char *options) pmi_setpal=0; else if (! strcmp(this_opt, "pmipal")) pmi_setpal=1; - else if (! strcmp(this_opt, "mtrr")) - mtrr=1; + else if (! strncmp(this_opt, "mtrr:", 5)) + mtrr = simple_strtoul(this_opt+5, NULL, 0); else if (! strcmp(this_opt, "nomtrr")) mtrr=0; else if (! strncmp(this_opt, "vtotal:", 7)) @@ -387,14 +387,39 @@ static int __init vesafb_probe(struct device *device) if (mtrr) { unsigned int temp_size = size_total; - /* Find the largest power-of-two */ - while (temp_size & (temp_size - 1)) - temp_size &= (temp_size - 1); - - /* Try and find a power of two to add */ - while (temp_size > PAGE_SIZE && - mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) { - temp_size >>= 1; + unsigned int type = 0; + + switch (mtrr) { + case 1: + type = MTRR_TYPE_UNCACHABLE; + break; + case 2: + type = MTRR_TYPE_WRBACK; + break; + case 3: + type = MTRR_TYPE_WRCOMB; + break; + case 4: + type = MTRR_TYPE_WRTHROUGH; + break; + default: + type = 0; + break; + } + + if (type) { + int rc; + + /* Find the largest power-of-two */ + while (temp_size & (temp_size - 1)) + temp_size &= (temp_size - 1); + + /* Try and find a power of two to add */ + do { + rc = mtrr_add(vesafb_fix.smem_start, temp_size, + type, 1); + temp_size >>= 1; + } while (temp_size >= PAGE_SIZE && rc == -EINVAL); } } diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 4f120796273e..711b90903e7b 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -30,7 +30,7 @@ config W1_DS9490 This support is also available as a module. If so, the module will be called ds9490r.ko. -config W1_DS9490R_BRIDGE +config W1_DS9490_BRIDGE tristate "DS9490R USB <-> W1 transport layer for 1-wire" depends on W1_DS9490 help diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 6ad1211f84ed..a096c5a56664 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -480,6 +480,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index cbc8510ad222..5ea6b3d45eaa 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -482,7 +482,8 @@ void hfs_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFS_I(inode)->phys_size) + return; size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1; blk_cnt = size / HFS_SB(sb)->alloc_blksz; alloc_cnt = HFS_I(inode)->alloc_blocks; diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 267872e84d71..8868d3b766fd 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -643,6 +643,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 376498cc64fd..e7235ca79a95 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -461,7 +461,9 @@ void hfsplus_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFSPLUS_I(inode).phys_size) + return; + blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; alloc_cnt = HFSPLUS_I(inode).alloc_blocks; if (blk_cnt == alloc_cnt) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index c1516d013bf6..67bca0d4a33b 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -69,6 +69,7 @@ extern int read_file(int fd, unsigned long long *offset, char *buf, int len); extern int write_file(int fd, unsigned long long *offset, const char *buf, int len); extern int lseek_file(int fd, long long offset, int whence); +extern int fsync_file(int fd, int datasync); extern int file_create(char *name, int ur, int uw, int ux, int gr, int gw, int gx, int or, int ow, int ox); extern int set_attr(const char *file, struct hostfs_iattr *attrs); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 88e68caa3784..b2d18200a003 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -382,7 +382,7 @@ int hostfs_file_open(struct inode *ino, struct file *file) int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) { - return(0); + return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); } static struct file_operations hostfs_file_fops = { diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 4796e8490f7d..b97809deba66 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -153,10 +153,24 @@ int lseek_file(int fd, long long offset, int whence) int ret; ret = lseek64(fd, offset, whence); - if(ret < 0) return(-errno); + if(ret < 0) + return(-errno); return(0); } +int fsync_file(int fd, int datasync) +{ + int ret; + if (datasync) + ret = fdatasync(fd); + else + ret = fsync(fd); + + if (ret < 0) + return -errno; + return 0; +} + void close_file(void *stream) { close(*((int *) stream)); diff --git a/fs/inotify.c b/fs/inotify.c index a8a714e48140..27ebcac5e07f 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -90,6 +90,7 @@ struct inotify_device { unsigned int queue_size; /* size of the queue (bytes) */ unsigned int event_count; /* number of pending events */ unsigned int max_events; /* maximum number of events */ + u32 last_wd; /* the last wd allocated */ }; /* @@ -352,7 +353,7 @@ static int inotify_dev_get_wd(struct inotify_device *dev, do { if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL))) return -ENOSPC; - ret = idr_get_new(&dev->idr, watch, &watch->wd); + ret = idr_get_new_above(&dev->idr, watch, dev->last_wd, &watch->wd); } while (ret == -EAGAIN); return ret; @@ -401,6 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, return ERR_PTR(ret); } + dev->last_wd = ret; watch->mask = mask; atomic_set(&watch->count, 0); INIT_LIST_HEAD(&watch->d_list); @@ -899,6 +901,7 @@ asmlinkage long sys_inotify_init(void) dev->queue_size = 0; dev->max_events = inotify_max_queued_events; dev->user = user; + dev->last_wd = 0; atomic_set(&dev->count, 0); get_inotify_dev(dev); diff --git a/fs/namei.c b/fs/namei.c index 02a824cd3c5c..4a27eb798118 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2218,7 +2218,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); if (!error) { const char *new_name = old_dentry->d_name.name; - fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir); + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); } fsnotify_oldname_free(old_name); diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 335288b9be0f..4013d7905e84 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -437,8 +437,8 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct dentry *dir = kobj->dentry; struct dentry *victim; - struct sysfs_dirent *sd; - umode_t umode = (mode & S_IALLUGO) | S_IFREG; + struct inode * inode; + struct iattr newattrs; int res = -ENOENT; down(&dir->d_inode->i_sem); @@ -446,13 +446,15 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) if (!IS_ERR(victim)) { if (victim->d_inode && (victim->d_parent->d_inode == dir->d_inode)) { - sd = victim->d_fsdata; - attr->mode = mode; - sd->s_mode = umode; - victim->d_inode->i_mode = umode; - dput(victim); - res = 0; + inode = victim->d_inode; + down(&inode->i_sem); + newattrs.ia_mode = (mode & S_IALLUGO) | + (inode->i_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; + res = notify_change(victim, &newattrs); + up(&inode->i_sem); } + dput(victim); } up(&dir->d_inode->i_sem); diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 8de13bafaa76..d727dc960634 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -85,7 +85,7 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; - sd_iattr->ia_mode = mode; + sd_iattr->ia_mode = sd->s_mode = mode; } return error; diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index caeaa71a5663..579fe191b7e7 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -56,8 +56,9 @@ /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_irq_penalty_init (void); -int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, +int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level, int *active_high_low, char **name); +int acpi_pci_link_free_irq(acpi_handle handle); /* ACPI PCI Interrupt Routing (pci_irq.c) */ diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h index c1adc6b3e86d..aad7aad026b3 100644 --- a/include/asm-arm/bitops.h +++ b/include/asm-arm/bitops.h @@ -229,6 +229,7 @@ extern int _find_next_zero_bit_be(const void * p, int size, int offset); extern int _find_first_bit_be(const unsigned long *p, unsigned size); extern int _find_next_bit_be(const unsigned long *p, int size, int offset); +#ifndef CONFIG_SMP /* * The __* form of bitops are non-atomic and may be reordered. */ @@ -241,6 +242,10 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); (__builtin_constant_p(nr) ? \ ____atomic_##name(nr, p) : \ _##name##_be(nr,p)) +#else +#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p) +#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p) +#endif #define NONATOMIC_BITOP(name,nr,p) \ (____nonatomic_##name(nr, p)) diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 195ccdc069e6..450eae22c39a 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -11,5 +11,6 @@ extern char _sinittext[], _einittext[]; extern char _sextratext[] __attribute__((weak)); extern char _eextratext[] __attribute__((weak)); extern char _end[]; +extern char __per_cpu_start[], __per_cpu_end[]; #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h index 1caee1039363..ddf1739dc7fd 100644 --- a/include/asm-i386/bitops.h +++ b/include/asm-i386/bitops.h @@ -335,14 +335,13 @@ static inline unsigned long __ffs(unsigned long word) static inline int find_first_bit(const unsigned long *addr, unsigned size) { int x = 0; - do { - if (*addr) - return __ffs(*addr) + x; - addr++; - if (x >= size) - break; + + while (x < size) { + unsigned long val = *addr++; + if (val) + return __ffs(val) + x; x += (sizeof(*addr)<<3); - } while (1); + } return x; } diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 78c85985aee3..2cbab30734d6 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -18,11 +18,9 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_scan_all_fns(a, b) 0 extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_IO 0x4000 #define PCIBIOS_MIN_MEM (pci_mem_start) -#define PCIBIOS_MIN_CARDBUS_IO 0x4000 - void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h index edad9b4712fa..a283738b80b3 100644 --- a/include/asm-i386/smp.h +++ b/include/asm-i386/smp.h @@ -37,9 +37,6 @@ extern int smp_num_siblings; extern cpumask_t cpu_sibling_map[]; extern cpumask_t cpu_core_map[]; -extern void smp_flush_tlb(void); -extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs); -extern void smp_invalidate_rcv(void); /* Process an NMI */ extern void (*mtrr_hook) (void); extern void zap_low_mappings (void); extern void lock_ipi_call_lock(void); diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 87f051138b9d..21e41c9b7267 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -35,8 +35,10 @@ #define PPC44x_LOW_SLOT 63 /* LS 32-bits of UART0 physical address location for early serial text debug */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define UART0_PHYS_IO_BASE 0xf0000200 +#elif defined(CONFIG_440EP) +#define UART0_PHYS_IO_BASE 0xe0000000 #else #define UART0_PHYS_IO_BASE 0x40000200 #endif @@ -49,11 +51,16 @@ /* * Standard 4GB "page" definitions */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define PPC44x_IO_PAGE 0x0000000100000000ULL #define PPC44x_PCICFG_PAGE 0x0000000900000000ULL #define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE #define PPC44x_PCIMEM_PAGE 0x0000000a00000000ULL +#elif defined(CONFIG_440EP) +#define PPC44x_IO_PAGE 0x0000000000000000ULL +#define PPC44x_PCICFG_PAGE 0x0000000000000000ULL +#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE +#define PPC44x_PCIMEM_PAGE 0x0000000000000000ULL #else #define PPC44x_IO_PAGE 0x0000000100000000ULL #define PPC44x_PCICFG_PAGE 0x0000000200000000ULL @@ -64,7 +71,7 @@ /* * 36-bit trap ranges */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define PPC44x_IO_LO 0xf0000000UL #define PPC44x_IO_HI 0xf0000fffUL #define PPC44x_PCI0CFG_LO 0x0ec00000UL @@ -75,6 +82,13 @@ #define PPC44x_PCI2CFG_HI 0x2ec00007UL #define PPC44x_PCIMEM_LO 0x80000000UL #define PPC44x_PCIMEM_HI 0xdfffffffUL +#elif defined(CONFIG_440EP) +#define PPC44x_IO_LO 0xef500000UL +#define PPC44x_IO_HI 0xefffffffUL +#define PPC44x_PCI0CFG_LO 0xeec00000UL +#define PPC44x_PCI0CFG_HI 0xeecfffffUL +#define PPC44x_PCIMEM_LO 0xa0000000UL +#define PPC44x_PCIMEM_HI 0xdfffffffUL #else #define PPC44x_IO_LO 0x40000000UL #define PPC44x_IO_HI 0x40000fffUL @@ -152,6 +166,12 @@ #define DCRN_SDR_UART0 0x0120 #define DCRN_SDR_UART1 0x0121 +#ifdef CONFIG_440EP +#define DCRN_SDR_UART2 0x0122 +#define DCRN_SDR_UART3 0x0123 +#define DCRN_SDR_CUST0 0x4000 +#endif + /* SDR read/write helper macros */ #define SDR_READ(offset) ({\ mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ @@ -169,6 +189,14 @@ #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ #define DCRN_MAL_BASE 0x180 +#ifdef CONFIG_440EP +#define DCRN_DMA2P40_BASE 0x300 +#define DCRN_DMA2P41_BASE 0x308 +#define DCRN_DMA2P42_BASE 0x310 +#define DCRN_DMA2P43_BASE 0x318 +#define DCRN_DMA2P4SR_BASE 0x320 +#endif + /* UIC */ #define DCRN_UIC0_BASE 0xc0 #define DCRN_UIC1_BASE 0xd0 diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 35260afa33a9..e807be96e981 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, #elif CONFIG_44x +#if defined(CONFIG_BAMBOO) +#include <platforms/4xx/bamboo.h> +#endif + #if defined(CONFIG_EBONY) #include <platforms/4xx/ebony.h> #endif diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h index 8c61d93043af..3f7b5669e6d5 100644 --- a/include/asm-ppc/ibm_ocp.h +++ b/include/asm-ppc/ibm_ocp.h @@ -71,6 +71,8 @@ struct ocp_func_emac_data { /* Sysfs support */ #define OCP_SYSFS_EMAC_DATA() \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_mux) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_idx) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_mux) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_idx) \ @@ -78,9 +80,14 @@ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_rx_chan) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_tx_chan) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, wol_irq) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, tah_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, phy_mode) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_map) \ \ void ocp_show_emac_data(struct device *dev) \ { \ + device_create_file(dev, &dev_attr_emac_rgmii_idx); \ + device_create_file(dev, &dev_attr_emac_rgmii_mux); \ device_create_file(dev, &dev_attr_emac_zmii_idx); \ device_create_file(dev, &dev_attr_emac_zmii_mux); \ device_create_file(dev, &dev_attr_emac_mal_idx); \ @@ -88,6 +95,9 @@ void ocp_show_emac_data(struct device *dev) \ device_create_file(dev, &dev_attr_emac_mal_tx_chan); \ device_create_file(dev, &dev_attr_emac_wol_irq); \ device_create_file(dev, &dev_attr_emac_mdio_idx); \ + device_create_file(dev, &dev_attr_emac_tah_idx); \ + device_create_file(dev, &dev_attr_emac_phy_mode); \ + device_create_file(dev, &dev_attr_emac_phy_map); \ } #ifdef CONFIG_40x @@ -157,7 +167,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_iic_data, "%d\n", iic, fast_mode) \ \ void ocp_show_iic_data(struct device *dev) \ { \ - device_create_file(dev, &dev_attr_iic_fast_mode); \ + device_create_file(dev, &dev_attr_iic_fast_mode); \ } #endif /* __IBM_OCP_H__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h index f76221def484..bb53e2def363 100644 --- a/include/asm-ppc/ppc_asm.h +++ b/include/asm-ppc/ppc_asm.h @@ -186,6 +186,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #define PPC405_ERR77_SYNC #endif +#ifdef CONFIG_IBM440EP_ERR42 +#define PPC440EP_ERR42 isync +#else +#define PPC440EP_ERR42 +#endif + /* The boring bits... */ /* Condition Register Bit Fields */ diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index a7894e0fbbb1..3173ab3d2eb9 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h @@ -279,8 +279,11 @@ #define __NR_waitid 272 #define __NR_ioprio_set 273 #define __NR_ioprio_get 274 +#define __NR_inotify_init 275 +#define __NR_inotify_add_watch 276 +#define __NR_inotify_rm_watch 277 -#define __NR_syscalls 275 +#define __NR_syscalls 278 #define __NR(n) #n diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h index fcdcfd26a26b..1e9b19073230 100644 --- a/include/asm-ppc64/topology.h +++ b/include/asm-ppc64/topology.h @@ -33,6 +33,7 @@ static inline int node_to_first_cpu(int node) return first_cpu(tmp); } +#define pcibus_to_node(node) (-1) #define pcibus_to_cpumask(bus) (cpu_online_map) #define nr_cpus_node(node) (nr_cpus_in_node[node]) @@ -59,8 +60,10 @@ static inline int node_to_first_cpu(int node) .nr_balance_failed = 0, \ } -#endif /* CONFIG_NUMA */ +#else #include <asm-generic/topology.h> +#endif /* CONFIG_NUMA */ + #endif /* _ASM_PPC64_TOPOLOGY_H */ diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index 4a94acf6bfed..977bc980c1af 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -285,8 +285,11 @@ #define __NR_waitid 272 #define __NR_ioprio_set 273 #define __NR_ioprio_get 274 +#define __NR_inotify_init 275 +#define __NR_inotify_add_watch 276 +#define __NR_inotify_rm_watch 277 -#define __NR_syscalls 275 +#define __NR_syscalls 278 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index 363db45f8d07..221e965da924 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -274,8 +274,13 @@ #define __NR_request_key 279 #define __NR_keyctl 280 #define __NR_waitid 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 -#define NR_syscalls 282 +#define NR_syscalls 287 /* * There are some system calls that are not present on 64 bit, some diff --git a/include/asm-um/vm86.h b/include/asm-um/vm86.h new file mode 100644 index 000000000000..7801f82de1f4 --- /dev/null +++ b/include/asm-um/vm86.h @@ -0,0 +1,6 @@ +#ifndef __UM_VM86_H +#define __UM_VM86_H + +#include "asm/arch/vm86.h" + +#endif diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h index a31bb99be53f..05a0d374404b 100644 --- a/include/asm-x86_64/bitops.h +++ b/include/asm-x86_64/bitops.h @@ -348,8 +348,7 @@ static inline int sched_find_first_bit(const unsigned long *b) return __ffs(b[0]); if (b[1]) return __ffs(b[1]) + 64; - if (b[2]) - return __ffs(b[2]) + 128; + return __ffs(b[2]) + 128; } /** diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h index 3d2a666a5dd5..eed785667289 100644 --- a/include/asm-x86_64/bug.h +++ b/include/asm-x86_64/bug.h @@ -8,17 +8,24 @@ * this frame. */ struct bug_frame { - unsigned char ud2[2]; + unsigned char ud2[2]; + unsigned char mov; /* should use 32bit offset instead, but the assembler doesn't like it */ char *filename; + unsigned char ret; unsigned short line; } __attribute__((packed)); #ifdef CONFIG_BUG #define HAVE_ARCH_BUG -#define BUG() \ - asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \ +/* We turn the bug frame into valid instructions to not confuse + the disassembler. Thanks to Jan Beulich & Suresh Siddha + for nice instruction selection. + The magic numbers generate mov $64bitimm,%eax ; ret $offset. */ +#define BUG() \ + asm volatile( \ + "ud2 ; .byte 0xa3 ; .quad %c1 ; .byte 0xc2 ; .short %c0" :: \ "i"(__LINE__), "i" (__stringify(__FILE__))) void out_of_line_bug(void); #else diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 6aefb9c0280d..c89b58bebee2 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h @@ -75,6 +75,7 @@ struct desc_ptr { */ extern struct desc_struct default_ldt[]; extern struct gate_struct idt_table[]; +extern struct desc_ptr cpu_gdt_descr[]; static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist) { diff --git a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h index d1841847ed89..5e166b9d3bde 100644 --- a/include/asm-x86_64/ipi.h +++ b/include/asm-x86_64/ipi.h @@ -82,30 +82,27 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) */ local_irq_save(flags); - for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) { - if (cpu_isset(query_cpu, mask)) { - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - /* - * prepare target chip field - */ - cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]); - apic_write_around(APIC_ICR2, cfg); - - /* - * program the ICR - */ - cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); - } + for_each_cpu_mask(query_cpu, mask) { + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + + /* + * prepare target chip field + */ + cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]); + apic_write_around(APIC_ICR2, cfg); + + /* + * program the ICR + */ + cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL); + + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); } local_irq_restore(flags); } diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h index eb3b7aa9eb9f..4482657777bb 100644 --- a/include/asm-x86_64/irq.h +++ b/include/asm-x86_64/irq.h @@ -57,4 +57,6 @@ int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern void fixup_irqs(cpumask_t map); #endif +#define __ARCH_HAS_DO_SOFTIRQ 1 + #endif /* _ASM_IRQ_H */ diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index bc700232728d..ba15279a79d0 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h @@ -218,7 +218,7 @@ extern inline unsigned int cpuid_edx(unsigned int op) #define MSR_K7_PERFCTR3 0xC0010007 #define MSR_K8_TOP_MEM1 0xC001001A #define MSR_K8_TOP_MEM2 0xC001001D -#define MSR_K8_SYSCFG 0xC0000010 +#define MSR_K8_SYSCFG 0xC0010010 /* K6 MSRs */ #define MSR_K6_EFER 0xC0000080 diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index eeb3088a1c9e..9c4527eb55e2 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -22,11 +22,9 @@ extern unsigned int pcibios_assign_all_busses(void); extern int no_iommu, force_iommu; extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_IO 0x4000 #define PCIBIOS_MIN_MEM (pci_mem_start) -#define PCIBIOS_MIN_CARDBUS_IO 0x4000 - void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 4eec176c3c39..4e167b5ea8f3 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -176,6 +176,8 @@ extern inline void pgd_clear (pgd_t * pgd) (_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_PCD) #define __PAGE_KERNEL_LARGE \ (__PAGE_KERNEL | _PAGE_PSE) +#define __PAGE_KERNEL_LARGE_EXEC \ + (__PAGE_KERNEL_EXEC | _PAGE_PSE) #define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL) diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index aeb1b73e21e1..de8b57b2b62b 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h @@ -46,12 +46,12 @@ extern int pic_mode; extern void lock_ipi_call_lock(void); extern void unlock_ipi_call_lock(void); extern int smp_num_siblings; -extern void smp_flush_tlb(void); -extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs); extern void smp_send_reschedule(int cpu); -extern void smp_invalidate_rcv(void); /* Process an NMI */ extern void zap_low_mappings(void); void smp_stop_cpu(void); +extern int smp_call_function_single(int cpuid, void (*func) (void *info), + void *info, int retry, int wait); + extern cpumask_t cpu_sibling_map[NR_CPUS]; extern cpumask_t cpu_core_map[NR_CPUS]; extern u8 phys_proc_id[NR_CPUS]; diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index 76165736e43a..8606e170a7dc 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h @@ -116,12 +116,12 @@ struct alt_instr { /* * Alternative inline assembly with input. * - * Pecularities: + * Peculiarities: * No memory clobber here. * Argument numbers start with 1. * Best is to use constraints that are fixed size (like (%1) ... "r") * If you use variable sized constraints like "m" or "g" in the - * replacement maake sure to pad to the worst case length. + * replacement make sure to pad to the worst case length. */ #define alternative_input(oldinstr, newinstr, feature, input...) \ asm volatile ("661:\n\t" oldinstr "\n662:\n" \ @@ -335,9 +335,6 @@ void cpu_idle_wait(void); void disable_hlt(void); void enable_hlt(void); -#define HAVE_EAT_KEY -void eat_key(void); - extern unsigned long arch_align_stack(unsigned long sp); #endif diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h index 061742382520..505b0cf906de 100644 --- a/include/asm-x86_64/tlbflush.h +++ b/include/asm-x86_64/tlbflush.h @@ -56,8 +56,9 @@ extern unsigned long pgkern_mask; * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables * - * ..but the x86_64 has somewhat limited tlb flushing capabilities, - * and page-granular flushes are available only on i486 and up. + * x86-64 can only flush individual pages or full VMs. For a range flush + * we always do the full VM. Might be worth trying if for a small + * range a few INVLPGs in a row are a win. */ #ifndef CONFIG_SMP @@ -115,7 +116,9 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* x86_64 does not keep any page table caches in TLB */ + /* x86_64 does not keep any page table caches in a software TLB. + The CPUs do in their hardware TLBs, but they are handled + by the normal TLB flushing algorithms. */ } #endif /* _X8664_TLBFLUSH_H */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f85cbe919e13..b46a5205ee7b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -453,9 +453,7 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); * If this matches the last registration, any IRQ resources for gsi * are freed. */ -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ void acpi_unregister_gsi (u32 gsi); -#endif #ifdef CONFIG_ACPI_PCI @@ -480,9 +478,7 @@ struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); void acpi_penalize_isa_irq(int irq, int active); -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ void acpi_pci_irq_disable (struct pci_dev *dev); -#endif struct acpi_pci_driver { struct acpi_pci_driver *next; diff --git a/include/linux/dcookies.h b/include/linux/dcookies.h index c28050136164..1d68428c925d 100644 --- a/include/linux/dcookies.h +++ b/include/linux/dcookies.h @@ -48,12 +48,12 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt, #else -struct dcookie_user * dcookie_register(void) +static inline struct dcookie_user * dcookie_register(void) { return NULL; } -void dcookie_unregister(struct dcookie_user * user) +static inline void dcookie_unregister(struct dcookie_user * user) { return; } diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index d07a92c94776..e96a4306ab3b 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -21,7 +21,7 @@ */ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, const char *old_name, const char *new_name, - int isdir) + int isdir, struct inode *target) { u32 cookie = inotify_get_cookie(); @@ -36,6 +36,11 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, isdir = IN_ISDIR; inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name); inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name); + + if (target) { + inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL); + inotify_inode_is_dead(target); + } } /* diff --git a/include/linux/input.h b/include/linux/input.h index b9cc0ac71f44..bdc53c6cc962 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -811,9 +811,9 @@ struct input_dev { void *private; - char *name; - char *phys; - char *uniq; + const char *name; + const char *phys; + const char *uniq; struct input_id id; unsigned long evbit[NBITS(EV_MAX)]; diff --git a/include/linux/mm.h b/include/linux/mm.h index 6eb7f48317f8..82d7024f0765 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -625,10 +625,16 @@ static inline int page_mapped(struct page *page) * Used to decide whether a process gets delivered SIGBUS or * just gets major/minor fault counters bumped up. */ -#define VM_FAULT_OOM (-1) -#define VM_FAULT_SIGBUS 0 -#define VM_FAULT_MINOR 1 -#define VM_FAULT_MAJOR 2 +#define VM_FAULT_OOM 0x00 +#define VM_FAULT_SIGBUS 0x01 +#define VM_FAULT_MINOR 0x02 +#define VM_FAULT_MAJOR 0x03 + +/* + * Special case for get_user_pages. + * Must be in a distinct bit from the above VM_FAULT_ flags. + */ +#define VM_FAULT_WRITE 0x10 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) @@ -704,7 +710,13 @@ extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsign extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot); extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot); -extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); +extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); + +static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access) +{ + return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE); +} + extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); void install_arg_page(struct vm_area_struct *, struct page *, unsigned long); diff --git a/include/linux/pci.h b/include/linux/pci.h index 7ac14961ba22..8621cf42b46f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -971,6 +971,8 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en #define isa_bridge ((struct pci_dev *)NULL) +#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) + #else /* @@ -985,9 +987,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) return 0; } #endif - -#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) - #endif /* !CONFIG_PCI */ /* these helpers provide future and backwards compatibility diff --git a/include/linux/uinput.h b/include/linux/uinput.h index 4c2c82336d10..84876077027f 100644 --- a/include/linux/uinput.h +++ b/include/linux/uinput.h @@ -42,8 +42,7 @@ struct uinput_request { int code; /* UI_FF_UPLOAD, UI_FF_ERASE */ int retval; - wait_queue_head_t waitq; - int completed; + struct completion done; union { int effect_id; @@ -62,7 +61,7 @@ struct uinput_device { struct uinput_request *requests[UINPUT_NUM_REQUESTS]; wait_queue_head_t requests_waitq; - struct semaphore requests_sem; + spinlock_t requests_lock; }; #endif /* __KERNEL__ */ diff --git a/include/linux/usb_input.h b/include/linux/usb_input.h new file mode 100644 index 000000000000..716e0cc16043 --- /dev/null +++ b/include/linux/usb_input.h @@ -0,0 +1,25 @@ +#ifndef __USB_INPUT_H +#define __USB_INPUT_H + +/* + * Copyright (C) 2005 Dmitry Torokhov + * + * 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/usb.h> +#include <linux/input.h> +#include <asm/byteorder.h> + +static inline void +usb_to_input_id(const struct usb_device *dev, struct input_id *id) +{ + id->bustype = BUS_USB; + id->vendor = le16_to_cpu(dev->descriptor.idVendor); + id->product = le16_to_cpu(dev->descriptor.idProduct); + id->version = le16_to_cpu(dev->descriptor.bcdDevice); +} + +#endif diff --git a/include/media/tuner.h b/include/media/tuner.h index d8c0a5563289..eeaa15ddee85 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -1,5 +1,5 @@ -/* $Id: tuner.h,v 1.42 2005/07/06 09:42:19 mchehab Exp $ +/* $Id: tuner.h,v 1.45 2005/07/28 18:41:21 mchehab Exp $ * tuner.h - definition for different tuners @@ -108,6 +108,8 @@ #define TUNER_TEA5767 62 /* Only FM Radio Tuner */ #define TUNER_PHILIPS_FMD1216ME_MK3 63 +#define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ +#define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ #define NOTUNER 0 #define PAL 1 /* PAL_BG */ diff --git a/include/net/tcp.h b/include/net/tcp.h index f4f9aba07ac2..5010f0c5a56e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1236,7 +1236,7 @@ static inline void tcp_sync_left_out(struct tcp_sock *tp) tp->left_out = tp->sacked_out + tp->lost_out; } -/* Set slow start threshould and cwnd not falling to slow start */ +/* Set slow start threshold and cwnd not falling to slow start */ static inline void __tcp_enter_cwr(struct tcp_sock *tp) { tp->undo_marker = 0; diff --git a/init/main.c b/init/main.c index b5e421e39ede..c9c311cf1771 100644 --- a/init/main.c +++ b/init/main.c @@ -51,6 +51,7 @@ #include <asm/io.h> #include <asm/bugs.h> #include <asm/setup.h> +#include <asm/sections.h> /* * This is one of the first .c files built. Error out early @@ -323,8 +324,6 @@ static void __init setup_per_cpu_areas(void) { unsigned long size, i; char *ptr; - /* Created by linker magic */ - extern char __per_cpu_start[], __per_cpu_end[]; /* Copy section for each CPU (we discard the original) */ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES); diff --git a/ipc/shm.c b/ipc/shm.c index cce022435dbc..1d6cf08d950b 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -170,7 +170,7 @@ static struct vm_operations_struct shm_vm_ops = { .open = shm_open, /* callback for a new vm-area open */ .close = shm_close, /* callback for when the vm-area is released */ .nopage = shmem_nopage, -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM) .set_policy = shmem_set_policy, .get_policy = shmem_get_policy, #endif diff --git a/kernel/module.c b/kernel/module.c index 068e271ab3a5..c32995fbd8fd 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -250,13 +250,18 @@ static inline unsigned int block_size(int val) /* Created by linker magic */ extern char __per_cpu_start[], __per_cpu_end[]; -static void *percpu_modalloc(unsigned long size, unsigned long align) +static void *percpu_modalloc(unsigned long size, unsigned long align, + const char *name) { unsigned long extra; unsigned int i; void *ptr; - BUG_ON(align > SMP_CACHE_BYTES); + if (align > SMP_CACHE_BYTES) { + printk(KERN_WARNING "%s: per-cpu alignment %li > %i\n", + name, align, SMP_CACHE_BYTES); + align = SMP_CACHE_BYTES; + } ptr = __per_cpu_start; for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { @@ -348,7 +353,8 @@ static int percpu_modinit(void) } __initcall(percpu_modinit); #else /* ... !CONFIG_SMP */ -static inline void *percpu_modalloc(unsigned long size, unsigned long align) +static inline void *percpu_modalloc(unsigned long size, unsigned long align, + const char *name) { return NULL; } @@ -1644,7 +1650,8 @@ static struct module *load_module(void __user *umod, if (pcpuindex) { /* We have a special allocation for this section. */ percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, - sechdrs[pcpuindex].sh_addralign); + sechdrs[pcpuindex].sh_addralign, + mod->name); if (!percpu) { err = -ENOMEM; goto free_mod; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 5b7b4736d82b..10b2ad749d14 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -896,21 +896,10 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp, jiffies_64_f = get_jiffies_64(); } /* - * Take away now to get delta + * Take away now to get delta and normalize */ - oc.tv_sec -= now.tv_sec; - oc.tv_nsec -= now.tv_nsec; - /* - * Normalize... - */ - while ((oc.tv_nsec - NSEC_PER_SEC) >= 0) { - oc.tv_nsec -= NSEC_PER_SEC; - oc.tv_sec++; - } - while ((oc.tv_nsec) < 0) { - oc.tv_nsec += NSEC_PER_SEC; - oc.tv_sec--; - } + set_normalized_timespec(&oc, oc.tv_sec - now.tv_sec, + oc.tv_nsec - now.tv_nsec); }else{ jiffies_64_f = get_jiffies_64(); } diff --git a/kernel/sys.c b/kernel/sys.c index 8f255259ef9e..0bcaed6560ac 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -392,7 +392,6 @@ void kernel_kexec(void) } notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL); system_state = SYSTEM_RESTART; - device_suspend(PMSG_FREEZE); device_shutdown(); printk(KERN_EMERG "Starting new kernel\n"); machine_shutdown(); @@ -405,7 +404,6 @@ void kernel_halt(void) { notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); system_state = SYSTEM_HALT; - device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "System halted.\n"); machine_halt(); @@ -416,7 +414,6 @@ void kernel_power_off(void) { notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); system_state = SYSTEM_POWER_OFF; - device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 42b40ae5eada..1ab2370e2efa 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -79,7 +79,6 @@ cond_syscall(sys_request_key); cond_syscall(sys_keyctl); cond_syscall(compat_sys_keyctl); cond_syscall(compat_sys_socketcall); -cond_syscall(sys_set_zone_reclaim); cond_syscall(sys_inotify_init); cond_syscall(sys_inotify_add_watch); cond_syscall(sys_inotify_rm_watch); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0c421295e613..299f7f3b5b08 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -141,7 +141,7 @@ config DEBUG_IOREMAP config DEBUG_FS bool "Debug Filesystem" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && SYSFS help debugfs is a virtual file system that kernel developers use to put debugging files into. Enable this option to be able to read and diff --git a/mm/memory.c b/mm/memory.c index 6fe77acbc1cd..e046b7e4b530 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -913,9 +913,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, pud = pud_offset(pgd, pg); BUG_ON(pud_none(*pud)); pmd = pmd_offset(pud, pg); - BUG_ON(pmd_none(*pmd)); + if (pmd_none(*pmd)) + return i ? : -EFAULT; pte = pte_offset_map(pmd, pg); - BUG_ON(pte_none(*pte)); + if (pte_none(*pte)) { + pte_unmap(pte); + return i ? : -EFAULT; + } if (pages) { pages[i] = pte_page(*pte); get_page(pages[i]); @@ -940,11 +944,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, } spin_lock(&mm->page_table_lock); do { + int write_access = write; struct page *page; - int lookup_write = write; cond_resched_lock(&mm->page_table_lock); - while (!(page = follow_page(mm, start, lookup_write))) { + while (!(page = follow_page(mm, start, write_access))) { + int ret; + /* * Shortcut for anonymous pages. We don't want * to force the creation of pages tables for @@ -952,13 +958,23 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * nobody touched so far. This is important * for doing a core dump for these mappings. */ - if (!lookup_write && - untouched_anonymous_page(mm,vma,start)) { + if (!write && untouched_anonymous_page(mm,vma,start)) { page = ZERO_PAGE(start); break; } spin_unlock(&mm->page_table_lock); - switch (handle_mm_fault(mm,vma,start,write)) { + ret = __handle_mm_fault(mm, vma, start, write_access); + + /* + * The VM_FAULT_WRITE bit tells us that do_wp_page has + * broken COW when necessary, even if maybe_mkwrite + * decided not to set pte_write. We can thus safely do + * subsequent page lookups as if they were reads. + */ + if (ret & VM_FAULT_WRITE) + write_access = 0; + + switch (ret & ~VM_FAULT_WRITE) { case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -972,14 +988,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, default: BUG(); } - /* - * Now that we have performed a write fault - * and surely no longer have a shared page we - * shouldn't write, we shouldn't ignore an - * unwritable page in the page table if - * we are forcing write access. - */ - lookup_write = write && !force; spin_lock(&mm->page_table_lock); } if (pages) { @@ -1229,6 +1237,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, struct page *old_page, *new_page; unsigned long pfn = pte_pfn(pte); pte_t entry; + int ret; if (unlikely(!pfn_valid(pfn))) { /* @@ -1256,7 +1265,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, lazy_mmu_prot_update(entry); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); - return VM_FAULT_MINOR; + return VM_FAULT_MINOR|VM_FAULT_WRITE; } } pte_unmap(page_table); @@ -1283,6 +1292,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* * Re-check the pte - we dropped the lock */ + ret = VM_FAULT_MINOR; spin_lock(&mm->page_table_lock); page_table = pte_offset_map(pmd, address); if (likely(pte_same(*page_table, pte))) { @@ -1299,12 +1309,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* Free the old page.. */ new_page = old_page; + ret |= VM_FAULT_WRITE; } pte_unmap(page_table); page_cache_release(new_page); page_cache_release(old_page); spin_unlock(&mm->page_table_lock); - return VM_FAULT_MINOR; + return ret; no_new_page: page_cache_release(old_page); @@ -1996,7 +2007,6 @@ static inline int handle_pte_fault(struct mm_struct *mm, if (write_access) { if (!pte_write(entry)) return do_wp_page(mm, vma, address, pte, pmd, entry); - entry = pte_mkdirty(entry); } entry = pte_mkyoung(entry); @@ -2011,7 +2021,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, /* * By the time we get here, we already hold the mm semaphore */ -int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, +int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long address, int write_access) { pgd_t *pgd; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1694845526be..b4eababc8198 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -443,7 +443,7 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, struct mempolicy *new; DECLARE_BITMAP(nodes, MAX_NUMNODES); - if (mode > MPOL_MAX) + if (mode < 0 || mode > MPOL_MAX) return -EINVAL; err = get_nodes(nodes, nmask, maxnode, mode); if (err) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 42bccfb8464d..8d088371196a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1061,20 +1061,19 @@ unsigned int nr_free_pages_pgdat(pg_data_t *pgdat) static unsigned int nr_free_zone_pages(int offset) { - pg_data_t *pgdat; + /* Just pick one node, since fallback list is circular */ + pg_data_t *pgdat = NODE_DATA(numa_node_id()); unsigned int sum = 0; - for_each_pgdat(pgdat) { - struct zonelist *zonelist = pgdat->node_zonelists + offset; - struct zone **zonep = zonelist->zones; - struct zone *zone; + struct zonelist *zonelist = pgdat->node_zonelists + offset; + struct zone **zonep = zonelist->zones; + struct zone *zone; - for (zone = *zonep++; zone; zone = *zonep++) { - unsigned long size = zone->present_pages; - unsigned long high = zone->pages_high; - if (size > high) - sum += size - high; - } + for (zone = *zonep++; zone; zone = *zonep++) { + unsigned long size = zone->present_pages; + unsigned long high = zone->pages_high; + if (size > high) + sum += size - high; } return sum; diff --git a/net/core/dev.c b/net/core/dev.c index ff9dc029233a..52a3bf7ae177 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -901,8 +901,7 @@ int dev_close(struct net_device *dev) smp_mb__after_clear_bit(); /* Commit netif_running(). */ while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) { /* No hurry. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + msleep(1); } /* diff --git a/net/core/dst.c b/net/core/dst.c index fc434ade5270..334790da9f16 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -45,6 +45,7 @@ static struct timer_list dst_gc_timer = static void dst_run_gc(unsigned long dummy) { int delayed = 0; + int work_performed; struct dst_entry * dst, **dstp; if (!spin_trylock(&dst_lock)) { @@ -52,9 +53,9 @@ static void dst_run_gc(unsigned long dummy) return; } - del_timer(&dst_gc_timer); dstp = &dst_garbage_list; + work_performed = 0; while ((dst = *dstp) != NULL) { if (atomic_read(&dst->__refcnt)) { dstp = &dst->next; @@ -62,6 +63,7 @@ static void dst_run_gc(unsigned long dummy) continue; } *dstp = dst->next; + work_performed = 1; dst = dst_destroy(dst); if (dst) { @@ -86,9 +88,14 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc = DST_GC_MAX; goto out; } - if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX) - dst_gc_timer_expires = DST_GC_MAX; - dst_gc_timer_inc += DST_GC_INC; + if (!work_performed) { + if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX) + dst_gc_timer_expires = DST_GC_MAX; + dst_gc_timer_inc += DST_GC_INC; + } else { + dst_gc_timer_inc = DST_GC_INC; + dst_gc_timer_expires = DST_GC_MIN; + } dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 printk("dst_total: %d/%d %ld\n", diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 884835522224..f0d5740d7e22 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); ipgre_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -1277,12 +1276,28 @@ err1: goto out; } -static void ipgre_fini(void) +static void __exit ipgre_destroy_tunnels(void) +{ + int prio; + + for (prio = 0; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + +static void __exit ipgre_fini(void) { if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); - unregister_netdev(ipgre_fb_tunnel_dev); + rtnl_lock(); + ipgre_destroy_tunnels(); + rtnl_unlock(); } module_init(ipgre_init); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index c3947cd566b7..c05c1df0bb04 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c dev_hold(dev); ipip_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -920,12 +919,29 @@ static int __init ipip_init(void) goto out; } +static void __exit ipip_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + static void __exit ipip_fini(void) { if (ipip_unregister() < 0) printk(KERN_INFO "ipip close: can't deregister tunnel\n"); - unregister_netdev(ipip_fb_tunnel_dev); + rtnl_lock(); + ipip_destroy_tunnels(); + unregister_netdevice(ipip_fb_tunnel_dev); + rtnl_unlock(); } module_init(ipip_init); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 7833d920bdba..dc806b578427 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -362,7 +362,7 @@ out: /* Fill oifs list. It is called under write locked mrt_lock. */ -static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls) +static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) { int vifi; @@ -727,7 +727,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) if (c != NULL) { write_lock_bh(&mrt_lock); c->mfc_parent = mfc->mfcc_parent; - ipmr_update_threshoulds(c, mfc->mfcc_ttls); + ipmr_update_thresholds(c, mfc->mfcc_ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; write_unlock_bh(&mrt_lock); @@ -744,7 +744,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) c->mfc_origin=mfc->mfcc_origin.s_addr; c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr; c->mfc_parent=mfc->mfcc_parent; - ipmr_update_threshoulds(c, mfc->mfcc_ttls); + ipmr_update_thresholds(c, mfc->mfcc_ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 86f04e41dd8e..a7f0c821a9b2 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -513,6 +513,11 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, #ifdef CONFIG_IP_NF_CONNTRACK_MARK conntrack->mark = exp->master->mark; #endif +#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ + defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) + /* this is ugly, but there is no other place where to put it */ + conntrack->nat.masq_index = exp->master->nat.masq_index; +#endif nf_conntrack_get(&conntrack->master->ct_general); CONNTRACK_STAT_INC(expect_new); } else { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b788f55e139b..e553e5b80d6e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); ipip6_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = { .err_handler = ipip6_err, }; +static void __exit sit_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + void __exit sit_cleanup(void) { inet_del_protocol(&sit_protocol, IPPROTO_IPV6); - unregister_netdev(ipip6_fb_tunnel_dev); + + rtnl_lock(); + sit_destroy_tunnels(); + unregister_netdevice(ipip6_fb_tunnel_dev); + rtnl_unlock(); } int __init sit_init(void) diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c index ad6b12043874..9f5aabd58fa9 100644 --- a/scripts/kconfig/gconf.c +++ b/scripts/kconfig/gconf.c @@ -178,17 +178,31 @@ const char *dbg_print_ptype(int val) } -/* Main Window Initialization */ +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} +/* Main Window Initialization */ void init_main_window(const gchar * glade_file) { GladeXML *xml; GtkWidget *widget; GtkTextBuffer *txtbuf; char title[256]; - GdkPixmap *pixmap; - GdkBitmap *mask; GtkStyle *style; xml = glade_xml_new(glade_file, "window1", NULL); @@ -221,36 +235,22 @@ void init_main_window(const gchar * glade_file) style = gtk_widget_get_style(main_wnd); widget = glade_xml_get_widget(xml, "toolbar1"); - pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **) xpm_single_view); - gtk_image_set_from_pixmap(GTK_IMAGE - (((GtkToolbarChild - *) (g_list_nth(GTK_TOOLBAR(widget)-> - children, - 5)->data))->icon), - pixmap, mask); - pixmap = - gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **) xpm_split_view); - gtk_image_set_from_pixmap(GTK_IMAGE - (((GtkToolbarChild - *) (g_list_nth(GTK_TOOLBAR(widget)-> - children, - 6)->data))->icon), - pixmap, mask); - pixmap = - gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **) xpm_tree_view); - gtk_image_set_from_pixmap(GTK_IMAGE - (((GtkToolbarChild - *) (g_list_nth(GTK_TOOLBAR(widget)-> - children, - 7)->data))->icon), - pixmap, mask); - +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 switch (view_mode) { case SINGLE_VIEW: widget = glade_xml_get_widget(xml, "button4"); @@ -265,7 +265,7 @@ void init_main_window(const gchar * glade_file) g_signal_emit_by_name(widget, "clicked"); break; } - +#endif txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", "foreground", "red", @@ -322,7 +322,7 @@ void init_left_tree(void) gtk_tree_view_set_model(view, model1); gtk_tree_view_set_headers_visible(view, TRUE); gtk_tree_view_set_rules_hint(view, FALSE); - + column = gtk_tree_view_column_new(); gtk_tree_view_append_column(view, column); gtk_tree_view_column_set_title(column, _("Options")); @@ -334,11 +334,11 @@ void init_left_tree(void) renderer, "active", COL_BTNACT, "inconsistent", COL_BTNINC, - "visible", COL_BTNVIS, + "visible", COL_BTNVIS, "radio", COL_BTNRAD, NULL); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), - renderer, FALSE); + renderer, FALSE); gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), renderer, "text", COL_OPTION, @@ -386,7 +386,7 @@ void init_right_tree(void) renderer, "active", COL_BTNACT, "inconsistent", COL_BTNINC, - "visible", COL_BTNVIS, + "visible", COL_BTNVIS, "radio", COL_BTNRAD, NULL); /*g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(renderer_toggled), NULL); */ @@ -806,7 +806,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) } -void on_back_pressed(GtkButton * button, gpointer user_data) +void on_back_clicked(GtkButton * button, gpointer user_data) { enum prop_type ptype; @@ -821,13 +821,13 @@ void on_back_pressed(GtkButton * button, gpointer user_data) } -void on_load_pressed(GtkButton * button, gpointer user_data) +void on_load_clicked(GtkButton * button, gpointer user_data) { on_load1_activate(NULL, user_data); } -void on_save_pressed(GtkButton * button, gpointer user_data) +void on_save_clicked(GtkButton * button, gpointer user_data) { on_save1_activate(NULL, user_data); } @@ -850,9 +850,12 @@ void on_split_clicked(GtkButton * button, gpointer user_data) gtk_widget_show(tree1_w); gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); gtk_paned_set_position(GTK_PANED(hpaned), w / 2); - if (tree2) + if (tree2) gtk_tree_store_clear(tree2); display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); } @@ -868,13 +871,13 @@ void on_full_clicked(GtkButton * button, gpointer user_data) } -void on_collapse_pressed(GtkButton * button, gpointer user_data) +void on_collapse_clicked(GtkButton * button, gpointer user_data) { gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); } -void on_expand_pressed(GtkButton * button, gpointer user_data) +void on_expand_clicked(GtkButton * button, gpointer user_data) { gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); } @@ -1242,13 +1245,13 @@ static gchar **fill_row(struct menu *menu) row[COL_VALUE] = g_strdup(menu_get_prompt(def_menu)); } - if(sym->flags & SYMBOL_CHOICEVAL) + if (sym->flags & SYMBOL_CHOICEVAL) row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); stype = sym_get_type(sym); switch (stype) { case S_BOOLEAN: - if(GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); if (sym_is_choice(sym)) break; @@ -1423,7 +1426,7 @@ static void update_tree(struct menu *src, GtkTreeIter * dst) child2); gtk_tree_store_remove(tree2, &tmp); if (!valid) - return; // next parent + return; // next parent else goto reparse; // next child } else @@ -1448,7 +1451,7 @@ static void update_tree(struct menu *src, GtkTreeIter * dst) child2); gtk_tree_store_remove(tree2, &tmp); if (!valid) - return; // next parent + return; // next parent else goto reparse; // next child } @@ -1486,12 +1489,12 @@ static void display_tree(struct menu *menu) if (sym) sym->flags &= ~SYMBOL_CHANGED; - if ((view_mode == SPLIT_VIEW) && !(child->flags & MENU_ROOT) && - (tree == tree1)) + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) continue; - if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) && - (tree == tree2)) + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) continue; if (menu_is_visible(child) || show_all) @@ -1513,11 +1516,12 @@ static void display_tree(struct menu *menu) && (tree == tree2)) continue; /* - if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) || - (view_mode == FULL_VIEW) + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW))*/ if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) - || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW)) { + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { indent++; display_tree(child); indent--; @@ -1530,9 +1534,9 @@ static void display_tree_part(void) { if (tree2) gtk_tree_store_clear(tree2); - if(view_mode == SINGLE_VIEW) + if (view_mode == SINGLE_VIEW) display_tree(current); - else if(view_mode == SPLIT_VIEW) + else if (view_mode == SPLIT_VIEW) display_tree(browsed); gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); } @@ -1551,24 +1555,22 @@ static void display_list(void) void fixup_rootmenu(struct menu *menu) { - struct menu *child; - static int menu_cnt = 0; - - menu->flags |= MENU_ROOT; - for (child = menu->list; child; child = child->next) { - if (child->prompt && child->prompt->type == P_MENU) { - menu_cnt++; - fixup_rootmenu(child); - menu_cnt--; - } else if (!menu_cnt) - fixup_rootmenu(child); - } + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } } /* Main */ - - int main(int ac, char *av[]) { const char *name; diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade index ace4706ab251..f8744ed64967 100644 --- a/scripts/kconfig/gconf.glade +++ b/scripts/kconfig/gconf.glade @@ -13,6 +13,11 @@ <property name="default_height">480</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <signal name="destroy" handler="on_window1_destroy" object="window1"/> <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/> <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/> @@ -46,7 +51,7 @@ <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image27"> + <widget class="GtkImage" id="image39"> <property name="visible">True</property> <property name="stock">gtk-open</property> <property name="icon_size">1</property> @@ -69,7 +74,7 @@ <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image28"> + <widget class="GtkImage" id="image40"> <property name="visible">True</property> <property name="stock">gtk-save</property> <property name="icon_size">1</property> @@ -91,7 +96,7 @@ <signal name="activate" handler="on_save_as1_activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image29"> + <widget class="GtkImage" id="image41"> <property name="visible">True</property> <property name="stock">gtk-save-as</property> <property name="icon_size">1</property> @@ -105,7 +110,7 @@ </child> <child> - <widget class="GtkMenuItem" id="separator1"> + <widget class="GtkSeparatorMenuItem" id="separator1"> <property name="visible">True</property> </widget> </child> @@ -119,7 +124,7 @@ <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image30"> + <widget class="GtkImage" id="image42"> <property name="visible">True</property> <property name="stock">gtk-quit</property> <property name="icon_size">1</property> @@ -179,7 +184,7 @@ </child> <child> - <widget class="GtkMenuItem" id="separator2"> + <widget class="GtkSeparatorMenuItem" id="separator2"> <property name="visible">True</property> </widget> </child> @@ -228,7 +233,7 @@ <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image31"> + <widget class="GtkImage" id="image43"> <property name="visible">True</property> <property name="stock">gtk-dialog-question</property> <property name="icon_size">1</property> @@ -250,7 +255,7 @@ <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/> <child internal-child="image"> - <widget class="GtkImage" id="image32"> + <widget class="GtkImage" id="image44"> <property name="visible">True</property> <property name="stock">gtk-properties</property> <property name="icon_size">1</property> @@ -271,7 +276,7 @@ <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/> <child internal-child="image"> - <widget class="GtkImage" id="image33"> + <widget class="GtkImage" id="image45"> <property name="visible">True</property> <property name="stock">gtk-justify-fill</property> <property name="icon_size">1</property> @@ -308,109 +313,207 @@ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> <property name="toolbar_style">GTK_TOOLBAR_BOTH</property> <property name="tooltips">True</property> + <property name="show_arrow">True</property> <child> - <widget class="button" id="button1"> + <widget class="GtkToolButton" id="button1"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Goes up of one level (single view)</property> <property name="label" translatable="yes">Back</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-undo</property> - <signal name="pressed" handler="on_back_pressed"/> + <property name="stock_id">gtk-undo</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_back_clicked"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="GtkVSeparator" id="vseparator1"> + <widget class="GtkToolItem" id="toolitem1"> <property name="visible">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + + <child> + <widget class="GtkVSeparator" id="vseparator1"> + <property name="visible">True</property> + </widget> + </child> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> </child> <child> - <widget class="button" id="button2"> + <widget class="GtkToolButton" id="button2"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Load a config file</property> <property name="label" translatable="yes">Load</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-open</property> - <signal name="pressed" handler="on_load_pressed"/> + <property name="stock_id">gtk-open</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_load_clicked"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="button" id="button3"> + <widget class="GtkToolButton" id="button3"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Save a config file</property> <property name="label" translatable="yes">Save</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-save</property> - <signal name="pressed" handler="on_save_pressed"/> + <property name="stock_id">gtk-save</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_save_clicked"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="GtkVSeparator" id="vseparator2"> + <widget class="GtkToolItem" id="toolitem2"> <property name="visible">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + + <child> + <widget class="GtkVSeparator" id="vseparator2"> + <property name="visible">True</property> + </widget> + </child> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> </child> <child> - <widget class="button" id="button4"> + <widget class="GtkToolButton" id="button4"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Single view</property> <property name="label" translatable="yes">Single</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-missing-image</property> + <property name="stock_id">gtk-missing-image</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="button" id="button5"> + <widget class="GtkToolButton" id="button5"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Split view</property> <property name="label" translatable="yes">Split</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-missing-image</property> + <property name="stock_id">gtk-missing-image</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="button" id="button6"> + <widget class="GtkToolButton" id="button6"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Full view</property> <property name="label" translatable="yes">Full</property> <property name="use_underline">True</property> - <property name="stock_pixmap">gtk-missing-image</property> + <property name="stock_id">gtk-missing-image</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="GtkVSeparator" id="vseparator3"> + <widget class="GtkToolItem" id="toolitem3"> <property name="visible">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + + <child> + <widget class="GtkVSeparator" id="vseparator3"> + <property name="visible">True</property> + </widget> + </child> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> </child> <child> - <widget class="button" id="button7"> + <widget class="GtkToolButton" id="button7"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property> <property name="label" translatable="yes">Collapse</property> <property name="use_underline">True</property> - <signal name="pressed" handler="on_collapse_pressed"/> + <property name="stock_id">gtk-remove</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_collapse_clicked"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> <child> - <widget class="button" id="button8"> + <widget class="GtkToolButton" id="button8"> <property name="visible">True</property> <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property> <property name="label" translatable="yes">Expand</property> <property name="use_underline">True</property> - <signal name="pressed" handler="on_expand_pressed"/> + <property name="stock_id">gtk-add</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_expand_clicked"/> </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> </child> </widget> </child> @@ -505,6 +608,8 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> <property name="justification">GTK_JUSTIFY_LEFT</property> <property name="wrap_mode">GTK_WRAP_WORD</property> <property name="cursor_visible">True</property> diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index fea262860ea0..a6516a64b297 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -49,9 +49,6 @@ asmlinkage long sys_add_key(const char __user *_type, goto error; type[31] = '\0'; - if (!type[0]) - goto error; - ret = -EPERM; if (type[0] == '.') goto error; @@ -144,6 +141,10 @@ asmlinkage long sys_request_key(const char __user *_type, goto error; type[31] = '\0'; + ret = -EPERM; + if (type[0] == '.') + goto error; + /* pull the description into kernel space */ ret = -EFAULT; dlen = strnlen_user(_description, PAGE_SIZE - 1); @@ -362,7 +363,7 @@ long keyctl_revoke_key(key_serial_t id) key_put(key); error: - return 0; + return ret; } /* end keyctl_revoke_key() */ @@ -685,6 +686,8 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) goto can_read_key2; ret = PTR_ERR(skey); + if (ret == -EAGAIN) + ret = -EACCES; goto error2; } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index dfcd983af1fd..90c1506d007c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -405,7 +405,7 @@ struct key *request_key_and_link(struct key_type *type, key_user_put(user); /* link the new key into the appropriate keyring */ - if (!PTR_ERR(key)) + if (!IS_ERR(key)) request_key_link(key, dest_keyring); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 10fd51c9056d..2253f388234f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3126,12 +3126,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, if (sk->sk_family == PF_INET) { addr4 = (struct sockaddr_in *)address; - if (addrlen != sizeof(struct sockaddr_in)) + if (addrlen < sizeof(struct sockaddr_in)) return -EINVAL; snum = ntohs(addr4->sin_port); } else { addr6 = (struct sockaddr_in6 *)address; - if (addrlen != sizeof(struct sockaddr_in6)) + if (addrlen < SIN6_LEN_RFC2133) return -EINVAL; snum = ntohs(addr6->sin6_port); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 7c806bd9cc90..d7af3e474432 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2376,6 +2376,9 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state) snd_ac97_suspend(chip->ac97[i]); if (chip->device_type == DEVICE_INTEL_ICH4) chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); + + if (chip->irq >= 0) + free_irq(chip->irq, (void *)chip); pci_disable_device(chip->pci); return 0; } @@ -2387,7 +2390,9 @@ static int intel8x0_resume(snd_card_t *card) pci_enable_device(chip->pci); pci_set_master(chip->pci); - snd_intel8x0_chip_init(chip, 0); + request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip); + synchronize_irq(chip->irq); + snd_intel8x0_chip_init(chip, 1); /* re-initialize mixer stuff */ if (chip->device_type == DEVICE_INTEL_ICH4) { |