diff --git a/[refs] b/[refs] index ae0323b0e3db..340e119aef1d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b80de369aa5c7c8ce7ff7a691e86e1dcc89accc6 +refs/heads/master: 0b3682ba33c59a362901b478bdab965da888b350 diff --git a/trunk/CREDITS b/trunk/CREDITS index b50db1767554..2358846f06be 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -598,11 +598,6 @@ S: Tamsui town, Taipei county, S: Taiwan 251 S: Republic of China -N: Reinette Chatre -E: reinette.chatre@intel.com -D: WiMedia Link Protocol implementation -D: UWB stack bits and pieces - N: Michael Elizabeth Chastain E: mec@shout.net D: Configure, Menuconfig, xconfig @@ -2700,12 +2695,6 @@ S: Demonstratsii 8-382 S: Tula 300000 S: Russia -N: Inaky Perez-Gonzalez -E: inaky.perez-gonzalez@intel.com -D: UWB stack, HWA-RC driver and HWA-HC drivers -D: Wireless USB additions to the USB stack -D: WiMedia Link Protocol bits and pieces - N: Gordon Peters E: GordPeters@smarttech.com D: Isochronous receive for IEEE 1394 driver (OHCI module). diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-umc b/trunk/Documentation/ABI/testing/sysfs-bus-umc deleted file mode 100644 index 948fec412446..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-bus-umc +++ /dev/null @@ -1,28 +0,0 @@ -What: /sys/bus/umc/ -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The Wireless Host Controller Interface (WHCI) - specification describes a PCI-based device with - multiple capabilities; the UWB Multi-interface - Controller (UMC). - - The umc bus presents each of the individual - capabilties as a device. - -What: /sys/bus/umc/devices/.../capability_id -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The ID of this capability, with 0 being the radio - controller capability. - -What: /sys/bus/umc/devices/.../version -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The specification version this capability's hardware - interface complies with. diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-usb b/trunk/Documentation/ABI/testing/sysfs-bus-usb index 7772928ee48f..df6c8a0159f1 100644 --- a/trunk/Documentation/ABI/testing/sysfs-bus-usb +++ b/trunk/Documentation/ABI/testing/sysfs-bus-usb @@ -101,46 +101,3 @@ Description: Users: USB PM tool git://git.moblin.org/users/sarah/usb-pm-tool/ - -What: /sys/bus/usb/device/.../authorized -Date: July 2008 -KernelVersion: 2.6.26 -Contact: David Vrabel -Description: - Authorized devices are available for use by device - drivers, non-authorized one are not. By default, wired - USB devices are authorized. - - Certified Wireless USB devices are not authorized - initially and should be (by writing 1) after the - device has been authenticated. - -What: /sys/bus/usb/device/.../wusb_cdid -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - For Certified Wireless USB devices only. - - A devices's CDID, as 16 space-separated hex octets. - -What: /sys/bus/usb/device/.../wusb_ck -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - For Certified Wireless USB devices only. - - Write the device's connection key (CK) to start the - authentication of the device. The CK is 16 - space-separated hex octets. - -What: /sys/bus/usb/device/.../wusb_disconnect -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - For Certified Wireless USB devices only. - - Write a 1 to force the device to disconnect - (equivalent to unplugging a wired USB device). diff --git a/trunk/Documentation/ABI/testing/sysfs-class-usb_host b/trunk/Documentation/ABI/testing/sysfs-class-usb_host deleted file mode 100644 index 46b66ad1f1b4..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-class-usb_host +++ /dev/null @@ -1,25 +0,0 @@ -What: /sys/class/usb_host/usb_hostN/wusb_chid -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - Write the CHID (16 space-separated hex octets) for this host controller. - This starts the host controller, allowing it to accept connection from - WUSB devices. - - Set an all zero CHID to stop the host controller. - -What: /sys/class/usb_host/usb_hostN/wusb_trust_timeout -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - Devices that haven't sent a WUSB packet to the host - within 'wusb_trust_timeout' ms are considered to have - disconnected and are removed. The default value of - 4000 ms is the value required by the WUSB - specification. - - Since this relates to security (specifically, the - lifetime of PTKs and GTKs) it should not be changed - from the default. diff --git a/trunk/Documentation/ABI/testing/sysfs-class-uwb_rc b/trunk/Documentation/ABI/testing/sysfs-class-uwb_rc deleted file mode 100644 index a0d18dbeb7a9..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-class-uwb_rc +++ /dev/null @@ -1,144 +0,0 @@ -What: /sys/class/uwb_rc -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - Interfaces for WiMedia Ultra Wideband Common Radio - Platform (UWB) radio controllers. - - Familiarity with the ECMA-368 'High Rate Ultra - Wideband MAC and PHY Specification' is assumed. - -What: /sys/class/uwb_rc/beacon_timeout_ms -Date: July 2008 -KernelVersion: 2.6.27 -Description: - If no beacons are received from a device for at least - this time, the device will be considered to have gone - and it will be removed. The default is 3 superframes - (~197 ms) as required by the specification. - -What: /sys/class/uwb_rc/uwbN/ -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - An individual UWB radio controller. - -What: /sys/class/uwb_rc/uwbN/beacon -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - Write: - - [] - - to start beaconing on a specific channel, or stop - beaconing if is -1. Valid channels depends - on the radio controller's supported band groups. - - may be used to try and join a specific - beacon group if more than one was found during a scan. - -What: /sys/class/uwb_rc/uwbN/scan -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - Write: - - [] - - to start (or stop) scanning on a channel. is one of: - 0 - scan - 1 - scan outside BP - 2 - scan while inactive - 3 - scanning disabled - 4 - scan (with start time of ) - -What: /sys/class/uwb_rc/uwbN/mac_address -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - The EUI-48, in colon-separated hex octets, for this - radio controller. A write will change the radio - controller's EUI-48 but only do so while the device is - not beaconing or scanning. - -What: /sys/class/uwb_rc/uwbN/wusbhc -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - A symlink to the device (if any) of the WUSB Host - Controller PAL using this radio controller. - -What: /sys/class/uwb_rc/uwbN// -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - A neighbour UWB device that has either been detected - as part of a scan or is a member of the radio - controllers beacon group. - -What: /sys/class/uwb_rc/uwbN//BPST -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - The time (using the radio controllers internal 1 ms - interval superframe timer) of the last beacon from - this device was received. - -What: /sys/class/uwb_rc/uwbN//DevAddr -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - The current DevAddr of this device in colon separated - hex octets. - -What: /sys/class/uwb_rc/uwbN//EUI_48 -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - - The EUI-48 of this device in colon separated hex - octets. - -What: /sys/class/uwb_rc/uwbN//BPST -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - -What: /sys/class/uwb_rc/uwbN//IEs -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - The latest IEs included in this device's beacon, in - space separated hex octets with one IE per line. - -What: /sys/class/uwb_rc/uwbN//LQE -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - Link Quality Estimate - the Signal to Noise Ratio - (SNR) of all packets received from this device in dB. - This gives an estimate on a suitable PHY rate. Refer - to [ECMA-368] section 13.3 for more details. - -What: /sys/class/uwb_rc/uwbN//RSSI -Date: July 2008 -KernelVersion: 2.6.27 -Contact: linux-usb@vger.kernel.org -Description: - Received Signal Strength Indication - the strength of - the received signal in dB. LQE is a more useful - measure of the radio link quality. diff --git a/trunk/Documentation/ABI/testing/sysfs-wusb_cbaf b/trunk/Documentation/ABI/testing/sysfs-wusb_cbaf deleted file mode 100644 index a99c5f86a37a..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-wusb_cbaf +++ /dev/null @@ -1,100 +0,0 @@ -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_* -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - Various files for managing Cable Based Association of - (wireless) USB devices. - - The sequence of operations should be: - - 1. Device is plugged in. - - 2. The connection manager (CM) sees a device with CBA capability. - (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE). - - 3. The CM writes the host name, supported band groups, - and the CHID (host ID) into the wusb_host_name, - wusb_host_band_groups and wusb_chid files. These - get sent to the device and the CDID (if any) for - this host is requested. - - 4. The CM can verify that the device's supported band - groups (wusb_device_band_groups) are compatible - with the host. - - 5. The CM reads the wusb_cdid file. - - 6. The CM looks it up its database. - - - If it has a matching CHID,CDID entry, the device - has been authorized before and nothing further - needs to be done. - - - If the CDID is zero (or the CM doesn't find a - matching CDID in its database), the device is - assumed to be not known. The CM may associate - the host with device by: writing a randomly - generated CDID to wusb_cdid and then a random CK - to wusb_ck (this uploads the new CC to the - device). - - CMD may choose to prompt the user before - associating with a new device. - - 7. Device is unplugged. - - References: - [WUSB-AM] Association Models Supplement to the - Certified Wireless Universal Serial Bus - Specification, version 1.0. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_chid -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The CHID of the host formatted as 16 space-separated - hex octets. - - Writes fetches device's supported band groups and the - the CDID for any existing association with this host. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_name -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - A friendly name for the host as a UTF-8 encoded string. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_host_band_groups -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The band groups supported by the host, in the format - defined in [WUSB-AM]. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_device_band_groups -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The band groups supported by the device, in the format - defined in [WUSB-AM]. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_cdid -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - The device's CDID formatted as 16 space-separated hex - octets. - -What: /sys/bus/usb/drivers/wusb_cbaf/.../wusb_ck -Date: August 2008 -KernelVersion: 2.6.27 -Contact: David Vrabel -Description: - Write 16 space-separated random, hex octets to - associate with the device. diff --git a/trunk/Documentation/DocBook/kernel-hacking.tmpl b/trunk/Documentation/DocBook/kernel-hacking.tmpl index ae15d55350ec..4c63e5864160 100644 --- a/trunk/Documentation/DocBook/kernel-hacking.tmpl +++ b/trunk/Documentation/DocBook/kernel-hacking.tmpl @@ -1105,7 +1105,7 @@ static struct block_device_operations opt_fops = { - Function names as strings (__func__). + Function names as strings (__FUNCTION__). diff --git a/trunk/Documentation/ia64/xen.txt b/trunk/Documentation/ia64/xen.txt deleted file mode 100644 index c61a99f7c8bb..000000000000 --- a/trunk/Documentation/ia64/xen.txt +++ /dev/null @@ -1,183 +0,0 @@ - Recipe for getting/building/running Xen/ia64 with pv_ops - -------------------------------------------------------- - -This recipe describes how to get xen-ia64 source and build it, -and run domU with pv_ops. - -============ -Requirements -============ - - - python - - mercurial - it (aka "hg") is an open-source source code - management software. See the below. - http://www.selenic.com/mercurial/wiki/ - - git - - bridge-utils - -================================= -Getting and Building Xen and Dom0 -================================= - - My environment is; - Machine : Tiger4 - Domain0 OS : RHEL5 - DomainU OS : RHEL5 - - 1. Download source - # hg clone http://xenbits.xensource.com/ext/ia64/xen-unstable.hg - # cd xen-unstable.hg - # hg clone http://xenbits.xensource.com/ext/ia64/linux-2.6.18-xen.hg - - 2. # make world - - 3. # make install-tools - - 4. copy kernels and xen - # cp xen/xen.gz /boot/efi/efi/redhat/ - # cp build-linux-2.6.18-xen_ia64/vmlinux.gz \ - /boot/efi/efi/redhat/vmlinuz-2.6.18.8-xen - - 5. make initrd for Dom0/DomU - # make -C linux-2.6.18-xen.hg ARCH=ia64 modules_install \ - O=$(/bin/pwd)/build-linux-2.6.18-xen_ia64 - # mkinitrd -f /boot/efi/efi/redhat/initrd-2.6.18.8-xen.img \ - 2.6.18.8-xen --builtin mptspi --builtin mptbase \ - --builtin mptscsih --builtin uhci-hcd --builtin ohci-hcd \ - --builtin ehci-hcd - -================================ -Making a disk image for guest OS -================================ - - 1. make file - # dd if=/dev/zero of=/root/rhel5.img bs=1M seek=4096 count=0 - # mke2fs -F -j /root/rhel5.img - # mount -o loop /root/rhel5.img /mnt - # cp -ax /{dev,var,etc,usr,bin,sbin,lib} /mnt - # mkdir /mnt/{root,proc,sys,home,tmp} - - Note: You may miss some device files. If so, please create them - with mknod. Or you can use tar instead of cp. - - 2. modify DomU's fstab - # vi /mnt/etc/fstab - /dev/xvda1 / ext3 defaults 1 1 - none /dev/pts devpts gid=5,mode=620 0 0 - none /dev/shm tmpfs defaults 0 0 - none /proc proc defaults 0 0 - none /sys sysfs defaults 0 0 - - 3. modify inittab - set runlevel to 3 to avoid X trying to start - # vi /mnt/etc/inittab - id:3:initdefault: - Start a getty on the hvc0 console - X0:2345:respawn:/sbin/mingetty hvc0 - tty1-6 mingetty can be commented out - - 4. add hvc0 into /etc/securetty - # vi /mnt/etc/securetty (add hvc0) - - 5. umount - # umount /mnt - -FYI, virt-manager can also make a disk image for guest OS. -It's GUI tools and easy to make it. - -================== -Boot Xen & Domain0 -================== - - 1. replace elilo - elilo of RHEL5 can boot Xen and Dom0. - If you use old elilo (e.g RHEL4), please download from the below - http://elilo.sourceforge.net/cgi-bin/blosxom - and copy into /boot/efi/efi/redhat/ - # cp elilo-3.6-ia64.efi /boot/efi/efi/redhat/elilo.efi - - 2. modify elilo.conf (like the below) - # vi /boot/efi/efi/redhat/elilo.conf - prompt - timeout=20 - default=xen - relocatable - - image=vmlinuz-2.6.18.8-xen - label=xen - vmm=xen.gz - initrd=initrd-2.6.18.8-xen.img - read-only - append=" -- rhgb root=/dev/sda2" - -The append options before "--" are for xen hypervisor, -the options after "--" are for dom0. - -FYI, your machine may need console options like -"com1=19200,8n1 console=vga,com1". For example, -append="com1=19200,8n1 console=vga,com1 -- rhgb console=tty0 \ -console=ttyS0 root=/dev/sda2" - -===================================== -Getting and Building domU with pv_ops -===================================== - - 1. get pv_ops tree - # git clone http://people.valinux.co.jp/~yamahata/xen-ia64/linux-2.6-xen-ia64.git/ - - 2. git branch (if necessary) - # cd linux-2.6-xen-ia64/ - # git checkout -b your_branch origin/xen-ia64-domu-minimal-2008may19 - (Note: The current branch is xen-ia64-domu-minimal-2008may19. - But you would find the new branch. You can see with - "git branch -r" to get the branch lists. - http://people.valinux.co.jp/~yamahata/xen-ia64/for_eagl/linux-2.6-ia64-pv-ops.git/ - is also available. The tree is based on - git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6 test) - - - 3. copy .config for pv_ops of domU - # cp arch/ia64/configs/xen_domu_wip_defconfig .config - - 4. make kernel with pv_ops - # make oldconfig - # make - - 5. install the kernel and initrd - # cp vmlinux.gz /boot/efi/efi/redhat/vmlinuz-2.6-pv_ops-xenU - # make modules_install - # mkinitrd -f /boot/efi/efi/redhat/initrd-2.6-pv_ops-xenU.img \ - 2.6.26-rc3xen-ia64-08941-g1b12161 --builtin mptspi \ - --builtin mptbase --builtin mptscsih --builtin uhci-hcd \ - --builtin ohci-hcd --builtin ehci-hcd - -======================== -Boot DomainU with pv_ops -======================== - - 1. make config of DomU - # vi /etc/xen/rhel5 - kernel = "/boot/efi/efi/redhat/vmlinuz-2.6-pv_ops-xenU" - ramdisk = "/boot/efi/efi/redhat/initrd-2.6-pv_ops-xenU.img" - vcpus = 1 - memory = 512 - name = "rhel5" - disk = [ 'file:/root/rhel5.img,xvda1,w' ] - root = "/dev/xvda1 ro" - extra= "rhgb console=hvc0" - - 2. After boot xen and dom0, start xend - # /etc/init.d/xend start - ( In the debugging case, # XEND_DEBUG=1 xend trace_start ) - - 3. start domU - # xm create -c rhel5 - -========= -Reference -========= -- Wiki of Xen/IA64 upstream merge - http://wiki.xensource.com/xenwiki/XenIA64/UpstreamMerge - -Written by Akio Takebe on 28 May 2008 diff --git a/trunk/Documentation/kdump/kdump.txt b/trunk/Documentation/kdump/kdump.txt index 3f4bc840da8b..0705040531a5 100644 --- a/trunk/Documentation/kdump/kdump.txt +++ b/trunk/Documentation/kdump/kdump.txt @@ -109,8 +109,7 @@ There are two possible methods of using Kdump. 2) Or use the system kernel binary itself as dump-capture kernel and there is no need to build a separate dump-capture kernel. This is possible only with the architecutres which support a relocatable kernel. As - of today, i386, x86_64, ppc64 and ia64 architectures support relocatable - kernel. + of today, i386, x86_64 and ia64 architectures support relocatable kernel. Building a relocatable kernel is advantageous from the point of view that one does not have to build a second kernel for capturing the dump. But @@ -208,15 +207,8 @@ Dump-capture kernel config options (Arch Dependent, i386 and x86_64) Dump-capture kernel config options (Arch Dependent, ppc64) ---------------------------------------------------------- -1) Enable "Build a kdump crash kernel" support under "Kernel" options: - - CONFIG_CRASH_DUMP=y - -2) Enable "Build a relocatable kernel" support - - CONFIG_RELOCATABLE=y - - Make and install the kernel and its modules. +* Make and install the kernel and its modules. DO NOT add this kernel + to the boot loader configuration files. Dump-capture kernel config options (Arch Dependent, ia64) ---------------------------------------------------------- diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index 02ea9a971b8e..de4063cb4fdc 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -1917,8 +1917,6 @@ platforms are moved over to use the flattened-device-tree model. inverse clock polarity (CPOL) mode - spi-cpha - (optional) Empty property indicating device requires shifted clock phase (CPHA) mode - - spi-cs-high - (optional) Empty property indicating device requires - chip select active high SPI example for an MPC5200 SPI bus: spi@f00 { diff --git a/trunk/Documentation/powerpc/dts-bindings/fsl/board.txt b/trunk/Documentation/powerpc/dts-bindings/fsl/board.txt index 81a917ef96e9..74ae6f1cd2d6 100644 --- a/trunk/Documentation/powerpc/dts-bindings/fsl/board.txt +++ b/trunk/Documentation/powerpc/dts-bindings/fsl/board.txt @@ -2,13 +2,13 @@ Required properties: - - compatible : Should be "fsl,-bcsr" + - device_type : Should be "board-control" - reg : Offset and length of the register set for the device Example: bcsr@f8000000 { - compatible = "fsl,mpc8360mds-bcsr"; + device_type = "board-control"; reg = ; }; diff --git a/trunk/Documentation/usb/WUSB-Design-overview.txt b/trunk/Documentation/usb/WUSB-Design-overview.txt deleted file mode 100644 index 4c3d62c7843a..000000000000 --- a/trunk/Documentation/usb/WUSB-Design-overview.txt +++ /dev/null @@ -1,448 +0,0 @@ - -Linux UWB + Wireless USB + WiNET - - (C) 2005-2006 Intel Corporation - Inaky Perez-Gonzalez - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - - -Please visit http://bughost.org/thewiki/Design-overview.txt-1.8 for -updated content. - - * Design-overview.txt-1.8 - -This code implements a Ultra Wide Band stack for Linux, as well as -drivers for the the USB based UWB radio controllers defined in the -Wireless USB 1.0 specification (including Wireless USB host controller -and an Intel WiNET controller). - - 1. Introduction - 1. HWA: Host Wire adapters, your Wireless USB dongle - - 2. DWA: Device Wired Adaptor, a Wireless USB hub for wired - devices - 3. WHCI: Wireless Host Controller Interface, the PCI WUSB host - adapter - 2. The UWB stack - 1. Devices and hosts: the basic structure - - 2. Host Controller life cycle - - 3. On the air: beacons and enumerating the radio neighborhood - - 4. Device lists - 5. Bandwidth allocation - - 3. Wireless USB Host Controller drivers - - 4. Glossary - - - Introduction - -UWB is a wide-band communication protocol that is to serve also as the -low-level protocol for others (much like TCP sits on IP). Currently -these others are Wireless USB and TCP/IP, but seems Bluetooth and -Firewire/1394 are coming along. - -UWB uses a band from roughly 3 to 10 GHz, transmitting at a max of -~-41dB (or 0.074 uW/MHz--geography specific data is still being -negotiated w/ regulators, so watch for changes). That band is divided in -a bunch of ~1.5 GHz wide channels (or band groups) composed of three -subbands/subchannels (528 MHz each). Each channel is independent of each -other, so you could consider them different "busses". Initially this -driver considers them all a single one. - -Radio time is divided in 65536 us long /superframes/, each one divided -in 256 256us long /MASs/ (Media Allocation Slots), which are the basic -time/media allocation units for transferring data. At the beginning of -each superframe there is a Beacon Period (BP), where every device -transmit its beacon on a single MAS. The length of the BP depends on how -many devices are present and the length of their beacons. - -Devices have a MAC (fixed, 48 bit address) and a device (changeable, 16 -bit address) and send periodic beacons to advertise themselves and pass -info on what they are and do. They advertise their capabilities and a -bunch of other stuff. - -The different logical parts of this driver are: - - * - - *UWB*: the Ultra-Wide-Band stack -- manages the radio and - associated spectrum to allow for devices sharing it. Allows to - control bandwidth assingment, beaconing, scanning, etc - - * - - *WUSB*: the layer that sits on top of UWB to provide Wireless USB. - The Wireless USB spec defines means to control a UWB radio and to - do the actual WUSB. - - - HWA: Host Wire adapters, your Wireless USB dongle - -WUSB also defines a device called a Host Wire Adaptor (HWA), which in -mere terms is a USB dongle that enables your PC to have UWB and Wireless -USB. The Wireless USB Host Controller in a HWA looks to the host like a -[Wireless] USB controller connected via USB (!) - -The HWA itself is broken in two or three main interfaces: - - * - - *RC*: Radio control -- this implements an interface to the - Ultra-Wide-Band radio controller. The driver for this implements a - USB-based UWB Radio Controller to the UWB stack. - - * - - *HC*: the wireless USB host controller. It looks like a USB host - whose root port is the radio and the WUSB devices connect to it. - To the system it looks like a separate USB host. The driver (will) - implement a USB host controller (similar to UHCI, OHCI or EHCI) - for which the root hub is the radio...To reiterate: it is a USB - controller that is connected via USB instead of PCI. - - * - - *WINET*: some HW provide a WiNET interface (IP over UWB). This - package provides a driver for it (it looks like a network - interface, winetX). The driver detects when there is a link up for - their type and kick into gear. - - - DWA: Device Wired Adaptor, a Wireless USB hub for wired devices - -These are the complement to HWAs. They are a USB host for connecting -wired devices, but it is connected to your PC connected via Wireless -USB. To the system it looks like yet another USB host. To the untrained -eye, it looks like a hub that connects upstream wirelessly. - -We still offer no support for this; however, it should share a lot of -code with the HWA-RC driver; there is a bunch of factorization work that -has been done to support that in upcoming releases. - - - WHCI: Wireless Host Controller Interface, the PCI WUSB host adapter - -This is your usual PCI device that implements WHCI. Similar in concept -to EHCI, it allows your wireless USB devices (including DWAs) to connect -to your host via a PCI interface. As in the case of the HWA, it has a -Radio Control interface and the WUSB Host Controller interface per se. - -There is still no driver support for this, but will be in upcoming -releases. - - - The UWB stack - -The main mission of the UWB stack is to keep a tally of which devices -are in radio proximity to allow drivers to connect to them. As well, it -provides an API for controlling the local radio controllers (RCs from -now on), such as to start/stop beaconing, scan, allocate bandwidth, etc. - - - Devices and hosts: the basic structure - -The main building block here is the UWB device (struct uwb_dev). For -each device that pops up in radio presence (ie: the UWB host receives a -beacon from it) you get a struct uwb_dev that will show up in -/sys/class/uwb and in /sys/bus/uwb/devices. - -For each RC that is detected, a new struct uwb_rc is created. In turn, a -RC is also a device, so they also show in /sys/class/uwb and -/sys/bus/uwb/devices, but at the same time, only radio controllers show -up in /sys/class/uwb_rc. - - * - - [*] The reason for RCs being also devices is that not only we can - see them while enumerating the system device tree, but also on the - radio (their beacons and stuff), so the handling has to be - likewise to that of a device. - -Each RC driver is implemented by a separate driver that plugs into the -interface that the UWB stack provides through a struct uwb_rc_ops. The -spec creators have been nice enough to make the message format the same -for HWA and WHCI RCs, so the driver is really a very thin transport that -moves the requests from the UWB API to the device [/uwb_rc_ops->cmd()/] -and sends the replies and notifications back to the API -[/uwb_rc_neh_grok()/]. Notifications are handled to the UWB daemon, that -is chartered, among other things, to keep the tab of how the UWB radio -neighborhood looks, creating and destroying devices as they show up or -dissapear. - -Command execution is very simple: a command block is sent and a event -block or reply is expected back. For sending/receiving command/events, a -handle called /neh/ (Notification/Event Handle) is opened with -/uwb_rc_neh_open()/. - -The HWA-RC (USB dongle) driver (drivers/uwb/hwa-rc.c) does this job for -the USB connected HWA. Eventually, drivers/whci-rc.c will do the same -for the PCI connected WHCI controller. - - - Host Controller life cycle - -So let's say we connect a dongle to the system: it is detected and -firmware uploaded if needed [for Intel's i1480 -/drivers/uwb/ptc/usb.c:ptc_usb_probe()/] and then it is reenumerated. -Now we have a real HWA device connected and -/drivers/uwb/hwa-rc.c:hwarc_probe()/ picks it up, that will set up the -Wire-Adaptor environment and then suck it into the UWB stack's vision of -the world [/drivers/uwb/lc-rc.c:uwb_rc_add()/]. - - * - - [*] The stack should put a new RC to scan for devices - [/uwb_rc_scan()/] so it finds what's available around and tries to - connect to them, but this is policy stuff and should be driven - from user space. As of now, the operator is expected to do it - manually; see the release notes for documentation on the procedure. - -When a dongle is disconnected, /drivers/uwb/hwa-rc.c:hwarc_disconnect()/ -takes time of tearing everything down safely (or not...). - - - On the air: beacons and enumerating the radio neighborhood - -So assuming we have devices and we have agreed for a channel to connect -on (let's say 9), we put the new RC to beacon: - - * - - $ echo 9 0 > /sys/class/uwb_rc/uwb0/beacon - -Now it is visible. If there were other devices in the same radio channel -and beacon group (that's what the zero is for), the dongle's radio -control interface will send beacon notifications on its -notification/event endpoint (NEEP). The beacon notifications are part of -the event stream that is funneled into the API with -/drivers/uwb/neh.c:uwb_rc_neh_grok()/ and delivered to the UWBD, the UWB -daemon through a notification list. - -UWBD wakes up and scans the event list; finds a beacon and adds it to -the BEACON CACHE (/uwb_beca/). If he receives a number of beacons from -the same device, he considers it to be 'onair' and creates a new device -[/drivers/uwb/lc-dev.c:uwbd_dev_onair()/]. Similarly, when no beacons -are received in some time, the device is considered gone and wiped out -[uwbd calls periodically /uwb/beacon.c:uwb_beca_purge()/ that will purge -the beacon cache of dead devices]. - - - Device lists - -All UWB devices are kept in the list of the struct bus_type uwb_bus. - - - Bandwidth allocation - -The UWB stack maintains a local copy of DRP availability through -processing of incoming *DRP Availability Change* notifications. This -local copy is currently used to present the current bandwidth -availability to the user through the sysfs file -/sys/class/uwb_rc/uwbx/bw_avail. In the future the bandwidth -availability information will be used by the bandwidth reservation -routines. - -The bandwidth reservation routines are in progress and are thus not -present in the current release. When completed they will enable a user -to initiate DRP reservation requests through interaction with sysfs. DRP -reservation requests from remote UWB devices will also be handled. The -bandwidth management done by the UWB stack will include callbacks to the -higher layers will enable the higher layers to use the reservations upon -completion. [Note: The bandwidth reservation work is in progress and -subject to change.] - - - Wireless USB Host Controller drivers - -*WARNING* This section needs a lot of work! - -As explained above, there are three different types of HCs in the WUSB -world: HWA-HC, DWA-HC and WHCI-HC. - -HWA-HC and DWA-HC share that they are Wire-Adapters (USB or WUSB -connected controllers), and their transfer management system is almost -identical. So is their notification delivery system. - -HWA-HC and WHCI-HC share that they are both WUSB host controllers, so -they have to deal with WUSB device life cycle and maintenance, wireless -root-hub - -HWA exposes a Host Controller interface (HWA-HC 0xe0/02/02). This has -three endpoints (Notifications, Data Transfer In and Data Transfer -Out--known as NEP, DTI and DTO in the code). - -We reserve UWB bandwidth for our Wireless USB Cluster, create a Cluster -ID and tell the HC to use all that. Then we start it. This means the HC -starts sending MMCs. - - * - - The MMCs are blocks of data defined somewhere in the WUSB1.0 spec - that define a stream in the UWB channel time allocated for sending - WUSB IEs (host to device commands/notifications) and Device - Notifications (device initiated to host). Each host defines a - unique Wireless USB cluster through MMCs. Devices can connect to a - single cluster at the time. The IEs are Information Elements, and - among them are the bandwidth allocations that tell each device - when can they transmit or receive. - -Now it all depends on external stimuli. - -*New device connection* - -A new device pops up, it scans the radio looking for MMCs that give out -the existence of Wireless USB channels. Once one (or more) are found, -selects which one to connect to. Sends a /DN_Connect/ (device -notification connect) during the DNTS (Device Notification Time -Slot--announced in the MMCs - -HC picks the /DN_Connect/ out (nep module sends to notif.c for delivery -into /devconnect/). This process starts the authentication process for -the device. First we allocate a /fake port/ and assign an -unauthenticated address (128 to 255--what we really do is -0x80 | fake_port_idx). We fiddle with the fake port status and /khubd/ -sees a new connection, so he moves on to enable the fake port with a reset. - -So now we are in the reset path -- we know we have a non-yet enumerated -device with an unauthorized address; we ask user space to authenticate -(FIXME: not yet done, similar to bluetooth pairing), then we do the key -exchange (FIXME: not yet done) and issue a /set address 0/ to bring the -device to the default state. Device is authenticated. - -From here, the USB stack takes control through the usb_hcd ops. khubd -has seen the port status changes, as we have been toggling them. It will -start enumerating and doing transfers through usb_hcd->urb_enqueue() to -read descriptors and move our data. - -*Device life cycle and keep alives* - -Everytime there is a succesful transfer to/from a device, we update a -per-device activity timestamp. If not, every now and then we check and -if the activity timestamp gets old, we ping the device by sending it a -Keep Alive IE; it responds with a /DN_Alive/ pong during the DNTS (this -arrives to us as a notification through -devconnect.c:wusb_handle_dn_alive(). If a device times out, we -disconnect it from the system (cleaning up internal information and -toggling the bits in the fake hub port, which kicks khubd into removing -the rest of the stuff). - -This is done through devconnect:__wusb_check_devs(), which will scan the -device list looking for whom needs refreshing. - -If the device wants to disconnect, it will either die (ugly) or send a -/DN_Disconnect/ that will prompt a disconnection from the system. - -*Sending and receiving data* - -Data is sent and received through /Remote Pipes/ (rpipes). An rpipe is -/aimed/ at an endpoint in a WUSB device. This is the same for HWAs and -DWAs. - -Each HC has a number of rpipes and buffers that can be assigned to them; -when doing a data transfer (xfer), first the rpipe has to be aimed and -prepared (buffers assigned), then we can start queueing requests for -data in or out. - -Data buffers have to be segmented out before sending--so we send first a -header (segment request) and then if there is any data, a data buffer -immediately after to the DTI interface (yep, even the request). If our -buffer is bigger than the max segment size, then we just do multiple -requests. - -[This sucks, because doing USB scatter gatter in Linux is resource -intensive, if any...not that the current approach is not. It just has to -be cleaned up a lot :)]. - -If reading, we don't send data buffers, just the segment headers saying -we want to read segments. - -When the xfer is executed, we receive a notification that says data is -ready in the DTI endpoint (handled through -xfer.c:wa_handle_notif_xfer()). In there we read from the DTI endpoint a -descriptor that gives us the status of the transfer, its identification -(given when we issued it) and the segment number. If it was a data read, -we issue another URB to read into the destination buffer the chunk of -data coming out of the remote endpoint. Done, wait for the next guy. The -callbacks for the URBs issued from here are the ones that will declare -the xfer complete at some point and call it's callback. - -Seems simple, but the implementation is not trivial. - - * - - *WARNING* Old!! - -The main xfer descriptor, wa_xfer (equivalent to a URB) contains an -array of segments, tallys on segments and buffers and callback -information. Buried in there is a lot of URBs for executing the segments -and buffer transfers. - -For OUT xfers, there is an array of segments, one URB for each, another -one of buffer URB. When submitting, we submit URBs for segment request -1, buffer 1, segment 2, buffer 2...etc. Then we wait on the DTI for xfer -result data; when all the segments are complete, we call the callback to -finalize the transfer. - -For IN xfers, we only issue URBs for the segments we want to read and -then wait for the xfer result data. - -*URB mapping into xfers* - -This is done by hwahc_op_urb_[en|de]queue(). In enqueue() we aim an -rpipe to the endpoint where we have to transmit, create a transfer -context (wa_xfer) and submit it. When the xfer is done, our callback is -called and we assign the status bits and release the xfer resources. - -In dequeue() we are basically cancelling/aborting the transfer. We issue -a xfer abort request to the HC, cancell all the URBs we had submitted -and not yet done and when all that is done, the xfer callback will be -called--this will call the URB callback. - - - Glossary - -*DWA* -- Device Wire Adapter - -USB host, wired for downstream devices, upstream connects wirelessly -with Wireless USB. - -*EVENT* -- Response to a command on the NEEP - -*HWA* -- Host Wire Adapter / USB dongle for UWB and Wireless USB - -*NEH* -- Notification/Event Handle - -Handle/file descriptor for receiving notifications or events. The WA -code requires you to get one of this to listen for notifications or -events on the NEEP. - -*NEEP* -- Notification/Event EndPoint - -Stuff related to the management of the first endpoint of a HWA USB -dongle that is used to deliver an stream of events and notifications to -the host. - -*NOTIFICATION* -- Message coming in the NEEP as response to something. - -*RC* -- Radio Control - -Design-overview.txt-1.8 (last edited 2006-11-04 12:22:24 by -InakyPerezGonzalez) - diff --git a/trunk/Documentation/usb/wusb-cbaf b/trunk/Documentation/usb/wusb-cbaf deleted file mode 100644 index 2e78b70f3adc..000000000000 --- a/trunk/Documentation/usb/wusb-cbaf +++ /dev/null @@ -1,139 +0,0 @@ -#! /bin/bash -# - -set -e - -progname=$(basename $0) -function help -{ - cat < $uwb_rc/beacon - echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2 - fi - echo $host_CHID > $dev/wusb_chid - echo I: started host $(basename $dev) >&2 - done - ;; - stop) - for dev in ${2:-$hdevs} - do - echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid - echo I: stopped host $(basename $dev) >&2 - uwb_rc=$(readlink -f $dev/uwb_rc) - echo -1 | cat > $uwb_rc/beacon - echo I: stopped beaconing on $(basename $uwb_rc) >&2 - done - ;; - set-chid) - shift - for dev in ${2:-$devs}; do - echo "${4:-$host_name}" > $dev/wusb_host_name - echo "${3:-$host_band_group}" > $dev/wusb_host_band_groups - echo ${2:-$host_CHID} > $dev/wusb_chid - done - ;; - get-cdid) - for dev in ${2:-$devs} - do - cat $dev/wusb_cdid - done - ;; - set-cc) - for dev in ${2:-$devs}; do - shift - CDID="$(head --bytes=16 /dev/urandom | od -tx1 -An)" - CK="$(head --bytes=16 /dev/urandom | od -tx1 -An)" - echo "$CDID" > $dev/wusb_cdid - echo "$CK" > $dev/wusb_ck - - echo I: CC set >&2 - echo "CHID: $(cat $dev/wusb_chid)" - echo "CDID:$CDID" - echo "CK: $CK" - done - ;; - help|h|--help|-h) - help - ;; - *) - echo "E: Unknown usage" 1>&2 - help 1>&2 - result=1 -esac -exit $result diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index a2afc494de4c..5c3f79c26384 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1053,12 +1053,6 @@ L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ S: Supported -CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: -P: David Vrabel -M: david.vrabel@csr.com -L: linux-usb@vger.kernel.org -S: Supported - CFAG12864B LCD DRIVER P: Miguel Ojeda Sandonis M: miguel.ojeda.sandonis@gmail.com @@ -2934,9 +2928,9 @@ S: Maintained NETEFFECT IWARP RNIC DRIVER (IW_NES) P: Faisal Latif -M: faisal.latif@intel.com +M: flatif@neteffect.com P: Chien Tung -M: chien.tin.tung@intel.com +M: ctung@neteffect.com L: general@lists.openfabrics.org W: http://www.neteffect.com S: Supported @@ -4197,12 +4191,6 @@ L: sparclinux@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git S: Maintained -ULTRA-WIDEBAND (UWB) SUBSYSTEM: -P: David Vrabel -M: david.vrabel@csr.com -L: linux-usb@vger.kernel.org -S: Supported - UNIFORM CDROM DRIVER P: Jens Axboe M: axboe@kernel.dk @@ -4628,11 +4616,6 @@ M: zaga@fly.cc.fer.hr L: linux-scsi@vger.kernel.org S: Maintained -WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM -P: David Vrabel -M: david.vrabel@csr.com -S: Maintained - WISTRON LAPTOP BUTTON DRIVER P: Miloslav Trmac M: mitr@volny.cz diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index f504c801792f..df39d20f7425 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -356,7 +356,7 @@ config ARCH_IXP4XX select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS - select DMABOUNCE if PCI + select ZONE_DMA if PCI help Support for Intel's IXP4XX (XScale) family of processors. @@ -1256,8 +1256,6 @@ source "drivers/hid/Kconfig" source "drivers/usb/Kconfig" -source "drivers/uwb/Kconfig" - source "drivers/mmc/Kconfig" source "drivers/memstick/Kconfig" diff --git a/trunk/arch/arm/common/Kconfig b/trunk/arch/arm/common/Kconfig index 86b5e6982660..2e32acca02fb 100644 --- a/trunk/arch/arm/common/Kconfig +++ b/trunk/arch/arm/common/Kconfig @@ -13,10 +13,10 @@ config ICST307 config SA1111 bool select DMABOUNCE if !ARCH_PXA + select ZONE_DMA if !ARCH_PXA config DMABOUNCE bool - select ZONE_DMA config TIMER_ACORN bool diff --git a/trunk/arch/arm/common/sa1111.c b/trunk/arch/arm/common/sa1111.c index 47ccec95f3e8..fb86f248aab8 100644 --- a/trunk/arch/arm/common/sa1111.c +++ b/trunk/arch/arm/common/sa1111.c @@ -581,7 +581,6 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, goto out; } -#ifdef CONFIG_DMABOUNCE /* * If the parent device has a DMA mask associated with it, * propagate it down to the children. @@ -599,7 +598,6 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, } } } -#endif out: return ret; @@ -939,7 +937,7 @@ static int sa1111_resume(struct platform_device *dev) #define sa1111_resume NULL #endif -static int __devinit sa1111_probe(struct platform_device *pdev) +static int sa1111_probe(struct platform_device *pdev) { struct resource *mem; int irq; diff --git a/trunk/arch/arm/configs/trizeps4_defconfig b/trunk/arch/arm/configs/trizeps4_defconfig index 9033d147f052..8b7a431a8bfc 100644 --- a/trunk/arch/arm/configs/trizeps4_defconfig +++ b/trunk/arch/arm/configs/trizeps4_defconfig @@ -147,7 +147,6 @@ CONFIG_ARCH_PXA=y # CONFIG_MACH_MAINSTONE is not set # CONFIG_ARCH_PXA_IDP is not set # CONFIG_PXA_SHARPSL is not set -CONFIG_TRIZEPS_PXA=y CONFIG_MACH_TRIZEPS4=y CONFIG_MACH_TRIZEPS4_CONXS=y # CONFIG_MACH_TRIZEPS4_ANY is not set diff --git a/trunk/arch/arm/mach-clps711x/include/mach/memory.h b/trunk/arch/arm/mach-clps711x/include/mach/memory.h index 98ec30c97bbe..71c2fa70c8e8 100644 --- a/trunk/arch/arm/mach-clps711x/include/mach/memory.h +++ b/trunk/arch/arm/mach-clps711x/include/mach/memory.h @@ -89,8 +89,6 @@ * node 3: 0xd8000000 - 0xdfffffff */ #define NODE_MEM_SIZE_BITS 24 -#define SECTION_SIZE_BITS 24 -#define MAX_PHYSMEM_BITS 32 #endif diff --git a/trunk/arch/arm/mach-iop13xx/include/mach/time.h b/trunk/arch/arm/mach-iop13xx/include/mach/time.h index d6d52527589d..49213d9d7cad 100644 --- a/trunk/arch/arm/mach-iop13xx/include/mach/time.h +++ b/trunk/arch/arm/mach-iop13xx/include/mach/time.h @@ -41,7 +41,7 @@ static inline unsigned long iop13xx_core_freq(void) return 1200000000; default: printk("%s: warning unknown frequency, defaulting to 800Mhz\n", - __func__); + __FUNCTION__); } return 800000000; @@ -60,7 +60,7 @@ static inline unsigned long iop13xx_xsi_bus_ratio(void) return 4; default: printk("%s: warning unknown ratio, defaulting to 2\n", - __func__); + __FUNCTION__); } return 2; diff --git a/trunk/arch/arm/mach-ixp4xx/Kconfig b/trunk/arch/arm/mach-ixp4xx/Kconfig index 2c5a02b8520e..db8b5fe06c0d 100644 --- a/trunk/arch/arm/mach-ixp4xx/Kconfig +++ b/trunk/arch/arm/mach-ixp4xx/Kconfig @@ -167,6 +167,11 @@ config MACH_GTWX5715 comment "IXP4xx Options" +config DMABOUNCE + bool + default y + depends on PCI + config IXP4XX_INDIRECT_PCI bool "Use indirect PCI memory access" depends on PCI diff --git a/trunk/arch/arm/mach-kirkwood/common.c b/trunk/arch/arm/mach-kirkwood/common.c index 0bb1fbd84ccb..85cad05d8c5b 100644 --- a/trunk/arch/arm/mach-kirkwood/common.c +++ b/trunk/arch/arm/mach-kirkwood/common.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -152,40 +151,6 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) } -/***************************************************************************** - * Ethernet switch - ****************************************************************************/ -static struct resource kirkwood_switch_resources[] = { - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device kirkwood_switch_device = { - .name = "dsa", - .id = 0, - .num_resources = 0, - .resource = kirkwood_switch_resources, -}; - -void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq) -{ - if (irq != NO_IRQ) { - kirkwood_switch_resources[0].start = irq; - kirkwood_switch_resources[0].end = irq; - kirkwood_switch_device.num_resources = 1; - } - - d->mii_bus = &kirkwood_ge00_shared.dev; - d->netdev = &kirkwood_ge00.dev; - kirkwood_switch_device.dev.platform_data = d; - - platform_device_register(&kirkwood_switch_device); -} - - /***************************************************************************** * SoC RTC ****************************************************************************/ diff --git a/trunk/arch/arm/mach-kirkwood/common.h b/trunk/arch/arm/mach-kirkwood/common.h index 5774632a67e3..8fa0f6a27635 100644 --- a/trunk/arch/arm/mach-kirkwood/common.h +++ b/trunk/arch/arm/mach-kirkwood/common.h @@ -11,7 +11,6 @@ #ifndef __ARCH_KIRKWOOD_COMMON_H #define __ARCH_KIRKWOOD_COMMON_H -struct dsa_platform_data; struct mv643xx_eth_platform_data; struct mv_sata_platform_data; @@ -30,7 +29,6 @@ void kirkwood_pcie_id(u32 *dev, u32 *rev); void kirkwood_ehci_init(void); void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data); -void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq); void kirkwood_pcie_init(void); void kirkwood_rtc_init(void); void kirkwood_sata_init(struct mv_sata_platform_data *sata_data); diff --git a/trunk/arch/arm/mach-kirkwood/rd88f6281-setup.c b/trunk/arch/arm/mach-kirkwood/rd88f6281-setup.c index 175054abd630..f785093e433f 100644 --- a/trunk/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/trunk/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -75,15 +74,6 @@ static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f6281_switch_data = { - .port_names[0] = "lan1", - .port_names[1] = "lan2", - .port_names[2] = "lan3", - .port_names[3] = "lan4", - .port_names[4] = "wan", - .port_names[5] = "cpu", -}; - static struct mv_sata_platform_data rd88f6281_sata_data = { .n_ports = 2, }; @@ -97,7 +87,6 @@ static void __init rd88f6281_init(void) kirkwood_ehci_init(); kirkwood_ge00_init(&rd88f6281_ge00_data); - kirkwood_ge00_switch_init(&rd88f6281_switch_data, NO_IRQ); kirkwood_rtc_init(); kirkwood_sata_init(&rd88f6281_sata_data); kirkwood_uart0_init(); diff --git a/trunk/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/trunk/arch/arm/mach-mv78xx0/db78x00-bp-setup.c index 2e285bbb7bbd..49f434c39eb7 100644 --- a/trunk/arch/arm/mach-mv78xx0/db78x00-bp-setup.c +++ b/trunk/arch/arm/mach-mv78xx0/db78x00-bp-setup.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -29,14 +28,10 @@ static struct mv643xx_eth_platform_data db78x00_ge01_data = { static struct mv643xx_eth_platform_data db78x00_ge10_data = { .phy_addr = MV643XX_ETH_PHY_NONE, - .speed = SPEED_1000, - .duplex = DUPLEX_FULL, }; static struct mv643xx_eth_platform_data db78x00_ge11_data = { .phy_addr = MV643XX_ETH_PHY_NONE, - .speed = SPEED_1000, - .duplex = DUPLEX_FULL, }; static struct mv_sata_platform_data db78x00_sata_data = { diff --git a/trunk/arch/arm/mach-orion5x/common.c b/trunk/arch/arm/mach-orion5x/common.c index 437065c25c9c..9625ef5975d0 100644 --- a/trunk/arch/arm/mach-orion5x/common.c +++ b/trunk/arch/arm/mach-orion5x/common.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -198,40 +197,6 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) } -/***************************************************************************** - * Ethernet switch - ****************************************************************************/ -static struct resource orion5x_switch_resources[] = { - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device orion5x_switch_device = { - .name = "dsa", - .id = 0, - .num_resources = 0, - .resource = orion5x_switch_resources, -}; - -void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq) -{ - if (irq != NO_IRQ) { - orion5x_switch_resources[0].start = irq; - orion5x_switch_resources[0].end = irq; - orion5x_switch_device.num_resources = 1; - } - - d->mii_bus = &orion5x_eth_shared.dev; - d->netdev = &orion5x_eth.dev; - orion5x_switch_device.dev.platform_data = d; - - platform_device_register(&orion5x_switch_device); -} - - /***************************************************************************** * I2C ****************************************************************************/ @@ -310,8 +275,7 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) * SPI ****************************************************************************/ static struct orion_spi_info orion5x_spi_plat_data = { - .tclk = 0, - .enable_clock_fix = 1, + .tclk = 0, }; static struct resource orion5x_spi_resources[] = { diff --git a/trunk/arch/arm/mach-orion5x/common.h b/trunk/arch/arm/mach-orion5x/common.h index a000c7c6ee96..1f8b2da676a5 100644 --- a/trunk/arch/arm/mach-orion5x/common.h +++ b/trunk/arch/arm/mach-orion5x/common.h @@ -1,7 +1,6 @@ #ifndef __ARCH_ORION5X_COMMON_H #define __ARCH_ORION5X_COMMON_H -struct dsa_platform_data; struct mv643xx_eth_platform_data; struct mv_sata_platform_data; @@ -30,7 +29,6 @@ void orion5x_setup_pcie_wa_win(u32 base, u32 size); void orion5x_ehci0_init(void); void orion5x_ehci1_init(void); void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data); -void orion5x_eth_switch_init(struct dsa_platform_data *d, int irq); void orion5x_i2c_init(void); void orion5x_sata_init(struct mv_sata_platform_data *sata_data); void orion5x_spi_init(void); diff --git a/trunk/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/trunk/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index 15f53235ee30..500cdadaf09c 100644 --- a/trunk/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/trunk/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -94,15 +93,6 @@ static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f5181l_fxo_switch_data = { - .port_names[0] = "lan2", - .port_names[1] = "lan1", - .port_names[2] = "wan", - .port_names[3] = "cpu", - .port_names[5] = "lan4", - .port_names[7] = "lan3", -}; - static void __init rd88f5181l_fxo_init(void) { /* @@ -117,7 +107,6 @@ static void __init rd88f5181l_fxo_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f5181l_fxo_eth_data); - orion5x_eth_switch_init(&rd88f5181l_fxo_switch_data, NO_IRQ); orion5x_uart0_init(); orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE, diff --git a/trunk/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/trunk/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index 8ad3934399d4..ebde81416499 100644 --- a/trunk/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/trunk/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -95,15 +94,6 @@ static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f5181l_ge_switch_data = { - .port_names[0] = "lan2", - .port_names[1] = "lan1", - .port_names[2] = "wan", - .port_names[3] = "cpu", - .port_names[5] = "lan4", - .port_names[7] = "lan3", -}; - static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = { I2C_BOARD_INFO("ds1338", 0x68), }; @@ -122,7 +112,6 @@ static void __init rd88f5181l_ge_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f5181l_ge_eth_data); - orion5x_eth_switch_init(&rd88f5181l_ge_switch_data, gpio_to_irq(8)); orion5x_i2c_init(); orion5x_uart0_init(); diff --git a/trunk/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/trunk/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c index 262e25e4dace..40e049539091 100644 --- a/trunk/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c +++ b/trunk/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -35,15 +34,6 @@ static struct mv643xx_eth_platform_data rd88f6183ap_ge_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f6183ap_ge_switch_data = { - .port_names[0] = "lan1", - .port_names[1] = "lan2", - .port_names[2] = "lan3", - .port_names[3] = "lan4", - .port_names[4] = "wan", - .port_names[5] = "cpu", -}; - static struct mtd_partition rd88f6183ap_ge_partitions[] = { { .name = "kernel", @@ -89,7 +79,6 @@ static void __init rd88f6183ap_ge_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f6183ap_ge_eth_data); - orion5x_eth_switch_init(&rd88f6183ap_ge_switch_data, gpio_to_irq(3)); spi_register_board_info(rd88f6183ap_ge_spi_slave_info, ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info)); orion5x_spi_init(); diff --git a/trunk/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/trunk/arch/arm/mach-orion5x/wrt350n-v2-setup.c index cc8f89200865..9a4fd5256462 100644 --- a/trunk/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/trunk/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -106,15 +105,6 @@ static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data wrt350n_v2_switch_data = { - .port_names[0] = "lan2", - .port_names[1] = "lan1", - .port_names[2] = "wan", - .port_names[3] = "cpu", - .port_names[5] = "lan3", - .port_names[7] = "lan4", -}; - static void __init wrt350n_v2_init(void) { /* @@ -129,7 +119,6 @@ static void __init wrt350n_v2_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&wrt350n_v2_eth_data); - orion5x_eth_switch_init(&wrt350n_v2_switch_data, NO_IRQ); orion5x_uart0_init(); orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE, diff --git a/trunk/arch/arm/mach-pxa/Kconfig b/trunk/arch/arm/mach-pxa/Kconfig index f781873431f3..f27f6b3d6e6f 100644 --- a/trunk/arch/arm/mach-pxa/Kconfig +++ b/trunk/arch/arm/mach-pxa/Kconfig @@ -257,6 +257,7 @@ config MACH_ARMCORE bool "CompuLab CM-X255/CM-X270 modules" select PXA27x select IWMMXT + select ZONE_DMA if PCI select PXA25x select PXA_SSP diff --git a/trunk/arch/arm/mach-pxa/include/mach/irqs.h b/trunk/arch/arm/mach-pxa/include/mach/irqs.h index 32bb4a2eb7f1..9c163e19ada9 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/irqs.h +++ b/trunk/arch/arm/mach-pxa/include/mach/irqs.h @@ -9,8 +9,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef __ASM_MACH_IRQS_H -#define __ASM_MACH_IRQS_H + #ifdef CONFIG_PXA_HAVE_ISA_IRQS #define PXA_ISA_IRQ(x) (x) @@ -265,5 +264,3 @@ #endif #endif /* CONFIG_PCI_HOST_ITE8152 */ - -#endif /* __ASM_MACH_IRQS_H */ diff --git a/trunk/arch/arm/mach-pxa/include/mach/spitz.h b/trunk/arch/arm/mach-pxa/include/mach/spitz.h index e8488dfb7e91..31ac26b55bc1 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/spitz.h +++ b/trunk/arch/arm/mach-pxa/include/mach/spitz.h @@ -142,7 +142,7 @@ #define SPITZ_SCP2_GPIO_BASE (NR_BUILTIN_GPIO + 12) #define SPITZ_GPIO_IR_ON (SPITZ_SCP2_GPIO_BASE + 0) -#define SPITZ_GPIO_AKIN_PULLUP (SPITZ_SCP2_GPIO_BASE + 1) +#define SPITZ_GPIO_AKIN_PULLUP (SPITZ_SCP2_GPIO_BASE + 1 #define SPITZ_GPIO_RESERVED_1 (SPITZ_SCP2_GPIO_BASE + 2) #define SPITZ_GPIO_RESERVED_2 (SPITZ_SCP2_GPIO_BASE + 3) #define SPITZ_GPIO_RESERVED_3 (SPITZ_SCP2_GPIO_BASE + 4) diff --git a/trunk/arch/arm/mach-pxa/include/mach/zylonite.h b/trunk/arch/arm/mach-pxa/include/mach/zylonite.h index bf6785adccf4..0d35ca04731e 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/zylonite.h +++ b/trunk/arch/arm/mach-pxa/include/mach/zylonite.h @@ -30,7 +30,7 @@ extern void zylonite_pxa300_init(void); static inline void zylonite_pxa300_init(void) { if (cpu_is_pxa300() || cpu_is_pxa310()) - panic("%s: PXA300/PXA310 not supported\n", __func__); + panic("%s: PXA300/PXA310 not supported\n", __FUNCTION__); } #endif @@ -40,7 +40,7 @@ extern void zylonite_pxa320_init(void); static inline void zylonite_pxa320_init(void) { if (cpu_is_pxa320()) - panic("%s: PXA320 not supported\n", __func__); + panic("%s: PXA320 not supported\n", __FUNCTION__); } #endif diff --git a/trunk/arch/arm/mach-pxa/pwm.c b/trunk/arch/arm/mach-pxa/pwm.c index 74e2ead8cee8..316cd986da5c 100644 --- a/trunk/arch/arm/mach-pxa/pwm.c +++ b/trunk/arch/arm/mach-pxa/pwm.c @@ -60,7 +60,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) do_div(c, 1000000000); period_cycles = c; - if (period_cycles < 1) + if (period_cycles < 0) period_cycles = 1; prescale = (period_cycles - 1) / 1024; pv = period_cycles / (prescale + 1) - 1; diff --git a/trunk/arch/arm/mach-pxa/trizeps4.c b/trunk/arch/arm/mach-pxa/trizeps4.c index a72e3add743c..a13dbf3c2c05 100644 --- a/trunk/arch/arm/mach-pxa/trizeps4.c +++ b/trunk/arch/arm/mach-pxa/trizeps4.c @@ -399,7 +399,7 @@ static void trizeps4_irda_transceiver_mode(struct device *dev, int mode) /* Switch mode */ if (mode & IR_SIRMODE) trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; /* Slow mode */ - else if (mode & IR_FIRMODE) + else if (mode & IR_FIRMODE) { trizeps_conxs_ircr |= ConXS_IRCR_MODE; /* Fast mode */ /* Switch power */ diff --git a/trunk/arch/arm/mach-s3c2443/clock.c b/trunk/arch/arm/mach-s3c2443/clock.c index f854e7385e3c..2f60bf6b8d43 100644 --- a/trunk/arch/arm/mach-s3c2443/clock.c +++ b/trunk/arch/arm/mach-s3c2443/clock.c @@ -1033,7 +1033,8 @@ void __init s3c2443_init_clocks(int xtal) fclk = pll / s3c2443_fclk_div(clkdiv0); hclk = s3c2443_prediv_getrate(&clk_prediv); - hclk /= s3c2443_get_hdiv(clkdiv0); + hclk = hclk / s3c2443_get_hdiv(clkdiv0); + hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1); pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); diff --git a/trunk/arch/arm/mm/cache-v4.S b/trunk/arch/arm/mm/cache-v4.S index 5786adf10040..33926c9fcda6 100644 --- a/trunk/arch/arm/mm/cache-v4.S +++ b/trunk/arch/arm/mm/cache-v4.S @@ -29,7 +29,7 @@ ENTRY(v4_flush_user_cache_all) * Clean and invalidate the entire cache. */ ENTRY(v4_flush_kern_cache_all) -#ifdef CONFIG_CPU_CP15 +#ifdef CPU_CP15 mov r0, #0 mcr p15, 0, r0, c7, c7, 0 @ flush ID cache mov pc, lr @@ -48,7 +48,7 @@ ENTRY(v4_flush_kern_cache_all) * - flags - vma_area_struct flags describing address space */ ENTRY(v4_flush_user_cache_range) -#ifdef CONFIG_CPU_CP15 +#ifdef CPU_CP15 mov ip, #0 mcreq p15, 0, ip, c7, c7, 0 @ flush ID cache mov pc, lr @@ -116,7 +116,7 @@ ENTRY(v4_dma_inv_range) * - end - virtual end address */ ENTRY(v4_dma_flush_range) -#ifdef CONFIG_CPU_CP15 +#ifdef CPU_CP15 mov r0, #0 mcr p15, 0, r0, c7, c7, 0 @ flush ID cache #endif diff --git a/trunk/arch/arm/plat-s3c24xx/pwm-clock.c b/trunk/arch/arm/plat-s3c24xx/pwm-clock.c index 3fad68a1e6bc..b8e854f1b1d5 100644 --- a/trunk/arch/arm/plat-s3c24xx/pwm-clock.c +++ b/trunk/arch/arm/plat-s3c24xx/pwm-clock.c @@ -315,7 +315,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) if (parent == s3c24xx_pwmclk_tclk(id)) bits = S3C2410_TCFG1_MUX_TCLK << shift; else if (parent == s3c24xx_pwmclk_tdiv(id)) - bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; + bits = clk_pwm_tdiv_bits(to_tdiv(clk)) << shift; else return -EINVAL; diff --git a/trunk/arch/arm/plat-s3c24xx/pwm.c b/trunk/arch/arm/plat-s3c24xx/pwm.c index ec56b88866c4..feb770f2e84e 100644 --- a/trunk/arch/arm/plat-s3c24xx/pwm.c +++ b/trunk/arch/arm/plat-s3c24xx/pwm.c @@ -56,7 +56,7 @@ static struct clk *clk_scaler[2]; } \ } -#define DEFINE_S3C_TIMER(_tmr_no, _irq) \ +#define DEFINE_TIMER(_tmr_no, _irq) \ .name = "s3c24xx-pwm", \ .id = _tmr_no, \ .num_resources = TIMER_RESOURCE_SIZE, \ @@ -67,11 +67,11 @@ static struct clk *clk_scaler[2]; */ struct platform_device s3c_device_timer[] = { - [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) }, - [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) }, - [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) }, - [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) }, - [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) }, + [0] = { DEFINE_TIMER(0, IRQ_TIMER0) }, + [1] = { DEFINE_TIMER(1, IRQ_TIMER1) }, + [2] = { DEFINE_TIMER(2, IRQ_TIMER2) }, + [3] = { DEFINE_TIMER(3, IRQ_TIMER3) }, + [4] = { DEFINE_TIMER(4, IRQ_TIMER4) }, }; static inline int pwm_is_tdiv(struct pwm_device *pwm) diff --git a/trunk/arch/cris/Kconfig b/trunk/arch/cris/Kconfig index b17aeea8d620..07335e719bf8 100644 --- a/trunk/arch/cris/Kconfig +++ b/trunk/arch/cris/Kconfig @@ -679,8 +679,6 @@ source "fs/Kconfig" source "drivers/usb/Kconfig" -source "drivers/uwb/Kconfig" - source "arch/cris/Kconfig.debug" source "security/Kconfig" diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 28f06fd9b7b7..bd1995403c67 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -216,8 +216,6 @@ source "drivers/hwmon/Kconfig" source "drivers/usb/Kconfig" -source "drivers/uwb/Kconfig" - endmenu source "fs/Kconfig" diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 27eec71429b0..912c57db2d21 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -23,7 +23,6 @@ config IA64 select HAVE_KRETPROBES select HAVE_DMA_ATTRS select HAVE_KVM - select HAVE_ARCH_TRACEHOOK default y help The Itanium Processor Family is Intel's 64-bit successor to @@ -111,33 +110,6 @@ config AUDIT_ARCH bool default y -menuconfig PARAVIRT_GUEST - bool "Paravirtualized guest support" - help - Say Y here to get to see options related to running Linux under - various hypervisors. This option alone does not add any kernel code. - - If you say N, all options in this submenu will be skipped and disabled. - -if PARAVIRT_GUEST - -config PARAVIRT - bool "Enable paravirtualization code" - depends on PARAVIRT_GUEST - default y - bool - default y - help - This changes the kernel so it can modify itself when it is run - under a hypervisor, potentially improving performance significantly - over full virtualization. However, when run without a hypervisor - the kernel is theoretically slower and slightly larger. - - -source "arch/ia64/xen/Kconfig" - -endif - choice prompt "System type" default IA64_GENERIC @@ -147,7 +119,6 @@ config IA64_GENERIC select NUMA select ACPI_NUMA select SWIOTLB - select PCI_MSI help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure @@ -155,13 +126,11 @@ config IA64_GENERIC generic For any supported IA-64 system DIG-compliant For DIG ("Developer's Interface Guide") compliant systems - DIG+Intel+IOMMU For DIG systems with Intel IOMMU HP-zx1/sx1000 For HP systems HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. SGI-SN2 For SGI Altix systems SGI-UV For SGI UV systems Ski-simulator For the HP simulator - Xen-domU For xen domU system If you don't know what to do, choose "generic". @@ -169,11 +138,6 @@ config IA64_DIG bool "DIG-compliant" select SWIOTLB -config IA64_DIG_VTD - bool "DIG+Intel+IOMMU" - select DMAR - select PCI_MSI - config IA64_HP_ZX1 bool "HP-zx1/sx1000" help @@ -217,10 +181,6 @@ config IA64_HP_SIM bool "Ski-simulator" select SWIOTLB -config IA64_XEN_GUEST - bool "Xen guest" - depends on XEN - endchoice choice @@ -623,16 +583,6 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pcmcia/Kconfig" -config DMAR - bool "Support for DMA Remapping Devices (EXPERIMENTAL)" - depends on IA64_GENERIC && ACPI && EXPERIMENTAL - help - DMA remapping (DMAR) devices support enables independent address - translations for Direct Memory Access (DMA) from devices. - These DMA remapping devices are reported via ACPI tables - and include PCI device scope covered by these DMA - remapping devices. - endmenu endif diff --git a/trunk/arch/ia64/Makefile b/trunk/arch/ia64/Makefile index 58a7e46affda..905d25b13d5a 100644 --- a/trunk/arch/ia64/Makefile +++ b/trunk/arch/ia64/Makefile @@ -53,15 +53,12 @@ libs-y += arch/ia64/lib/ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ -core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ -core-$(CONFIG_IA64_XEN_GUEST) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/ core-$(CONFIG_KVM) += arch/ia64/kvm/ -core-$(CONFIG_XEN) += arch/ia64/xen/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ diff --git a/trunk/arch/ia64/configs/generic_defconfig b/trunk/arch/ia64/configs/generic_defconfig index e05f9e1d3faa..9f483976228f 100644 --- a/trunk/arch/ia64/configs/generic_defconfig +++ b/trunk/arch/ia64/configs/generic_defconfig @@ -233,8 +233,6 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -# CONFIG_DMAR is not set - # # Power management and ACPI # diff --git a/trunk/arch/ia64/configs/tiger_defconfig b/trunk/arch/ia64/configs/tiger_defconfig index c522edf23c62..797acf9066c1 100644 --- a/trunk/arch/ia64/configs/tiger_defconfig +++ b/trunk/arch/ia64/configs/tiger_defconfig @@ -172,8 +172,6 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -# CONFIG_DMAR is not set - # # Power management and ACPI # diff --git a/trunk/arch/ia64/dig/Makefile b/trunk/arch/ia64/dig/Makefile index 5c0283830bd6..971cd7870dd4 100644 --- a/trunk/arch/ia64/dig/Makefile +++ b/trunk/arch/ia64/dig/Makefile @@ -6,9 +6,4 @@ # obj-y := setup.o -ifeq ($(CONFIG_DMAR), y) -obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o dig_vtd_iommu.o -else obj-$(CONFIG_IA64_GENERIC) += machvec.o -endif -obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o diff --git a/trunk/arch/ia64/dig/dig_vtd_iommu.c b/trunk/arch/ia64/dig/dig_vtd_iommu.c deleted file mode 100644 index 1c8a079017a3..000000000000 --- a/trunk/arch/ia64/dig/dig_vtd_iommu.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include - -void * -vtd_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t flags) -{ - return intel_alloc_coherent(dev, size, dma_handle, flags); -} -EXPORT_SYMBOL_GPL(vtd_alloc_coherent); - -void -vtd_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle) -{ - intel_free_coherent(dev, size, vaddr, dma_handle); -} -EXPORT_SYMBOL_GPL(vtd_free_coherent); - -dma_addr_t -vtd_map_single_attrs(struct device *dev, void *addr, size_t size, - int dir, struct dma_attrs *attrs) -{ - return intel_map_single(dev, (phys_addr_t)addr, size, dir); -} -EXPORT_SYMBOL_GPL(vtd_map_single_attrs); - -void -vtd_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, - int dir, struct dma_attrs *attrs) -{ - intel_unmap_single(dev, iova, size, dir); -} -EXPORT_SYMBOL_GPL(vtd_unmap_single_attrs); - -int -vtd_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, - int dir, struct dma_attrs *attrs) -{ - return intel_map_sg(dev, sglist, nents, dir); -} -EXPORT_SYMBOL_GPL(vtd_map_sg_attrs); - -void -vtd_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, - int nents, int dir, struct dma_attrs *attrs) -{ - intel_unmap_sg(dev, sglist, nents, dir); -} -EXPORT_SYMBOL_GPL(vtd_unmap_sg_attrs); - -int -vtd_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return 0; -} -EXPORT_SYMBOL_GPL(vtd_dma_mapping_error); diff --git a/trunk/arch/ia64/dig/machvec_vtd.c b/trunk/arch/ia64/dig/machvec_vtd.c deleted file mode 100644 index 7cd3eb471cad..000000000000 --- a/trunk/arch/ia64/dig/machvec_vtd.c +++ /dev/null @@ -1,3 +0,0 @@ -#define MACHVEC_PLATFORM_NAME dig_vtd -#define MACHVEC_PLATFORM_HEADER -#include diff --git a/trunk/arch/ia64/ia32/ia32_entry.S b/trunk/arch/ia64/ia32/ia32_entry.S index a8cf19958850..53505bb04771 100644 --- a/trunk/arch/ia64/ia32/ia32_entry.S +++ b/trunk/arch/ia64/ia32/ia32_entry.S @@ -108,11 +108,6 @@ GLOBAL_ENTRY(ia32_trace_syscall) ;; st8 [r2]=r3 // initialize return code to -ENOSYS br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args - cmp.lt p6,p0=r8,r0 // check tracehook - adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 - ;; -(p6) st8.spill [r2]=r8 // store return value in slot for r8 -(p6) br.spnt.few .ret4 .ret2: // Need to reload arguments (they may be changed by the tracing process) adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1 adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13 @@ -204,10 +199,10 @@ ia32_syscall_table: data8 sys_setuid /* 16-bit version */ data8 sys_getuid /* 16-bit version */ data8 compat_sys_stime /* 25 */ - data8 compat_sys_ptrace + data8 sys32_ptrace data8 sys32_alarm data8 sys_ni_syscall - data8 sys_pause + data8 sys32_pause data8 compat_sys_utime /* 30 */ data8 sys_ni_syscall /* old stty syscall holder */ data8 sys_ni_syscall /* old gtty syscall holder */ @@ -220,7 +215,7 @@ ia32_syscall_table: data8 sys_mkdir data8 sys_rmdir /* 40 */ data8 sys_dup - data8 sys_pipe + data8 sys32_pipe data8 compat_sys_times data8 sys_ni_syscall /* old prof syscall holder */ data8 sys32_brk /* 45 */ diff --git a/trunk/arch/ia64/ia32/sys_ia32.c b/trunk/arch/ia64/ia32/sys_ia32.c index 5e92ae00bdbb..f4430bb4bbdc 100644 --- a/trunk/arch/ia64/ia32/sys_ia32.c +++ b/trunk/arch/ia64/ia32/sys_ia32.c @@ -1098,6 +1098,21 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, return ret; } +asmlinkage long +sys32_pipe (int __user *fd) +{ + int retval; + int fds[2]; + + retval = do_pipe_flags(fds, 0); + if (retval) + goto out; + if (copy_to_user(fd, fds, sizeof(fds))) + retval = -EFAULT; + out: + return retval; +} + asmlinkage unsigned long sys32_alarm (unsigned int seconds) { @@ -1194,6 +1209,25 @@ sys32_waitpid (int pid, unsigned int *stat_addr, int options) return compat_sys_wait4(pid, stat_addr, options, NULL); } +static unsigned int +ia32_peek (struct task_struct *child, unsigned long addr, unsigned int *val) +{ + size_t copied; + unsigned int ret; + + copied = access_process_vm(child, addr, val, sizeof(*val), 0); + return (copied != sizeof(ret)) ? -EIO : 0; +} + +static unsigned int +ia32_poke (struct task_struct *child, unsigned long addr, unsigned int val) +{ + + if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) + return -EIO; + return 0; +} + /* * The order in which registers are stored in the ptrace regs structure */ @@ -1491,15 +1525,49 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __u return 0; } -long compat_arch_ptrace(struct task_struct *child, compat_long_t request, - compat_ulong_t caddr, compat_ulong_t cdata) +asmlinkage long +sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) { - unsigned long addr = caddr; - unsigned long data = cdata; - unsigned int tmp; + struct task_struct *child; + unsigned int value, tmp; long i, ret; + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = sys_ptrace(request, pid, addr, data); + goto out_tsk; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_tsk; + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: /* read word at location addr */ + ret = ia32_peek(child, addr, &value); + if (ret == 0) + ret = put_user(value, (unsigned int __user *) compat_ptr(data)); + else + ret = -EIO; + goto out_tsk; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: /* write the word at location addr */ + ret = ia32_poke(child, addr, data); + goto out_tsk; + case PTRACE_PEEKUSR: /* read word at addr in USER area */ ret = -EIO; if ((addr & 3) || addr > 17*sizeof(int)) @@ -1564,9 +1632,27 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, compat_ptr(data)); break; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) compat_ptr(data)); + break; + + case PTRACE_SYSCALL: /* continue, stop after next syscall */ + case PTRACE_CONT: /* restart after signal. */ + case PTRACE_KILL: + case PTRACE_SINGLESTEP: /* execute chile for one instruction */ + case PTRACE_DETACH: /* detach a process */ + ret = sys_ptrace(request, pid, addr, data); + break; + default: - return compat_ptrace_request(child, request, caddr, cdata); + ret = ptrace_request(child, request, addr, data); + break; + } + out_tsk: + put_task_struct(child); + out: + unlock_kernel(); return ret; } @@ -1617,6 +1703,14 @@ sys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32, return ret; } +asmlinkage int +sys32_pause (void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; +} + asmlinkage int sys32_msync (unsigned int start, unsigned int len, int flags) { diff --git a/trunk/arch/ia64/include/asm/break.h b/trunk/arch/ia64/include/asm/break.h index e90c40ec9edf..f03402039896 100644 --- a/trunk/arch/ia64/include/asm/break.h +++ b/trunk/arch/ia64/include/asm/break.h @@ -20,13 +20,4 @@ */ #define __IA64_BREAK_SYSCALL 0x100000 -/* - * Xen specific break numbers: - */ -#define __IA64_XEN_HYPERCALL 0x1000 -/* [__IA64_XEN_HYPERPRIVOP_START, __IA64_XEN_HYPERPRIVOP_MAX] is used - for xen hyperprivops */ -#define __IA64_XEN_HYPERPRIVOP_START 0x1 -#define __IA64_XEN_HYPERPRIVOP_MAX 0x1a - #endif /* _ASM_IA64_BREAK_H */ diff --git a/trunk/arch/ia64/include/asm/cacheflush.h b/trunk/arch/ia64/include/asm/cacheflush.h index c8ce2719fee8..afcfbda76e20 100644 --- a/trunk/arch/ia64/include/asm/cacheflush.h +++ b/trunk/arch/ia64/include/asm/cacheflush.h @@ -34,8 +34,6 @@ do { \ #define flush_dcache_mmap_unlock(mapping) do { } while (0) extern void flush_icache_range (unsigned long start, unsigned long end); -extern void clflush_cache_range(void *addr, int size); - #define flush_icache_user_range(vma, page, user_addr, len) \ do { \ diff --git a/trunk/arch/ia64/include/asm/device.h b/trunk/arch/ia64/include/asm/device.h index 41ab85d66f33..3db6daf7f251 100644 --- a/trunk/arch/ia64/include/asm/device.h +++ b/trunk/arch/ia64/include/asm/device.h @@ -10,9 +10,6 @@ struct dev_archdata { #ifdef CONFIG_ACPI void *acpi_handle; #endif -#ifdef CONFIG_DMAR - void *iommu; /* hook for IOMMU specific extension */ -#endif }; #endif /* _ASM_IA64_DEVICE_H */ diff --git a/trunk/arch/ia64/include/asm/dma-mapping.h b/trunk/arch/ia64/include/asm/dma-mapping.h index bbab7e2b0fc9..06ff1ba21465 100644 --- a/trunk/arch/ia64/include/asm/dma-mapping.h +++ b/trunk/arch/ia64/include/asm/dma-mapping.h @@ -7,49 +7,6 @@ */ #include #include -#include - -struct dma_mapping_ops { - int (*mapping_error)(struct device *dev, - dma_addr_t dma_addr); - void* (*alloc_coherent)(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp); - void (*free_coherent)(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - dma_addr_t (*map_single)(struct device *hwdev, unsigned long ptr, - size_t size, int direction); - void (*unmap_single)(struct device *dev, dma_addr_t addr, - size_t size, int direction); - void (*sync_single_for_cpu)(struct device *hwdev, - dma_addr_t dma_handle, size_t size, - int direction); - void (*sync_single_for_device)(struct device *hwdev, - dma_addr_t dma_handle, size_t size, - int direction); - void (*sync_single_range_for_cpu)(struct device *hwdev, - dma_addr_t dma_handle, unsigned long offset, - size_t size, int direction); - void (*sync_single_range_for_device)(struct device *hwdev, - dma_addr_t dma_handle, unsigned long offset, - size_t size, int direction); - void (*sync_sg_for_cpu)(struct device *hwdev, - struct scatterlist *sg, int nelems, - int direction); - void (*sync_sg_for_device)(struct device *hwdev, - struct scatterlist *sg, int nelems, - int direction); - int (*map_sg)(struct device *hwdev, struct scatterlist *sg, - int nents, int direction); - void (*unmap_sg)(struct device *hwdev, - struct scatterlist *sg, int nents, - int direction); - int (*dma_supported_op)(struct device *hwdev, u64 mask); - int is_phys; -}; - -extern struct dma_mapping_ops *dma_ops; -extern struct ia64_machine_vector ia64_mv; -extern void set_iommu_machvec(void); #define dma_alloc_coherent(dev, size, handle, gfp) \ platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA) @@ -139,11 +96,4 @@ dma_cache_sync (struct device *dev, void *vaddr, size_t size, #define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */ -static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) -{ - return dma_ops; -} - - - #endif /* _ASM_IA64_DMA_MAPPING_H */ diff --git a/trunk/arch/ia64/include/asm/iommu.h b/trunk/arch/ia64/include/asm/iommu.h deleted file mode 100644 index 5fb2bb93de3b..000000000000 --- a/trunk/arch/ia64/include/asm/iommu.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ASM_IA64_IOMMU_H -#define _ASM_IA64_IOMMU_H 1 - -#define cpu_has_x2apic 0 -/* 10 seconds */ -#define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) - -extern void pci_iommu_shutdown(void); -extern void no_iommu_init(void); -extern int force_iommu, no_iommu; -extern int iommu_detected; -extern void iommu_dma_init(void); -extern void machvec_init(const char *name); -extern int forbid_dac; - -#endif diff --git a/trunk/arch/ia64/include/asm/kregs.h b/trunk/arch/ia64/include/asm/kregs.h index 39e65f6639f5..aefcdfee7f23 100644 --- a/trunk/arch/ia64/include/asm/kregs.h +++ b/trunk/arch/ia64/include/asm/kregs.h @@ -32,7 +32,7 @@ #define IA64_TR_CURRENT_STACK 1 /* dtr1: maps kernel's memory- & register-stacks */ #define IA64_TR_ALLOC_BASE 2 /* itr&dtr: Base of dynamic TR resource*/ -#define IA64_TR_ALLOC_MAX 64 /* Max number for dynamic use*/ +#define IA64_TR_ALLOC_MAX 32 /* Max number for dynamic use*/ /* Processor status register bits: */ #define IA64_PSR_BE_BIT 1 diff --git a/trunk/arch/ia64/include/asm/machvec.h b/trunk/arch/ia64/include/asm/machvec.h index 1ea28bcee33b..2b850ccafef5 100644 --- a/trunk/arch/ia64/include/asm/machvec.h +++ b/trunk/arch/ia64/include/asm/machvec.h @@ -120,8 +120,6 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include # elif defined (CONFIG_IA64_DIG) # include -# elif defined(CONFIG_IA64_DIG_VTD) -# include # elif defined (CONFIG_IA64_HP_ZX1) # include # elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB) @@ -130,8 +128,6 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include # elif defined (CONFIG_IA64_SGI_UV) # include -# elif defined (CONFIG_IA64_XEN_GUEST) -# include # elif defined (CONFIG_IA64_GENERIC) # ifdef MACHVEC_PLATFORM_HEADER diff --git a/trunk/arch/ia64/include/asm/machvec_dig_vtd.h b/trunk/arch/ia64/include/asm/machvec_dig_vtd.h deleted file mode 100644 index 3400b561e711..000000000000 --- a/trunk/arch/ia64/include/asm/machvec_dig_vtd.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h -#define _ASM_IA64_MACHVEC_DIG_VTD_h - -extern ia64_mv_setup_t dig_setup; -extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent; -extern ia64_mv_dma_free_coherent vtd_free_coherent; -extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs; -extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs; -extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs; -extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs; -extern ia64_mv_dma_supported iommu_dma_supported; -extern ia64_mv_dma_mapping_error vtd_dma_mapping_error; -extern ia64_mv_dma_init pci_iommu_alloc; - -/* - * This stuff has dual use! - * - * For a generic kernel, the macros are used to initialize the - * platform's machvec structure. When compiling a non-generic kernel, - * the macros are used directly. - */ -#define platform_name "dig_vtd" -#define platform_setup dig_setup -#define platform_dma_init pci_iommu_alloc -#define platform_dma_alloc_coherent vtd_alloc_coherent -#define platform_dma_free_coherent vtd_free_coherent -#define platform_dma_map_single_attrs vtd_map_single_attrs -#define platform_dma_unmap_single_attrs vtd_unmap_single_attrs -#define platform_dma_map_sg_attrs vtd_map_sg_attrs -#define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs -#define platform_dma_sync_single_for_cpu machvec_dma_sync_single -#define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg -#define platform_dma_sync_single_for_device machvec_dma_sync_single -#define platform_dma_sync_sg_for_device machvec_dma_sync_sg -#define platform_dma_supported iommu_dma_supported -#define platform_dma_mapping_error vtd_dma_mapping_error - -#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */ diff --git a/trunk/arch/ia64/include/asm/machvec_init.h b/trunk/arch/ia64/include/asm/machvec_init.h index ef964b286842..7f21249fba3f 100644 --- a/trunk/arch/ia64/include/asm/machvec_init.h +++ b/trunk/arch/ia64/include/asm/machvec_init.h @@ -1,4 +1,3 @@ -#include #include extern ia64_mv_send_ipi_t ia64_send_ipi; diff --git a/trunk/arch/ia64/include/asm/machvec_xen.h b/trunk/arch/ia64/include/asm/machvec_xen.h deleted file mode 100644 index 55f9228056cd..000000000000 --- a/trunk/arch/ia64/include/asm/machvec_xen.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ASM_IA64_MACHVEC_XEN_h -#define _ASM_IA64_MACHVEC_XEN_h - -extern ia64_mv_setup_t dig_setup; -extern ia64_mv_cpu_init_t xen_cpu_init; -extern ia64_mv_irq_init_t xen_irq_init; -extern ia64_mv_send_ipi_t xen_platform_send_ipi; - -/* - * This stuff has dual use! - * - * For a generic kernel, the macros are used to initialize the - * platform's machvec structure. When compiling a non-generic kernel, - * the macros are used directly. - */ -#define platform_name "xen" -#define platform_setup dig_setup -#define platform_cpu_init xen_cpu_init -#define platform_irq_init xen_irq_init -#define platform_send_ipi xen_platform_send_ipi - -#endif /* _ASM_IA64_MACHVEC_XEN_h */ diff --git a/trunk/arch/ia64/include/asm/meminit.h b/trunk/arch/ia64/include/asm/meminit.h index 6bc96ee54327..7245a5781594 100644 --- a/trunk/arch/ia64/include/asm/meminit.h +++ b/trunk/arch/ia64/include/asm/meminit.h @@ -18,11 +18,10 @@ * - crash dumping code reserved region * - Kernel memory map built from EFI memory map * - ELF core header - * - xen start info if CONFIG_XEN * * More could be added if necessary */ -#define IA64_MAX_RSVD_REGIONS 9 +#define IA64_MAX_RSVD_REGIONS 8 struct rsvd_region { unsigned long start; /* virtual address of beginning of element */ diff --git a/trunk/arch/ia64/include/asm/native/inst.h b/trunk/arch/ia64/include/asm/native/inst.h index 0a1026cca4fa..c8efbf7b849e 100644 --- a/trunk/arch/ia64/include/asm/native/inst.h +++ b/trunk/arch/ia64/include/asm/native/inst.h @@ -36,13 +36,8 @@ ;; \ movl clob = PARAVIRT_POISON; \ ;; -# define CLOBBER_PRED(pred_clob) \ - ;; \ - cmp.eq pred_clob, p0 = r0, r0 \ - ;; #else -# define CLOBBER(clob) /* nothing */ -# define CLOBBER_PRED(pred_clob) /* nothing */ +# define CLOBBER(clob) /* nothing */ #endif #define MOV_FROM_IFA(reg) \ @@ -141,8 +136,7 @@ #define SSM_PSR_I(pred, pred_clob, clob) \ (pred) ssm psr.i \ - CLOBBER(clob) \ - CLOBBER_PRED(pred_clob) + CLOBBER(clob) #define RSM_PSR_I(pred, clob0, clob1) \ (pred) rsm psr.i \ diff --git a/trunk/arch/ia64/include/asm/native/pvchk_inst.h b/trunk/arch/ia64/include/asm/native/pvchk_inst.h deleted file mode 100644 index b8e6eb1090d7..000000000000 --- a/trunk/arch/ia64/include/asm/native/pvchk_inst.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef _ASM_NATIVE_PVCHK_INST_H -#define _ASM_NATIVE_PVCHK_INST_H - -/****************************************************************************** - * arch/ia64/include/asm/native/pvchk_inst.h - * Checker for paravirtualizations of privileged operations. - * - * Copyright (C) 2005 Hewlett-Packard Co - * Dan Magenheimer - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/********************************************** - * Instructions paravirtualized for correctness - **********************************************/ - -/* "fc" and "thash" are privilege-sensitive instructions, meaning they - * may have different semantics depending on whether they are executed - * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't - * be allowed to execute directly, lest incorrect semantics result. - */ - -#define fc .error "fc should not be used directly." -#define thash .error "thash should not be used directly." - -/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" - * is not currently used (though it may be in a long-format VHPT system!) - * and the semantics of cover only change if psr.ic is off which is very - * rare (and currently non-existent outside of assembly code - */ -#define ttag .error "ttag should not be used directly." -#define cover .error "cover should not be used directly." - -/* There are also privilege-sensitive registers. These registers are - * readable at any privilege level but only writable at PL0. - */ -#define cpuid .error "cpuid should not be used directly." -#define pmd .error "pmd should not be used directly." - -/* - * mov ar.eflag = - * mov = ar.eflag - */ - -/********************************************** - * Instructions paravirtualized for performance - **********************************************/ -/* - * Those instructions include '.' which can't be handled by cpp. - * or can't be handled by cpp easily. - * They are handled by sed instead of cpp. - */ - -/* for .S - * itc.i - * itc.d - * - * bsw.0 - * bsw.1 - * - * ssm psr.ic | PSR_DEFAULT_BITS - * ssm psr.ic - * rsm psr.ic - * ssm psr.i - * rsm psr.i - * rsm psr.i | psr.ic - * rsm psr.dt - * ssm psr.dt - * - * mov = cr.ifa - * mov = cr.itir - * mov = cr.isr - * mov = cr.iha - * mov = cr.ipsr - * mov = cr.iim - * mov = cr.iip - * mov = cr.ivr - * mov = psr - * - * mov cr.ifa = - * mov cr.itir = - * mov cr.iha = - * mov cr.ipsr = - * mov cr.ifs = - * mov cr.iip = - * mov cr.kr = - */ - -/* for intrinsics - * ssm psr.i - * rsm psr.i - * mov = psr - * mov = ivr - * mov = tpr - * mov cr.itm = - * mov eoi = - * mov rr[] = - * mov = rr[] - * mov = kr - * mov kr = - * ptc.ga - */ - -/************************************************************* - * define paravirtualized instrcution macros as nop to ingore. - * and check whether arguments are appropriate. - *************************************************************/ - -/* check whether reg is a regular register */ -.macro is_rreg_in reg - .ifc "\reg", "r0" - nop 0 - .exitm - .endif - ;; - mov \reg = r0 - ;; -.endm -#define IS_RREG_IN(reg) is_rreg_in reg ; - -#define IS_RREG_OUT(reg) \ - ;; \ - mov reg = r0 \ - ;; - -#define IS_RREG_CLOB(reg) IS_RREG_OUT(reg) - -/* check whether pred is a predicate register */ -#define IS_PRED_IN(pred) \ - ;; \ - (pred) nop 0 \ - ;; - -#define IS_PRED_OUT(pred) \ - ;; \ - cmp.eq pred, p0 = r0, r0 \ - ;; - -#define IS_PRED_CLOB(pred) IS_PRED_OUT(pred) - - -#define DO_SAVE_MIN(__COVER, SAVE_IFS, EXTRA, WORKAROUND) \ - nop 0 -#define MOV_FROM_IFA(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_ITIR(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_ISR(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_IHA(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_IPSR(pred, reg) \ - IS_PRED_IN(pred) \ - IS_RREG_OUT(reg) -#define MOV_FROM_IIM(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_IIP(reg) \ - IS_RREG_OUT(reg) -#define MOV_FROM_IVR(reg, clob) \ - IS_RREG_OUT(reg) \ - IS_RREG_CLOB(clob) -#define MOV_FROM_PSR(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_OUT(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_IFA(reg, clob) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_ITIR(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_IHA(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_IPSR(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_IFS(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_IIP(reg, clob) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define MOV_TO_KR(kr, reg, clob0, clob1) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) -#define ITC_I(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define ITC_D(pred, reg, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \ - IS_PRED_IN(pred_i) \ - IS_PRED_IN(pred_d) \ - IS_RREG_IN(reg) \ - IS_RREG_CLOB(clob) -#define THASH(pred, reg0, reg1, clob) \ - IS_PRED_IN(pred) \ - IS_RREG_OUT(reg0) \ - IS_RREG_IN(reg1) \ - IS_RREG_CLOB(clob) -#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) -#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) -#define RSM_PSR_IC(clob) \ - IS_RREG_CLOB(clob) -#define SSM_PSR_I(pred, pred_clob, clob) \ - IS_PRED_IN(pred) \ - IS_PRED_CLOB(pred_clob) \ - IS_RREG_CLOB(clob) -#define RSM_PSR_I(pred, clob0, clob1) \ - IS_PRED_IN(pred) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) -#define RSM_PSR_I_IC(clob0, clob1, clob2) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) \ - IS_RREG_CLOB(clob2) -#define RSM_PSR_DT \ - nop 0 -#define SSM_PSR_DT_AND_SRLZ_I \ - nop 0 -#define BSW_0(clob0, clob1, clob2) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) \ - IS_RREG_CLOB(clob2) -#define BSW_1(clob0, clob1) \ - IS_RREG_CLOB(clob0) \ - IS_RREG_CLOB(clob1) -#define COVER \ - nop 0 -#define RFI \ - br.ret.sptk.many rp /* defining nop causes dependency error */ - -#endif /* _ASM_NATIVE_PVCHK_INST_H */ diff --git a/trunk/arch/ia64/include/asm/paravirt.h b/trunk/arch/ia64/include/asm/paravirt.h index 2bf3636473fe..660cab044834 100644 --- a/trunk/arch/ia64/include/asm/paravirt.h +++ b/trunk/arch/ia64/include/asm/paravirt.h @@ -117,7 +117,7 @@ static inline void paravirt_post_smp_prepare_boot_cpu(void) struct pv_iosapic_ops { void (*pcat_compat_init)(void); - struct irq_chip *(*__get_irq_chip)(unsigned long trigger); + struct irq_chip *(*get_irq_chip)(unsigned long trigger); unsigned int (*__read)(char __iomem *iosapic, unsigned int reg); void (*__write)(char __iomem *iosapic, unsigned int reg, u32 val); @@ -135,7 +135,7 @@ iosapic_pcat_compat_init(void) static inline struct irq_chip* iosapic_get_irq_chip(unsigned long trigger) { - return pv_iosapic_ops.__get_irq_chip(trigger); + return pv_iosapic_ops.get_irq_chip(trigger); } static inline unsigned int diff --git a/trunk/arch/ia64/include/asm/pci.h b/trunk/arch/ia64/include/asm/pci.h index 1d660d89db0d..ce342fb74246 100644 --- a/trunk/arch/ia64/include/asm/pci.h +++ b/trunk/arch/ia64/include/asm/pci.h @@ -156,7 +156,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); } -#ifdef CONFIG_DMAR -extern void pci_iommu_alloc(void); -#endif #endif /* _ASM_IA64_PCI_H */ diff --git a/trunk/arch/ia64/include/asm/ptrace.h b/trunk/arch/ia64/include/asm/ptrace.h index 6417c1ecb44e..15f8dcfe6eee 100644 --- a/trunk/arch/ia64/include/asm/ptrace.h +++ b/trunk/arch/ia64/include/asm/ptrace.h @@ -240,12 +240,6 @@ struct switch_stack { */ # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri) -static inline unsigned long user_stack_pointer(struct pt_regs *regs) -{ - /* FIXME: should this be bspstore + nr_dirty regs? */ - return regs->ar_bspstore; -} - #define regs_return_value(regs) ((regs)->r8) /* Conserve space in histogram by encoding slot bits in address @@ -325,8 +319,6 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) #define arch_has_block_step() (1) extern void user_enable_block_step(struct task_struct *); -#define __ARCH_WANT_COMPAT_SYS_PTRACE - #endif /* !__KERNEL__ */ /* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */ diff --git a/trunk/arch/ia64/include/asm/pvclock-abi.h b/trunk/arch/ia64/include/asm/pvclock-abi.h deleted file mode 100644 index 44ef9ef8f5b3..000000000000 --- a/trunk/arch/ia64/include/asm/pvclock-abi.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * same structure to x86's - * Hopefully asm-x86/pvclock-abi.h would be moved to somewhere more generic. - * For now, define same duplicated definitions. - */ - -#ifndef _ASM_IA64__PVCLOCK_ABI_H -#define _ASM_IA64__PVCLOCK_ABI_H -#ifndef __ASSEMBLY__ - -/* - * These structs MUST NOT be changed. - * They are the ABI between hypervisor and guest OS. - * Both Xen and KVM are using this. - * - * pvclock_vcpu_time_info holds the system time and the tsc timestamp - * of the last update. So the guest can use the tsc delta to get a - * more precise system time. There is one per virtual cpu. - * - * pvclock_wall_clock references the point in time when the system - * time was zero (usually boot time), thus the guest calculates the - * current wall clock by adding the system time. - * - * Protocol for the "version" fields is: hypervisor raises it (making - * it uneven) before it starts updating the fields and raises it again - * (making it even) when it is done. Thus the guest can make sure the - * time values it got are consistent by checking the version before - * and after reading them. - */ - -struct pvclock_vcpu_time_info { - u32 version; - u32 pad0; - u64 tsc_timestamp; - u64 system_time; - u32 tsc_to_system_mul; - s8 tsc_shift; - u8 pad[3]; -} __attribute__((__packed__)); /* 32 bytes */ - -struct pvclock_wall_clock { - u32 version; - u32 sec; - u32 nsec; -} __attribute__((__packed__)); - -#endif /* __ASSEMBLY__ */ -#endif /* _ASM_IA64__PVCLOCK_ABI_H */ diff --git a/trunk/arch/ia64/include/asm/swiotlb.h b/trunk/arch/ia64/include/asm/swiotlb.h deleted file mode 100644 index fb79423834d0..000000000000 --- a/trunk/arch/ia64/include/asm/swiotlb.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ASM_IA64__SWIOTLB_H -#define ASM_IA64__SWIOTLB_H - -#include - -/* SWIOTLB interface */ - -extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, - size_t size, int dir); -extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, gfp_t flags); -extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_single_for_cpu(struct device *hwdev, - dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_single_for_device(struct device *hwdev, - dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev, - dma_addr_t dev_addr, - unsigned long offset, - size_t size, int dir); -extern void swiotlb_sync_single_range_for_device(struct device *hwdev, - dma_addr_t dev_addr, - unsigned long offset, - size_t size, int dir); -extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, - struct scatterlist *sg, int nelems, - int dir); -extern void swiotlb_sync_sg_for_device(struct device *hwdev, - struct scatterlist *sg, int nelems, - int dir); -extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, int direction); -extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, - int nents, int direction); -extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr); -extern void swiotlb_free_coherent(struct device *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle); -extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); -extern void swiotlb_init(void); - -extern int swiotlb_force; - -#ifdef CONFIG_SWIOTLB -extern int swiotlb; -extern void pci_swiotlb_init(void); -#else -#define swiotlb 0 -static inline void pci_swiotlb_init(void) -{ -} -#endif - -#endif /* ASM_IA64__SWIOTLB_H */ diff --git a/trunk/arch/ia64/include/asm/sync_bitops.h b/trunk/arch/ia64/include/asm/sync_bitops.h deleted file mode 100644 index 593c12eeb270..000000000000 --- a/trunk/arch/ia64/include/asm/sync_bitops.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _ASM_IA64_SYNC_BITOPS_H -#define _ASM_IA64_SYNC_BITOPS_H - -/* - * Copyright (C) 2008 Isaku Yamahata - * - * Based on synch_bitops.h which Dan Magenhaimer wrote. - * - * bit operations which provide guaranteed strong synchronisation - * when communicating with Xen or other guest OSes running on other CPUs. - */ - -static inline void sync_set_bit(int nr, volatile void *addr) -{ - set_bit(nr, addr); -} - -static inline void sync_clear_bit(int nr, volatile void *addr) -{ - clear_bit(nr, addr); -} - -static inline void sync_change_bit(int nr, volatile void *addr) -{ - change_bit(nr, addr); -} - -static inline int sync_test_and_set_bit(int nr, volatile void *addr) -{ - return test_and_set_bit(nr, addr); -} - -static inline int sync_test_and_clear_bit(int nr, volatile void *addr) -{ - return test_and_clear_bit(nr, addr); -} - -static inline int sync_test_and_change_bit(int nr, volatile void *addr) -{ - return test_and_change_bit(nr, addr); -} - -static inline int sync_test_bit(int nr, const volatile void *addr) -{ - return test_bit(nr, addr); -} - -#define sync_cmpxchg(ptr, old, new) \ - ((__typeof__(*(ptr)))cmpxchg_acq((ptr), (old), (new))) - -#endif /* _ASM_IA64_SYNC_BITOPS_H */ diff --git a/trunk/arch/ia64/include/asm/syscall.h b/trunk/arch/ia64/include/asm/syscall.h deleted file mode 100644 index 2f758a42f94b..000000000000 --- a/trunk/arch/ia64/include/asm/syscall.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Access to user system call parameters and results - * - * Copyright (C) 2008 Intel Corp. Shaohua Li - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. - * - * See asm-generic/syscall.h for descriptions of what we must do here. - */ - -#ifndef _ASM_SYSCALL_H -#define _ASM_SYSCALL_H 1 - -#include -#include - -static inline long syscall_get_nr(struct task_struct *task, - struct pt_regs *regs) -{ - if ((long)regs->cr_ifs < 0) /* Not a syscall */ - return -1; - -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - return regs->r1; -#endif - - return regs->r15; -} - -static inline void syscall_rollback(struct task_struct *task, - struct pt_regs *regs) -{ -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - regs->r8 = regs->r1; -#endif - - /* do nothing */ -} - -static inline long syscall_get_error(struct task_struct *task, - struct pt_regs *regs) -{ -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - return regs->r8; -#endif - - return regs->r10 == -1 ? regs->r8:0; -} - -static inline long syscall_get_return_value(struct task_struct *task, - struct pt_regs *regs) -{ - return regs->r8; -} - -static inline void syscall_set_return_value(struct task_struct *task, - struct pt_regs *regs, - int error, long val) -{ -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - regs->r8 = (long) error ? error : val; - return; - } -#endif - - if (error) { - /* error < 0, but ia64 uses > 0 return value */ - regs->r8 = -error; - regs->r10 = -1; - } else { - regs->r8 = val; - regs->r10 = 0; - } -} - -extern void ia64_syscall_get_set_arguments(struct task_struct *task, - struct pt_regs *regs, unsigned int i, unsigned int n, - unsigned long *args, int rw); -static inline void syscall_get_arguments(struct task_struct *task, - struct pt_regs *regs, - unsigned int i, unsigned int n, - unsigned long *args) -{ - BUG_ON(i + n > 6); - -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - switch (i + n) { - case 6: - if (!n--) break; - *args++ = regs->r13; - case 5: - if (!n--) break; - *args++ = regs->r15; - case 4: - if (!n--) break; - *args++ = regs->r14; - case 3: - if (!n--) break; - *args++ = regs->r10; - case 2: - if (!n--) break; - *args++ = regs->r9; - case 1: - if (!n--) break; - *args++ = regs->r11; - case 0: - if (!n--) break; - default: - BUG(); - break; - } - - return; - } -#endif - ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); -} - -static inline void syscall_set_arguments(struct task_struct *task, - struct pt_regs *regs, - unsigned int i, unsigned int n, - unsigned long *args) -{ - BUG_ON(i + n > 6); - -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - switch (i + n) { - case 6: - if (!n--) break; - regs->r13 = *args++; - case 5: - if (!n--) break; - regs->r15 = *args++; - case 4: - if (!n--) break; - regs->r14 = *args++; - case 3: - if (!n--) break; - regs->r10 = *args++; - case 2: - if (!n--) break; - regs->r9 = *args++; - case 1: - if (!n--) break; - regs->r11 = *args++; - case 0: - if (!n--) break; - } - - return; - } -#endif - ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); -} -#endif /* _ASM_SYSCALL_H */ diff --git a/trunk/arch/ia64/include/asm/thread_info.h b/trunk/arch/ia64/include/asm/thread_info.h index ae6922626bf4..7c60fcdd2efd 100644 --- a/trunk/arch/ia64/include/asm/thread_info.h +++ b/trunk/arch/ia64/include/asm/thread_info.h @@ -87,6 +87,9 @@ struct thread_info { #define alloc_task_struct() ((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER)) #define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER) +#define tsk_set_notify_resume(tsk) \ + set_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME) +extern void tsk_clear_notify_resume(struct task_struct *tsk); #endif /* !__ASSEMBLY */ /* diff --git a/trunk/arch/ia64/include/asm/timex.h b/trunk/arch/ia64/include/asm/timex.h index 4e03cfe74a0c..05a6baf8a472 100644 --- a/trunk/arch/ia64/include/asm/timex.h +++ b/trunk/arch/ia64/include/asm/timex.h @@ -39,6 +39,4 @@ get_cycles (void) return ret; } -extern void ia64_cpu_local_tick (void); - #endif /* _ASM_IA64_TIMEX_H */ diff --git a/trunk/arch/ia64/include/asm/unistd.h b/trunk/arch/ia64/include/asm/unistd.h index f791576355ad..d535833aab5e 100644 --- a/trunk/arch/ia64/include/asm/unistd.h +++ b/trunk/arch/ia64/include/asm/unistd.h @@ -337,7 +337,6 @@ # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLD_GETRLIMIT # define __ARCH_WANT_SYS_OLDUMOUNT -# define __ARCH_WANT_SYS_PAUSE # define __ARCH_WANT_SYS_SIGPENDING # define __ARCH_WANT_SYS_SIGPROCMASK # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND diff --git a/trunk/arch/ia64/include/asm/xen/events.h b/trunk/arch/ia64/include/asm/xen/events.h deleted file mode 100644 index 73248781fba8..000000000000 --- a/trunk/arch/ia64/include/asm/xen/events.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/events.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef _ASM_IA64_XEN_EVENTS_H -#define _ASM_IA64_XEN_EVENTS_H - -enum ipi_vector { - XEN_RESCHEDULE_VECTOR, - XEN_IPI_VECTOR, - XEN_CMCP_VECTOR, - XEN_CPEP_VECTOR, - - XEN_NR_IPIS, -}; - -static inline int xen_irqs_disabled(struct pt_regs *regs) -{ - return !(ia64_psr(regs)->i); -} - -static inline void xen_do_IRQ(int irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs; - old_regs = set_irq_regs(regs); - irq_enter(); - __do_IRQ(irq); - irq_exit(); - set_irq_regs(old_regs); -} -#define irq_ctx_init(cpu) do { } while (0) - -#endif /* _ASM_IA64_XEN_EVENTS_H */ diff --git a/trunk/arch/ia64/include/asm/xen/grant_table.h b/trunk/arch/ia64/include/asm/xen/grant_table.h deleted file mode 100644 index 2b1fae0e2d11..000000000000 --- a/trunk/arch/ia64/include/asm/xen/grant_table.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/grant_table.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _ASM_IA64_XEN_GRANT_TABLE_H -#define _ASM_IA64_XEN_GRANT_TABLE_H - -struct vm_struct *xen_alloc_vm_area(unsigned long size); -void xen_free_vm_area(struct vm_struct *area); - -#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */ diff --git a/trunk/arch/ia64/include/asm/xen/hypercall.h b/trunk/arch/ia64/include/asm/xen/hypercall.h deleted file mode 100644 index 96fc62366aa4..000000000000 --- a/trunk/arch/ia64/include/asm/xen/hypercall.h +++ /dev/null @@ -1,265 +0,0 @@ -/****************************************************************************** - * hypercall.h - * - * Linux-specific hypervisor handling. - * - * Copyright (c) 2002-2004, K A Fraser - * - * 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; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _ASM_IA64_XEN_HYPERCALL_H -#define _ASM_IA64_XEN_HYPERCALL_H - -#include -#include -#include -#include -struct xencomm_handle; -extern unsigned long __hypercall(unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, - unsigned long a5, unsigned long cmd); - -/* - * Assembler stubs for hyper-calls. - */ - -#define _hypercall0(type, name) \ -({ \ - long __res; \ - __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\ - (type)__res; \ -}) - -#define _hypercall1(type, name, a1) \ -({ \ - long __res; \ - __res = __hypercall((unsigned long)a1, \ - 0, 0, 0, 0, __HYPERVISOR_##name); \ - (type)__res; \ -}) - -#define _hypercall2(type, name, a1, a2) \ -({ \ - long __res; \ - __res = __hypercall((unsigned long)a1, \ - (unsigned long)a2, \ - 0, 0, 0, __HYPERVISOR_##name); \ - (type)__res; \ -}) - -#define _hypercall3(type, name, a1, a2, a3) \ -({ \ - long __res; \ - __res = __hypercall((unsigned long)a1, \ - (unsigned long)a2, \ - (unsigned long)a3, \ - 0, 0, __HYPERVISOR_##name); \ - (type)__res; \ -}) - -#define _hypercall4(type, name, a1, a2, a3, a4) \ -({ \ - long __res; \ - __res = __hypercall((unsigned long)a1, \ - (unsigned long)a2, \ - (unsigned long)a3, \ - (unsigned long)a4, \ - 0, __HYPERVISOR_##name); \ - (type)__res; \ -}) - -#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ -({ \ - long __res; \ - __res = __hypercall((unsigned long)a1, \ - (unsigned long)a2, \ - (unsigned long)a3, \ - (unsigned long)a4, \ - (unsigned long)a5, \ - __HYPERVISOR_##name); \ - (type)__res; \ -}) - - -static inline int -xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, sched_op_new, cmd, arg); -} - -static inline long -HYPERVISOR_set_timer_op(u64 timeout) -{ - unsigned long timeout_hi = (unsigned long)(timeout >> 32); - unsigned long timeout_lo = (unsigned long)timeout; - return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); -} - -static inline int -xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list, - int nr_calls) -{ - return _hypercall2(int, multicall, call_list, nr_calls); -} - -static inline int -xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, memory_op, cmd, arg); -} - -static inline int -xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, event_channel_op, cmd, arg); -} - -static inline int -xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, xen_version, cmd, arg); -} - -static inline int -xencomm_arch_hypercall_console_io(int cmd, int count, - struct xencomm_handle *str) -{ - return _hypercall3(int, console_io, cmd, count, str); -} - -static inline int -xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, physdev_op, cmd, arg); -} - -static inline int -xencomm_arch_hypercall_grant_table_op(unsigned int cmd, - struct xencomm_handle *uop, - unsigned int count) -{ - return _hypercall3(int, grant_table_op, cmd, uop, count); -} - -int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); - -extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg); - -static inline int -xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg) -{ - return _hypercall2(int, callback_op, cmd, arg); -} - -static inline long -xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg) -{ - return _hypercall3(long, vcpu_op, cmd, cpu, arg); -} - -static inline int -HYPERVISOR_physdev_op(int cmd, void *arg) -{ - switch (cmd) { - case PHYSDEVOP_eoi: - return _hypercall1(int, ia64_fast_eoi, - ((struct physdev_eoi *)arg)->irq); - default: - return xencomm_hypercall_physdev_op(cmd, arg); - } -} - -static inline long -xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg) -{ - return _hypercall1(long, opt_feature, arg); -} - -/* for balloon driver */ -#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) - -/* Use xencomm to do hypercalls. */ -#define HYPERVISOR_sched_op xencomm_hypercall_sched_op -#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op -#define HYPERVISOR_callback_op xencomm_hypercall_callback_op -#define HYPERVISOR_multicall xencomm_hypercall_multicall -#define HYPERVISOR_xen_version xencomm_hypercall_xen_version -#define HYPERVISOR_console_io xencomm_hypercall_console_io -#define HYPERVISOR_memory_op xencomm_hypercall_memory_op -#define HYPERVISOR_suspend xencomm_hypercall_suspend -#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op -#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature - -/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */ -#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; }) - -static inline int -HYPERVISOR_shutdown( - unsigned int reason) -{ - struct sched_shutdown sched_shutdown = { - .reason = reason - }; - - int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); - - return rc; -} - -/* for netfront.c, netback.c */ -#define MULTI_UVMFLAGS_INDEX 0 /* XXX any value */ - -static inline void -MULTI_update_va_mapping( - struct multicall_entry *mcl, unsigned long va, - pte_t new_val, unsigned long flags) -{ - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->result = 0; -} - -static inline void -MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd, - void *uop, unsigned int count) -{ - mcl->op = __HYPERVISOR_grant_table_op; - mcl->args[0] = cmd; - mcl->args[1] = (unsigned long)uop; - mcl->args[2] = count; -} - -static inline void -MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req, - int count, int *success_count, domid_t domid) -{ - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)req; - mcl->args[1] = count; - mcl->args[2] = (unsigned long)success_count; - mcl->args[3] = domid; -} - -#endif /* _ASM_IA64_XEN_HYPERCALL_H */ diff --git a/trunk/arch/ia64/include/asm/xen/hypervisor.h b/trunk/arch/ia64/include/asm/xen/hypervisor.h deleted file mode 100644 index 7a804e80fc67..000000000000 --- a/trunk/arch/ia64/include/asm/xen/hypervisor.h +++ /dev/null @@ -1,89 +0,0 @@ -/****************************************************************************** - * hypervisor.h - * - * Linux-specific hypervisor handling. - * - * Copyright (c) 2002-2004, K A Fraser - * - * 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; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _ASM_IA64_XEN_HYPERVISOR_H -#define _ASM_IA64_XEN_HYPERVISOR_H - -#ifdef CONFIG_XEN - -#include -#include -#include /* to compile feature.c */ -#include /* to comiple xen-netfront.c */ -#include - -/* xen_domain_type is set before executing any C code by early_xen_setup */ -enum xen_domain_type { - XEN_NATIVE, - XEN_PV_DOMAIN, - XEN_HVM_DOMAIN, -}; - -extern enum xen_domain_type xen_domain_type; - -#define xen_domain() (xen_domain_type != XEN_NATIVE) -#define xen_pv_domain() (xen_domain_type == XEN_PV_DOMAIN) -#define xen_initial_domain() (xen_pv_domain() && \ - (xen_start_info->flags & SIF_INITDOMAIN)) -#define xen_hvm_domain() (xen_domain_type == XEN_HVM_DOMAIN) - -/* deprecated. remove this */ -#define is_running_on_xen() (xen_domain_type == XEN_PV_DOMAIN) - -extern struct shared_info *HYPERVISOR_shared_info; -extern struct start_info *xen_start_info; - -void __init xen_setup_vcpu_info_placement(void); -void force_evtchn_callback(void); - -/* for drivers/xen/balloon/balloon.c */ -#ifdef CONFIG_XEN_SCRUB_PAGES -#define scrub_pages(_p, _n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT) -#else -#define scrub_pages(_p, _n) ((void)0) -#endif - -/* For setup_arch() in arch/ia64/kernel/setup.c */ -void xen_ia64_enable_opt_feature(void); - -#else /* CONFIG_XEN */ - -#define xen_domain() (0) -#define xen_pv_domain() (0) -#define xen_initial_domain() (0) -#define xen_hvm_domain() (0) -#define is_running_on_xen() (0) /* deprecated. remove this */ -#endif - -#define is_initial_xendomain() (0) /* deprecated. remove this */ - -#endif /* _ASM_IA64_XEN_HYPERVISOR_H */ diff --git a/trunk/arch/ia64/include/asm/xen/inst.h b/trunk/arch/ia64/include/asm/xen/inst.h deleted file mode 100644 index 19c2ae1d878a..000000000000 --- a/trunk/arch/ia64/include/asm/xen/inst.h +++ /dev/null @@ -1,458 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/inst.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include - -#define ia64_ivt xen_ivt -#define DO_SAVE_MIN XEN_DO_SAVE_MIN - -#define __paravirt_switch_to xen_switch_to -#define __paravirt_leave_syscall xen_leave_syscall -#define __paravirt_work_processed_syscall xen_work_processed_syscall -#define __paravirt_leave_kernel xen_leave_kernel -#define __paravirt_pending_syscall_end xen_work_pending_syscall_end -#define __paravirt_work_processed_syscall_target \ - xen_work_processed_syscall - -#define MOV_FROM_IFA(reg) \ - movl reg = XSI_IFA; \ - ;; \ - ld8 reg = [reg] - -#define MOV_FROM_ITIR(reg) \ - movl reg = XSI_ITIR; \ - ;; \ - ld8 reg = [reg] - -#define MOV_FROM_ISR(reg) \ - movl reg = XSI_ISR; \ - ;; \ - ld8 reg = [reg] - -#define MOV_FROM_IHA(reg) \ - movl reg = XSI_IHA; \ - ;; \ - ld8 reg = [reg] - -#define MOV_FROM_IPSR(pred, reg) \ -(pred) movl reg = XSI_IPSR; \ - ;; \ -(pred) ld8 reg = [reg] - -#define MOV_FROM_IIM(reg) \ - movl reg = XSI_IIM; \ - ;; \ - ld8 reg = [reg] - -#define MOV_FROM_IIP(reg) \ - movl reg = XSI_IIP; \ - ;; \ - ld8 reg = [reg] - -.macro __MOV_FROM_IVR reg, clob - .ifc "\reg", "r8" - XEN_HYPER_GET_IVR - .exitm - .endif - .ifc "\clob", "r8" - XEN_HYPER_GET_IVR - ;; - mov \reg = r8 - .exitm - .endif - - mov \clob = r8 - ;; - XEN_HYPER_GET_IVR - ;; - mov \reg = r8 - ;; - mov r8 = \clob -.endm -#define MOV_FROM_IVR(reg, clob) __MOV_FROM_IVR reg, clob - -.macro __MOV_FROM_PSR pred, reg, clob - .ifc "\reg", "r8" - (\pred) XEN_HYPER_GET_PSR; - .exitm - .endif - .ifc "\clob", "r8" - (\pred) XEN_HYPER_GET_PSR - ;; - (\pred) mov \reg = r8 - .exitm - .endif - - (\pred) mov \clob = r8 - (\pred) XEN_HYPER_GET_PSR - ;; - (\pred) mov \reg = r8 - (\pred) mov r8 = \clob -.endm -#define MOV_FROM_PSR(pred, reg, clob) __MOV_FROM_PSR pred, reg, clob - - -#define MOV_TO_IFA(reg, clob) \ - movl clob = XSI_IFA; \ - ;; \ - st8 [clob] = reg \ - -#define MOV_TO_ITIR(pred, reg, clob) \ -(pred) movl clob = XSI_ITIR; \ - ;; \ -(pred) st8 [clob] = reg - -#define MOV_TO_IHA(pred, reg, clob) \ -(pred) movl clob = XSI_IHA; \ - ;; \ -(pred) st8 [clob] = reg - -#define MOV_TO_IPSR(pred, reg, clob) \ -(pred) movl clob = XSI_IPSR; \ - ;; \ -(pred) st8 [clob] = reg; \ - ;; - -#define MOV_TO_IFS(pred, reg, clob) \ -(pred) movl clob = XSI_IFS; \ - ;; \ -(pred) st8 [clob] = reg; \ - ;; - -#define MOV_TO_IIP(reg, clob) \ - movl clob = XSI_IIP; \ - ;; \ - st8 [clob] = reg - -.macro ____MOV_TO_KR kr, reg, clob0, clob1 - .ifc "\clob0", "r9" - .error "clob0 \clob0 must not be r9" - .endif - .ifc "\clob1", "r8" - .error "clob1 \clob1 must not be r8" - .endif - - .ifnc "\reg", "r9" - .ifnc "\clob1", "r9" - mov \clob1 = r9 - .endif - mov r9 = \reg - .endif - .ifnc "\clob0", "r8" - mov \clob0 = r8 - .endif - mov r8 = \kr - ;; - XEN_HYPER_SET_KR - - .ifnc "\reg", "r9" - .ifnc "\clob1", "r9" - mov r9 = \clob1 - .endif - .endif - .ifnc "\clob0", "r8" - mov r8 = \clob0 - .endif -.endm - -.macro __MOV_TO_KR kr, reg, clob0, clob1 - .ifc "\clob0", "r9" - ____MOV_TO_KR \kr, \reg, \clob1, \clob0 - .exitm - .endif - .ifc "\clob1", "r8" - ____MOV_TO_KR \kr, \reg, \clob1, \clob0 - .exitm - .endif - - ____MOV_TO_KR \kr, \reg, \clob0, \clob1 -.endm - -#define MOV_TO_KR(kr, reg, clob0, clob1) \ - __MOV_TO_KR IA64_KR_ ## kr, reg, clob0, clob1 - - -.macro __ITC_I pred, reg, clob - .ifc "\reg", "r8" - (\pred) XEN_HYPER_ITC_I - .exitm - .endif - .ifc "\clob", "r8" - (\pred) mov r8 = \reg - ;; - (\pred) XEN_HYPER_ITC_I - .exitm - .endif - - (\pred) mov \clob = r8 - (\pred) mov r8 = \reg - ;; - (\pred) XEN_HYPER_ITC_I - ;; - (\pred) mov r8 = \clob - ;; -.endm -#define ITC_I(pred, reg, clob) __ITC_I pred, reg, clob - -.macro __ITC_D pred, reg, clob - .ifc "\reg", "r8" - (\pred) XEN_HYPER_ITC_D - ;; - .exitm - .endif - .ifc "\clob", "r8" - (\pred) mov r8 = \reg - ;; - (\pred) XEN_HYPER_ITC_D - ;; - .exitm - .endif - - (\pred) mov \clob = r8 - (\pred) mov r8 = \reg - ;; - (\pred) XEN_HYPER_ITC_D - ;; - (\pred) mov r8 = \clob - ;; -.endm -#define ITC_D(pred, reg, clob) __ITC_D pred, reg, clob - -.macro __ITC_I_AND_D pred_i, pred_d, reg, clob - .ifc "\reg", "r8" - (\pred_i)XEN_HYPER_ITC_I - ;; - (\pred_d)XEN_HYPER_ITC_D - ;; - .exitm - .endif - .ifc "\clob", "r8" - mov r8 = \reg - ;; - (\pred_i)XEN_HYPER_ITC_I - ;; - (\pred_d)XEN_HYPER_ITC_D - ;; - .exitm - .endif - - mov \clob = r8 - mov r8 = \reg - ;; - (\pred_i)XEN_HYPER_ITC_I - ;; - (\pred_d)XEN_HYPER_ITC_D - ;; - mov r8 = \clob - ;; -.endm -#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \ - __ITC_I_AND_D pred_i, pred_d, reg, clob - -.macro __THASH pred, reg0, reg1, clob - .ifc "\reg0", "r8" - (\pred) mov r8 = \reg1 - (\pred) XEN_HYPER_THASH - .exitm - .endc - .ifc "\reg1", "r8" - (\pred) XEN_HYPER_THASH - ;; - (\pred) mov \reg0 = r8 - ;; - .exitm - .endif - .ifc "\clob", "r8" - (\pred) mov r8 = \reg1 - (\pred) XEN_HYPER_THASH - ;; - (\pred) mov \reg0 = r8 - ;; - .exitm - .endif - - (\pred) mov \clob = r8 - (\pred) mov r8 = \reg1 - (\pred) XEN_HYPER_THASH - ;; - (\pred) mov \reg0 = r8 - (\pred) mov r8 = \clob - ;; -.endm -#define THASH(pred, reg0, reg1, clob) __THASH pred, reg0, reg1, clob - -#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \ - mov clob0 = 1; \ - movl clob1 = XSI_PSR_IC; \ - ;; \ - st4 [clob1] = clob0 \ - ;; - -#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \ - ;; \ - srlz.d; \ - mov clob1 = 1; \ - movl clob0 = XSI_PSR_IC; \ - ;; \ - st4 [clob0] = clob1 - -#define RSM_PSR_IC(clob) \ - movl clob = XSI_PSR_IC; \ - ;; \ - st4 [clob] = r0; \ - ;; - -/* pred will be clobbered */ -#define MASK_TO_PEND_OFS (-1) -#define SSM_PSR_I(pred, pred_clob, clob) \ -(pred) movl clob = XSI_PSR_I_ADDR \ - ;; \ -(pred) ld8 clob = [clob] \ - ;; \ - /* if (pred) vpsr.i = 1 */ \ - /* if (pred) (vcpu->vcpu_info->evtchn_upcall_mask)=0 */ \ -(pred) st1 [clob] = r0, MASK_TO_PEND_OFS \ - ;; \ - /* if (vcpu->vcpu_info->evtchn_upcall_pending) */ \ -(pred) ld1 clob = [clob] \ - ;; \ -(pred) cmp.ne.unc pred_clob, p0 = clob, r0 \ - ;; \ -(pred_clob)XEN_HYPER_SSM_I /* do areal ssm psr.i */ - -#define RSM_PSR_I(pred, clob0, clob1) \ - movl clob0 = XSI_PSR_I_ADDR; \ - mov clob1 = 1; \ - ;; \ - ld8 clob0 = [clob0]; \ - ;; \ -(pred) st1 [clob0] = clob1 - -#define RSM_PSR_I_IC(clob0, clob1, clob2) \ - movl clob0 = XSI_PSR_I_ADDR; \ - movl clob1 = XSI_PSR_IC; \ - ;; \ - ld8 clob0 = [clob0]; \ - mov clob2 = 1; \ - ;; \ - /* note: clears both vpsr.i and vpsr.ic! */ \ - st1 [clob0] = clob2; \ - st4 [clob1] = r0; \ - ;; - -#define RSM_PSR_DT \ - XEN_HYPER_RSM_PSR_DT - -#define SSM_PSR_DT_AND_SRLZ_I \ - XEN_HYPER_SSM_PSR_DT - -#define BSW_0(clob0, clob1, clob2) \ - ;; \ - /* r16-r31 all now hold bank1 values */ \ - mov clob2 = ar.unat; \ - movl clob0 = XSI_BANK1_R16; \ - movl clob1 = XSI_BANK1_R16 + 8; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r16, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r17, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r18, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r19, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r20, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r21, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r22, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r23, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r24, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r25, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r26, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r27, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r28, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r29, 16; \ - ;; \ -.mem.offset 0, 0; st8.spill [clob0] = r30, 16; \ -.mem.offset 8, 0; st8.spill [clob1] = r31, 16; \ - ;; \ - mov clob1 = ar.unat; \ - movl clob0 = XSI_B1NAT; \ - ;; \ - st8 [clob0] = clob1; \ - mov ar.unat = clob2; \ - movl clob0 = XSI_BANKNUM; \ - ;; \ - st4 [clob0] = r0 - - - /* FIXME: THIS CODE IS NOT NaT SAFE! */ -#define XEN_BSW_1(clob) \ - mov clob = ar.unat; \ - movl r30 = XSI_B1NAT; \ - ;; \ - ld8 r30 = [r30]; \ - mov r31 = 1; \ - ;; \ - mov ar.unat = r30; \ - movl r30 = XSI_BANKNUM; \ - ;; \ - st4 [r30] = r31; \ - movl r30 = XSI_BANK1_R16; \ - movl r31 = XSI_BANK1_R16+8; \ - ;; \ - ld8.fill r16 = [r30], 16; \ - ld8.fill r17 = [r31], 16; \ - ;; \ - ld8.fill r18 = [r30], 16; \ - ld8.fill r19 = [r31], 16; \ - ;; \ - ld8.fill r20 = [r30], 16; \ - ld8.fill r21 = [r31], 16; \ - ;; \ - ld8.fill r22 = [r30], 16; \ - ld8.fill r23 = [r31], 16; \ - ;; \ - ld8.fill r24 = [r30], 16; \ - ld8.fill r25 = [r31], 16; \ - ;; \ - ld8.fill r26 = [r30], 16; \ - ld8.fill r27 = [r31], 16; \ - ;; \ - ld8.fill r28 = [r30], 16; \ - ld8.fill r29 = [r31], 16; \ - ;; \ - ld8.fill r30 = [r30]; \ - ld8.fill r31 = [r31]; \ - ;; \ - mov ar.unat = clob - -#define BSW_1(clob0, clob1) XEN_BSW_1(clob1) - - -#define COVER \ - XEN_HYPER_COVER - -#define RFI \ - XEN_HYPER_RFI; \ - dv_serialize_data diff --git a/trunk/arch/ia64/include/asm/xen/interface.h b/trunk/arch/ia64/include/asm/xen/interface.h deleted file mode 100644 index f00fab40854d..000000000000 --- a/trunk/arch/ia64/include/asm/xen/interface.h +++ /dev/null @@ -1,346 +0,0 @@ -/****************************************************************************** - * arch-ia64/hypervisor-if.h - * - * Guest OS interface to IA64 Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright by those who contributed. (in alphabetical order) - * - * Anthony Xu - * Eddie Dong - * Fred Yang - * Kevin Tian - * Alex Williamson - * Chris Wright - * Christian Limpach - * Dietmar Hahn - * Hollis Blanchard - * Isaku Yamahata - * Jan Beulich - * John Levon - * Kazuhiro Suzuki - * Keir Fraser - * Kouya Shimura - * Masaki Kanno - * Matt Chapman - * Matthew Chapman - * Samuel Thibault - * Tomonari Horikoshi - * Tristan Gingold - * Tsunehisa Doi - * Yutaka Ezaki - * Zhang Xin - * Zhang xiantao - * dan.magenheimer@hp.com - * ian.pratt@cl.cam.ac.uk - * michael.fetterman@cl.cam.ac.uk - */ - -#ifndef _ASM_IA64_XEN_INTERFACE_H -#define _ASM_IA64_XEN_INTERFACE_H - -#define __DEFINE_GUEST_HANDLE(name, type) \ - typedef struct { type *p; } __guest_handle_ ## name - -#define DEFINE_GUEST_HANDLE_STRUCT(name) \ - __DEFINE_GUEST_HANDLE(name, struct name) -#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) -#define GUEST_HANDLE(name) __guest_handle_ ## name -#define GUEST_HANDLE_64(name) GUEST_HANDLE(name) -#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) - -#ifndef __ASSEMBLY__ -/* Guest handles for primitive C types. */ -__DEFINE_GUEST_HANDLE(uchar, unsigned char); -__DEFINE_GUEST_HANDLE(uint, unsigned int); -__DEFINE_GUEST_HANDLE(ulong, unsigned long); -__DEFINE_GUEST_HANDLE(u64, unsigned long); -DEFINE_GUEST_HANDLE(char); -DEFINE_GUEST_HANDLE(int); -DEFINE_GUEST_HANDLE(long); -DEFINE_GUEST_HANDLE(void); - -typedef unsigned long xen_pfn_t; -DEFINE_GUEST_HANDLE(xen_pfn_t); -#define PRI_xen_pfn "lx" -#endif - -/* Arch specific VIRQs definition */ -#define VIRQ_ITC VIRQ_ARCH_0 /* V. Virtual itc timer */ -#define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */ -#define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */ - -/* Maximum number of virtual CPUs in multi-processor guests. */ -/* keep sizeof(struct shared_page) <= PAGE_SIZE. - * this is checked in arch/ia64/xen/hypervisor.c. */ -#define MAX_VIRT_CPUS 64 - -#ifndef __ASSEMBLY__ - -#define INVALID_MFN (~0UL) - -union vac { - unsigned long value; - struct { - int a_int:1; - int a_from_int_cr:1; - int a_to_int_cr:1; - int a_from_psr:1; - int a_from_cpuid:1; - int a_cover:1; - int a_bsw:1; - long reserved:57; - }; -}; - -union vdc { - unsigned long value; - struct { - int d_vmsw:1; - int d_extint:1; - int d_ibr_dbr:1; - int d_pmc:1; - int d_to_pmd:1; - int d_itm:1; - long reserved:58; - }; -}; - -struct mapped_regs { - union vac vac; - union vdc vdc; - unsigned long virt_env_vaddr; - unsigned long reserved1[29]; - unsigned long vhpi; - unsigned long reserved2[95]; - union { - unsigned long vgr[16]; - unsigned long bank1_regs[16]; /* bank1 regs (r16-r31) - when bank0 active */ - }; - union { - unsigned long vbgr[16]; - unsigned long bank0_regs[16]; /* bank0 regs (r16-r31) - when bank1 active */ - }; - unsigned long vnat; - unsigned long vbnat; - unsigned long vcpuid[5]; - unsigned long reserved3[11]; - unsigned long vpsr; - unsigned long vpr; - unsigned long reserved4[76]; - union { - unsigned long vcr[128]; - struct { - unsigned long dcr; /* CR0 */ - unsigned long itm; - unsigned long iva; - unsigned long rsv1[5]; - unsigned long pta; /* CR8 */ - unsigned long rsv2[7]; - unsigned long ipsr; /* CR16 */ - unsigned long isr; - unsigned long rsv3; - unsigned long iip; - unsigned long ifa; - unsigned long itir; - unsigned long iipa; - unsigned long ifs; - unsigned long iim; /* CR24 */ - unsigned long iha; - unsigned long rsv4[38]; - unsigned long lid; /* CR64 */ - unsigned long ivr; - unsigned long tpr; - unsigned long eoi; - unsigned long irr[4]; - unsigned long itv; /* CR72 */ - unsigned long pmv; - unsigned long cmcv; - unsigned long rsv5[5]; - unsigned long lrr0; /* CR80 */ - unsigned long lrr1; - unsigned long rsv6[46]; - }; - }; - union { - unsigned long reserved5[128]; - struct { - unsigned long precover_ifs; - unsigned long unat; /* not sure if this is needed - until NaT arch is done */ - int interrupt_collection_enabled; /* virtual psr.ic */ - - /* virtual interrupt deliverable flag is - * evtchn_upcall_mask in shared info area now. - * interrupt_mask_addr is the address - * of evtchn_upcall_mask for current vcpu - */ - unsigned char *interrupt_mask_addr; - int pending_interruption; - unsigned char vpsr_pp; - unsigned char vpsr_dfh; - unsigned char hpsr_dfh; - unsigned char hpsr_mfh; - unsigned long reserved5_1[4]; - int metaphysical_mode; /* 1 = use metaphys mapping - 0 = use virtual */ - int banknum; /* 0 or 1, which virtual - register bank is active */ - unsigned long rrs[8]; /* region registers */ - unsigned long krs[8]; /* kernel registers */ - unsigned long tmp[16]; /* temp registers - (e.g. for hyperprivops) */ - }; - }; -}; - -struct arch_vcpu_info { - /* nothing */ -}; - -/* - * This structure is used for magic page in domain pseudo physical address - * space and the result of XENMEM_machine_memory_map. - * As the XENMEM_machine_memory_map result, - * xen_memory_map::nr_entries indicates the size in bytes - * including struct xen_ia64_memmap_info. Not the number of entries. - */ -struct xen_ia64_memmap_info { - uint64_t efi_memmap_size; /* size of EFI memory map */ - uint64_t efi_memdesc_size; /* size of an EFI memory map - * descriptor */ - uint32_t efi_memdesc_version; /* memory descriptor version */ - void *memdesc[0]; /* array of efi_memory_desc_t */ -}; - -struct arch_shared_info { - /* PFN of the start_info page. */ - unsigned long start_info_pfn; - - /* Interrupt vector for event channel. */ - int evtchn_vector; - - /* PFN of memmap_info page */ - unsigned int memmap_info_num_pages; /* currently only = 1 case is - supported. */ - unsigned long memmap_info_pfn; - - uint64_t pad[31]; -}; - -struct xen_callback { - unsigned long ip; -}; -typedef struct xen_callback xen_callback_t; - -#endif /* !__ASSEMBLY__ */ - -/* Size of the shared_info area (this is not related to page size). */ -#define XSI_SHIFT 14 -#define XSI_SIZE (1 << XSI_SHIFT) -/* Log size of mapped_regs area (64 KB - only 4KB is used). */ -#define XMAPPEDREGS_SHIFT 12 -#define XMAPPEDREGS_SIZE (1 << XMAPPEDREGS_SHIFT) -/* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */ -#define XMAPPEDREGS_OFS XSI_SIZE - -/* Hyperprivops. */ -#define HYPERPRIVOP_START 0x1 -#define HYPERPRIVOP_RFI (HYPERPRIVOP_START + 0x0) -#define HYPERPRIVOP_RSM_DT (HYPERPRIVOP_START + 0x1) -#define HYPERPRIVOP_SSM_DT (HYPERPRIVOP_START + 0x2) -#define HYPERPRIVOP_COVER (HYPERPRIVOP_START + 0x3) -#define HYPERPRIVOP_ITC_D (HYPERPRIVOP_START + 0x4) -#define HYPERPRIVOP_ITC_I (HYPERPRIVOP_START + 0x5) -#define HYPERPRIVOP_SSM_I (HYPERPRIVOP_START + 0x6) -#define HYPERPRIVOP_GET_IVR (HYPERPRIVOP_START + 0x7) -#define HYPERPRIVOP_GET_TPR (HYPERPRIVOP_START + 0x8) -#define HYPERPRIVOP_SET_TPR (HYPERPRIVOP_START + 0x9) -#define HYPERPRIVOP_EOI (HYPERPRIVOP_START + 0xa) -#define HYPERPRIVOP_SET_ITM (HYPERPRIVOP_START + 0xb) -#define HYPERPRIVOP_THASH (HYPERPRIVOP_START + 0xc) -#define HYPERPRIVOP_PTC_GA (HYPERPRIVOP_START + 0xd) -#define HYPERPRIVOP_ITR_D (HYPERPRIVOP_START + 0xe) -#define HYPERPRIVOP_GET_RR (HYPERPRIVOP_START + 0xf) -#define HYPERPRIVOP_SET_RR (HYPERPRIVOP_START + 0x10) -#define HYPERPRIVOP_SET_KR (HYPERPRIVOP_START + 0x11) -#define HYPERPRIVOP_FC (HYPERPRIVOP_START + 0x12) -#define HYPERPRIVOP_GET_CPUID (HYPERPRIVOP_START + 0x13) -#define HYPERPRIVOP_GET_PMD (HYPERPRIVOP_START + 0x14) -#define HYPERPRIVOP_GET_EFLAG (HYPERPRIVOP_START + 0x15) -#define HYPERPRIVOP_SET_EFLAG (HYPERPRIVOP_START + 0x16) -#define HYPERPRIVOP_RSM_BE (HYPERPRIVOP_START + 0x17) -#define HYPERPRIVOP_GET_PSR (HYPERPRIVOP_START + 0x18) -#define HYPERPRIVOP_SET_RR0_TO_RR4 (HYPERPRIVOP_START + 0x19) -#define HYPERPRIVOP_MAX (0x1a) - -/* Fast and light hypercalls. */ -#define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1 - -/* Xencomm macros. */ -#define XENCOMM_INLINE_MASK 0xf800000000000000UL -#define XENCOMM_INLINE_FLAG 0x8000000000000000UL - -#ifndef __ASSEMBLY__ - -/* - * Optimization features. - * The hypervisor may do some special optimizations for guests. This hypercall - * can be used to switch on/of these special optimizations. - */ -#define __HYPERVISOR_opt_feature 0x700UL - -#define XEN_IA64_OPTF_OFF 0x0 -#define XEN_IA64_OPTF_ON 0x1 - -/* - * If this feature is switched on, the hypervisor inserts the - * tlb entries without calling the guests traphandler. - * This is useful in guests using region 7 for identity mapping - * like the linux kernel does. - */ -#define XEN_IA64_OPTF_IDENT_MAP_REG7 1 - -/* Identity mapping of region 4 addresses in HVM. */ -#define XEN_IA64_OPTF_IDENT_MAP_REG4 2 - -/* Identity mapping of region 5 addresses in HVM. */ -#define XEN_IA64_OPTF_IDENT_MAP_REG5 3 - -#define XEN_IA64_OPTF_IDENT_MAP_NOT_SET (0) - -struct xen_ia64_opt_feature { - unsigned long cmd; /* Which feature */ - unsigned char on; /* Switch feature on/off */ - union { - struct { - /* The page protection bit mask of the pte. - * This will be or'ed with the pte. */ - unsigned long pgprot; - unsigned long key; /* A protection key for itir.*/ - }; - }; -}; - -#endif /* __ASSEMBLY__ */ - -#endif /* _ASM_IA64_XEN_INTERFACE_H */ diff --git a/trunk/arch/ia64/include/asm/xen/irq.h b/trunk/arch/ia64/include/asm/xen/irq.h deleted file mode 100644 index a90450983003..000000000000 --- a/trunk/arch/ia64/include/asm/xen/irq.h +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/irq.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _ASM_IA64_XEN_IRQ_H -#define _ASM_IA64_XEN_IRQ_H - -/* - * The flat IRQ space is divided into two regions: - * 1. A one-to-one mapping of real physical IRQs. This space is only used - * if we have physical device-access privilege. This region is at the - * start of the IRQ space so that existing device drivers do not need - * to be modified to translate physical IRQ numbers into our IRQ space. - * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These - * are bound using the provided bind/unbind functions. - */ - -#define XEN_PIRQ_BASE 0 -#define XEN_NR_PIRQS 256 - -#define XEN_DYNIRQ_BASE (XEN_PIRQ_BASE + XEN_NR_PIRQS) -#define XEN_NR_DYNIRQS (NR_CPUS * 8) - -#define XEN_NR_IRQS (XEN_NR_PIRQS + XEN_NR_DYNIRQS) - -#endif /* _ASM_IA64_XEN_IRQ_H */ diff --git a/trunk/arch/ia64/include/asm/xen/minstate.h b/trunk/arch/ia64/include/asm/xen/minstate.h deleted file mode 100644 index 4d92d9bbda7b..000000000000 --- a/trunk/arch/ia64/include/asm/xen/minstate.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves - * the minimum state necessary that allows us to turn psr.ic back - * on. - * - * Assumed state upon entry: - * psr.ic: off - * r31: contains saved predicates (pr) - * - * Upon exit, the state is as follows: - * psr.ic: off - * r2 = points to &pt_regs.r16 - * r8 = contents of ar.ccv - * r9 = contents of ar.csd - * r10 = contents of ar.ssd - * r11 = FPSR_DEFAULT - * r12 = kernel sp (kernel virtual address) - * r13 = points to current task_struct (kernel virtual address) - * p15 = TRUE if psr.i is set in cr.ipsr - * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15: - * preserved - * CONFIG_XEN note: p6/p7 are not preserved - * - * Note that psr.ic is NOT turned on by this macro. This is so that - * we can pass interruption state as arguments to a handler. - */ -#define XEN_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \ - mov r16=IA64_KR(CURRENT); /* M */ \ - mov r27=ar.rsc; /* M */ \ - mov r20=r1; /* A */ \ - mov r25=ar.unat; /* M */ \ - MOV_FROM_IPSR(p0,r29); /* M */ \ - MOV_FROM_IIP(r28); /* M */ \ - mov r21=ar.fpsr; /* M */ \ - mov r26=ar.pfs; /* I */ \ - __COVER; /* B;; (or nothing) */ \ - adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ - ;; \ - ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \ - st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \ - adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \ - /* switch from user to kernel RBS: */ \ - ;; \ - invala; /* M */ \ - /* SAVE_IFS;*/ /* see xen special handling below */ \ - cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \ - ;; \ -(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ - ;; \ -(pUStk) mov.m r24=ar.rnat; \ -(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \ -(pKStk) mov r1=sp; /* get sp */ \ - ;; \ -(pUStk) lfetch.fault.excl.nt1 [r22]; \ -(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ -(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ - ;; \ -(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ -(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ - ;; \ -(pUStk) mov r18=ar.bsp; \ -(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ - adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \ - adds r16=PT(CR_IPSR),r1; \ - ;; \ - lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \ - st8 [r16]=r29; /* save cr.ipsr */ \ - ;; \ - lfetch.fault.excl.nt1 [r17]; \ - tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ - mov r29=b0 \ - ;; \ - WORKAROUND; \ - adds r16=PT(R8),r1; /* initialize first base pointer */ \ - adds r17=PT(R9),r1; /* initialize second base pointer */ \ -(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r8,16; \ -.mem.offset 8,0; st8.spill [r17]=r9,16; \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r10,24; \ - movl r8=XSI_PRECOVER_IFS; \ -.mem.offset 8,0; st8.spill [r17]=r11,24; \ - ;; \ - /* xen special handling for possibly lazy cover */ \ - /* SAVE_MIN case in dispatch_ia32_handler: mov r30=r0 */ \ - ld8 r30=[r8]; \ -(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \ - st8 [r16]=r28,16; /* save cr.iip */ \ - ;; \ - st8 [r17]=r30,16; /* save cr.ifs */ \ - mov r8=ar.ccv; \ - mov r9=ar.csd; \ - mov r10=ar.ssd; \ - movl r11=FPSR_DEFAULT; /* L-unit */ \ - ;; \ - st8 [r16]=r25,16; /* save ar.unat */ \ - st8 [r17]=r26,16; /* save ar.pfs */ \ - shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ - ;; \ - st8 [r16]=r27,16; /* save ar.rsc */ \ -(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \ -(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \ - ;; /* avoid RAW on r16 & r17 */ \ -(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \ - st8 [r17]=r31,16; /* save predicates */ \ -(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \ - ;; \ - st8 [r16]=r29,16; /* save b0 */ \ - st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ - cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ -.mem.offset 8,0; st8.spill [r17]=r12,16; \ - adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r13,16; \ -.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \ - mov r13=IA64_KR(CURRENT); /* establish `current' */ \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r15,16; \ -.mem.offset 8,0; st8.spill [r17]=r14,16; \ - ;; \ -.mem.offset 0,0; st8.spill [r16]=r2,16; \ -.mem.offset 8,0; st8.spill [r17]=r3,16; \ - ACCOUNT_GET_STAMP \ - adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ - ;; \ - EXTRA; \ - movl r1=__gp; /* establish kernel global pointer */ \ - ;; \ - ACCOUNT_SYS_ENTER \ - BSW_1(r3,r14); /* switch back to bank 1 (must be last in insn group) */ \ - ;; diff --git a/trunk/arch/ia64/include/asm/xen/page.h b/trunk/arch/ia64/include/asm/xen/page.h deleted file mode 100644 index 03441a780b5b..000000000000 --- a/trunk/arch/ia64/include/asm/xen/page.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/page.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _ASM_IA64_XEN_PAGE_H -#define _ASM_IA64_XEN_PAGE_H - -#define INVALID_P2M_ENTRY (~0UL) - -static inline unsigned long mfn_to_pfn(unsigned long mfn) -{ - return mfn; -} - -static inline unsigned long pfn_to_mfn(unsigned long pfn) -{ - return pfn; -} - -#define phys_to_machine_mapping_valid(_x) (1) - -static inline void *mfn_to_virt(unsigned long mfn) -{ - return __va(mfn << PAGE_SHIFT); -} - -static inline unsigned long virt_to_mfn(void *virt) -{ - return __pa(virt) >> PAGE_SHIFT; -} - -/* for tpmfront.c */ -static inline unsigned long virt_to_machine(void *virt) -{ - return __pa(virt); -} - -static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) -{ - /* nothing */ -} - -#define pte_mfn(_x) pte_pfn(_x) -#define mfn_pte(_x, _y) __pte_ma(0) /* unmodified use */ -#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ - -#endif /* _ASM_IA64_XEN_PAGE_H */ diff --git a/trunk/arch/ia64/include/asm/xen/privop.h b/trunk/arch/ia64/include/asm/xen/privop.h deleted file mode 100644 index 71ec7546e100..000000000000 --- a/trunk/arch/ia64/include/asm/xen/privop.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _ASM_IA64_XEN_PRIVOP_H -#define _ASM_IA64_XEN_PRIVOP_H - -/* - * Copyright (C) 2005 Hewlett-Packard Co - * Dan Magenheimer - * - * Paravirtualizations of privileged operations for Xen/ia64 - * - * - * inline privop and paravirt_alt support - * Copyright (c) 2007 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - */ - -#ifndef __ASSEMBLY__ -#include /* arch-ia64.h requires uint64_t */ -#endif -#include - -/* At 1 MB, before per-cpu space but still addressable using addl instead - of movl. */ -#define XSI_BASE 0xfffffffffff00000 - -/* Address of mapped regs. */ -#define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE) - -#ifdef __ASSEMBLY__ -#define XEN_HYPER_RFI break HYPERPRIVOP_RFI -#define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT -#define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT -#define XEN_HYPER_COVER break HYPERPRIVOP_COVER -#define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D -#define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I -#define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I -#define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR -#define XEN_HYPER_THASH break HYPERPRIVOP_THASH -#define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D -#define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR -#define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR -#define XEN_HYPER_SET_RR0_TO_RR4 break HYPERPRIVOP_SET_RR0_TO_RR4 - -#define XSI_IFS (XSI_BASE + XSI_IFS_OFS) -#define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS) -#define XSI_IFA (XSI_BASE + XSI_IFA_OFS) -#define XSI_ISR (XSI_BASE + XSI_ISR_OFS) -#define XSI_IIM (XSI_BASE + XSI_IIM_OFS) -#define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS) -#define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) -#define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS) -#define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS) -#define XSI_IIP (XSI_BASE + XSI_IIP_OFS) -#define XSI_B1NAT (XSI_BASE + XSI_B1NATS_OFS) -#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) -#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) -#define XSI_IHA (XSI_BASE + XSI_IHA_OFS) -#endif - -#ifndef __ASSEMBLY__ - -/************************************************/ -/* Instructions paravirtualized for correctness */ -/************************************************/ - -/* "fc" and "thash" are privilege-sensitive instructions, meaning they - * may have different semantics depending on whether they are executed - * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't - * be allowed to execute directly, lest incorrect semantics result. */ -extern void xen_fc(unsigned long addr); -extern unsigned long xen_thash(unsigned long addr); - -/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" - * is not currently used (though it may be in a long-format VHPT system!) - * and the semantics of cover only change if psr.ic is off which is very - * rare (and currently non-existent outside of assembly code */ - -/* There are also privilege-sensitive registers. These registers are - * readable at any privilege level but only writable at PL0. */ -extern unsigned long xen_get_cpuid(int index); -extern unsigned long xen_get_pmd(int index); - -extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ -extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ - -/************************************************/ -/* Instructions paravirtualized for performance */ -/************************************************/ - -/* Xen uses memory-mapped virtual privileged registers for access to many - * performance-sensitive privileged registers. Some, like the processor - * status register (psr), are broken up into multiple memory locations. - * Others, like "pend", are abstractions based on privileged registers. - * "Pend" is guaranteed to be set if reading cr.ivr would return a - * (non-spurious) interrupt. */ -#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) - -#define XSI_PSR_I \ - (*XEN_MAPPEDREGS->interrupt_mask_addr) -#define xen_get_virtual_psr_i() \ - (!XSI_PSR_I) -#define xen_set_virtual_psr_i(_val) \ - ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) -#define xen_set_virtual_psr_ic(_val) \ - ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) -#define xen_get_virtual_pend() \ - (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1)) - -/* Although all privileged operations can be left to trap and will - * be properly handled by Xen, some are frequent enough that we use - * hyperprivops for performance. */ -extern unsigned long xen_get_psr(void); -extern unsigned long xen_get_ivr(void); -extern unsigned long xen_get_tpr(void); -extern void xen_hyper_ssm_i(void); -extern void xen_set_itm(unsigned long); -extern void xen_set_tpr(unsigned long); -extern void xen_eoi(unsigned long); -extern unsigned long xen_get_rr(unsigned long index); -extern void xen_set_rr(unsigned long index, unsigned long val); -extern void xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1, - unsigned long val2, unsigned long val3, - unsigned long val4); -extern void xen_set_kr(unsigned long index, unsigned long val); -extern void xen_ptcga(unsigned long addr, unsigned long size); - -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_IA64_XEN_PRIVOP_H */ diff --git a/trunk/arch/ia64/include/asm/xen/xcom_hcall.h b/trunk/arch/ia64/include/asm/xen/xcom_hcall.h deleted file mode 100644 index 20b2950c71b6..000000000000 --- a/trunk/arch/ia64/include/asm/xen/xcom_hcall.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2006 Tristan Gingold , Bull SAS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_IA64_XEN_XCOM_HCALL_H -#define _ASM_IA64_XEN_XCOM_HCALL_H - -/* These function creates inline or mini descriptor for the parameters and - calls the corresponding xencomm_arch_hypercall_X. - Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless - they want to use their own wrapper. */ -extern int xencomm_hypercall_console_io(int cmd, int count, char *str); - -extern int xencomm_hypercall_event_channel_op(int cmd, void *op); - -extern int xencomm_hypercall_xen_version(int cmd, void *arg); - -extern int xencomm_hypercall_physdev_op(int cmd, void *op); - -extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, - unsigned int count); - -extern int xencomm_hypercall_sched_op(int cmd, void *arg); - -extern int xencomm_hypercall_multicall(void *call_list, int nr_calls); - -extern int xencomm_hypercall_callback_op(int cmd, void *arg); - -extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg); - -extern int xencomm_hypercall_suspend(unsigned long srec); - -extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg); - -extern long xencomm_hypercall_opt_feature(void *arg); - -#endif /* _ASM_IA64_XEN_XCOM_HCALL_H */ diff --git a/trunk/arch/ia64/include/asm/xen/xencomm.h b/trunk/arch/ia64/include/asm/xen/xencomm.h deleted file mode 100644 index cded677bebf2..000000000000 --- a/trunk/arch/ia64/include/asm/xen/xencomm.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2006 Hollis Blanchard , IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_IA64_XEN_XENCOMM_H -#define _ASM_IA64_XEN_XENCOMM_H - -#include -#include - -/* Must be called before any hypercall. */ -extern void xencomm_initialize(void); -extern int xencomm_is_initialized(void); - -/* Check if virtual contiguity means physical contiguity - * where the passed address is a pointer value in virtual address. - * On ia64, identity mapping area in region 7 or the piece of region 5 - * that is mapped by itr[IA64_TR_KERNEL]/dtr[IA64_TR_KERNEL] - */ -static inline int xencomm_is_phys_contiguous(unsigned long addr) -{ - return (PAGE_OFFSET <= addr && - addr < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) || - (KERNEL_START <= addr && - addr < KERNEL_START + KERNEL_TR_PAGE_SIZE); -} - -#endif /* _ASM_IA64_XEN_XENCOMM_H */ diff --git a/trunk/arch/ia64/kernel/Makefile b/trunk/arch/ia64/kernel/Makefile index c381ea954892..87fea11aecb7 100644 --- a/trunk/arch/ia64/kernel/Makefile +++ b/trunk/arch/ia64/kernel/Makefile @@ -42,10 +42,6 @@ obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper endif -obj-$(CONFIG_DMAR) += pci-dma.o -ifeq ($(CONFIG_DMAR), y) -obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o -endif # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o @@ -116,23 +112,5 @@ clean-files += $(objtree)/include/asm-ia64/nr-irqs.h ASM_PARAVIRT_OBJS = ivt.o entry.o define paravirtualized_native AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE -AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK -extra-y += pvchk-$(1) endef $(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj)))) - -# -# Checker for paravirtualizations of privileged operations. -# -quiet_cmd_pv_check_sed = PVCHK $@ -define cmd_pv_check_sed - sed -f $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed $< > $@ -endef - -$(obj)/pvchk-sed-%.s: $(src)/%.S $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed FORCE - $(call if_changed_dep,as_s_S) -$(obj)/pvchk-%.s: $(obj)/pvchk-sed-%.s FORCE - $(call if_changed,pv_check_sed) -$(obj)/pvchk-%.o: $(obj)/pvchk-%.s FORCE - $(call if_changed,as_o_S) -.PRECIOUS: $(obj)/pvchk-sed-%.s $(obj)/pvchk-%.s $(obj)/pvchk-%.o diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index 0635015d0aaa..5d1eb7ee2bf6 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -52,7 +52,6 @@ #include #include #include -#include #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ @@ -92,9 +91,6 @@ acpi_get_sysname(void) struct acpi_table_rsdp *rsdp; struct acpi_table_xsdt *xsdt; struct acpi_table_header *hdr; -#ifdef CONFIG_DMAR - u64 i, nentries; -#endif rsdp_phys = acpi_find_rsdp(); if (!rsdp_phys) { @@ -125,21 +121,7 @@ acpi_get_sysname(void) return "uv"; else return "sn2"; - } else if (xen_pv_domain() && !strcmp(hdr->oem_id, "XEN")) { - return "xen"; - } - -#ifdef CONFIG_DMAR - /* Look for Intel IOMMU */ - nentries = (hdr->length - sizeof(*hdr)) / - sizeof(xsdt->table_offset_entry[0]); - for (i = 0; i < nentries; i++) { - hdr = __va(xsdt->table_offset_entry[i]); - if (strncmp(hdr->signature, ACPI_SIG_DMAR, - sizeof(ACPI_SIG_DMAR) - 1) == 0) - return "dig_vtd"; } -#endif return "dig"; #else @@ -155,10 +137,6 @@ acpi_get_sysname(void) return "uv"; # elif defined (CONFIG_IA64_DIG) return "dig"; -# elif defined (CONFIG_IA64_XEN_GUEST) - return "xen"; -# elif defined(CONFIG_IA64_DIG_VTD) - return "dig_vtd"; # else # error Unknown platform. Fix acpi.c. # endif diff --git a/trunk/arch/ia64/kernel/asm-offsets.c b/trunk/arch/ia64/kernel/asm-offsets.c index 742dbb1d5a4f..94c44b1ccfd0 100644 --- a/trunk/arch/ia64/kernel/asm-offsets.c +++ b/trunk/arch/ia64/kernel/asm-offsets.c @@ -16,9 +16,6 @@ #include #include -#include -#include - #include "../kernel/sigframe.h" #include "../kernel/fsyscall_gtod_data.h" @@ -289,32 +286,4 @@ void foo(void) offsetof (struct itc_jitter_data_t, itc_jitter)); DEFINE(IA64_ITC_LASTCYCLE_OFFSET, offsetof (struct itc_jitter_data_t, itc_lastcycle)); - -#ifdef CONFIG_XEN - BLANK(); - - DEFINE(XEN_NATIVE_ASM, XEN_NATIVE); - DEFINE(XEN_PV_DOMAIN_ASM, XEN_PV_DOMAIN); - -#define DEFINE_MAPPED_REG_OFS(sym, field) \ - DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(struct mapped_regs, field))) - - DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr); - DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr); - DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip); - DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs); - DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs); - DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr); - DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa); - DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa); - DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim); - DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha); - DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir); - DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled); - DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum); - DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]); - DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); - DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); - DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); -#endif /* CONFIG_XEN */ } diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index 7ef0c594f5ed..0dd6c1419d8d 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -534,11 +534,6 @@ GLOBAL_ENTRY(ia64_trace_syscall) stf.spill [r16]=f10 stf.spill [r17]=f11 br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args - cmp.lt p6,p0=r8,r0 // check tracehook - adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 - adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 - mov r10=0 -(p6) br.cond.sptk strace_error // syscall failed -> adds r16=PT(F6)+16,sp adds r17=PT(F7)+16,sp ;; diff --git a/trunk/arch/ia64/kernel/ivt.S b/trunk/arch/ia64/kernel/ivt.S index f675d8e33853..416a952b19bd 100644 --- a/trunk/arch/ia64/kernel/ivt.S +++ b/trunk/arch/ia64/kernel/ivt.S @@ -580,7 +580,7 @@ ENTRY(dirty_bit) mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - ITC_D(p0, r18, r16) // install updated PTE + itc.d r18 // install updated PTE #endif mov pr=r31,-1 // restore pr RFI @@ -646,7 +646,7 @@ ENTRY(iaccess_bit) mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - ITC_I(p0, r18, r16) // install updated PTE + itc.i r18 // install updated PTE #endif /* !CONFIG_SMP */ mov pr=r31,-1 RFI @@ -698,7 +698,7 @@ ENTRY(daccess_bit) or r18=_PAGE_A,r18 // set the accessed bit ;; st8 [r17]=r18 // store back updated PTE - ITC_D(p0, r18, r16) // install updated PTE + itc.d r18 // install updated PTE #endif mov b0=r29 // restore b0 mov pr=r31,-1 diff --git a/trunk/arch/ia64/kernel/msi_ia64.c b/trunk/arch/ia64/kernel/msi_ia64.c index 702a09c13238..60c6ef67ebb2 100644 --- a/trunk/arch/ia64/kernel/msi_ia64.c +++ b/trunk/arch/ia64/kernel/msi_ia64.c @@ -5,7 +5,6 @@ #include #include #include -#include #include /* @@ -163,82 +162,3 @@ void arch_teardown_msi_irq(unsigned int irq) return ia64_teardown_msi_irq(irq); } - -#ifdef CONFIG_DMAR -#ifdef CONFIG_SMP -static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) -{ - struct irq_cfg *cfg = irq_cfg + irq; - struct msi_msg msg; - int cpu = first_cpu(mask); - - - if (!cpu_online(cpu)) - return; - - if (irq_prepare_move(irq, cpu)) - return; - - dmar_msi_read(irq, &msg); - - msg.data &= ~MSI_DATA_VECTOR_MASK; - msg.data |= MSI_DATA_VECTOR(cfg->vector); - msg.address_lo &= ~MSI_ADDR_DESTID_MASK; - msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); - - dmar_msi_write(irq, &msg); - irq_desc[irq].affinity = mask; -} -#endif /* CONFIG_SMP */ - -struct irq_chip dmar_msi_type = { - .name = "DMAR_MSI", - .unmask = dmar_msi_unmask, - .mask = dmar_msi_mask, - .ack = ia64_ack_msi_irq, -#ifdef CONFIG_SMP - .set_affinity = dmar_msi_set_affinity, -#endif - .retrigger = ia64_msi_retrigger_irq, -}; - -static int -msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) -{ - struct irq_cfg *cfg = irq_cfg + irq; - unsigned dest; - cpumask_t mask; - - cpus_and(mask, irq_to_domain(irq), cpu_online_map); - dest = cpu_physical_id(first_cpu(mask)); - - msg->address_hi = 0; - msg->address_lo = - MSI_ADDR_HEADER | - MSI_ADDR_DESTMODE_PHYS | - MSI_ADDR_REDIRECTION_CPU | - MSI_ADDR_DESTID_CPU(dest); - - msg->data = - MSI_DATA_TRIGGER_EDGE | - MSI_DATA_LEVEL_ASSERT | - MSI_DATA_DELIVERY_FIXED | - MSI_DATA_VECTOR(cfg->vector); - return 0; -} - -int arch_setup_dmar_msi(unsigned int irq) -{ - int ret; - struct msi_msg msg; - - ret = msi_compose_msg(NULL, irq, &msg); - if (ret < 0) - return ret; - dmar_msi_write(irq, &msg); - set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, - "edge"); - return 0; -} -#endif /* CONFIG_DMAR */ - diff --git a/trunk/arch/ia64/kernel/nr-irqs.c b/trunk/arch/ia64/kernel/nr-irqs.c index ee564575148e..8273afc32db8 100644 --- a/trunk/arch/ia64/kernel/nr-irqs.c +++ b/trunk/arch/ia64/kernel/nr-irqs.c @@ -10,7 +10,6 @@ #include #include #include -#include void foo(void) { diff --git a/trunk/arch/ia64/kernel/paravirt.c b/trunk/arch/ia64/kernel/paravirt.c index de35d8e8b7d2..afaf5b9a2cf0 100644 --- a/trunk/arch/ia64/kernel/paravirt.c +++ b/trunk/arch/ia64/kernel/paravirt.c @@ -332,7 +332,7 @@ ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) struct pv_iosapic_ops pv_iosapic_ops = { .pcat_compat_init = ia64_native_iosapic_pcat_compat_init, - .__get_irq_chip = ia64_native_iosapic_get_irq_chip, + .get_irq_chip = ia64_native_iosapic_get_irq_chip, .__read = ia64_native_iosapic_read, .__write = ia64_native_iosapic_write, diff --git a/trunk/arch/ia64/kernel/paravirt_inst.h b/trunk/arch/ia64/kernel/paravirt_inst.h index 64d6d810c64b..5cad6fb2ed19 100644 --- a/trunk/arch/ia64/kernel/paravirt_inst.h +++ b/trunk/arch/ia64/kernel/paravirt_inst.h @@ -20,9 +20,7 @@ * */ -#ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK -#include -#elif defined(__IA64_ASM_PARAVIRTUALIZED_XEN) +#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN #include #include #else diff --git a/trunk/arch/ia64/kernel/pci-dma.c b/trunk/arch/ia64/kernel/pci-dma.c deleted file mode 100644 index 10a75b557650..000000000000 --- a/trunk/arch/ia64/kernel/pci-dma.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Dynamic DMA mapping support. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_DMAR - -#include -#include - -#include -#include - -dma_addr_t bad_dma_address __read_mostly; -EXPORT_SYMBOL(bad_dma_address); - -static int iommu_sac_force __read_mostly; - -int no_iommu __read_mostly; -#ifdef CONFIG_IOMMU_DEBUG -int force_iommu __read_mostly = 1; -#else -int force_iommu __read_mostly; -#endif - -/* Set this to 1 if there is a HW IOMMU in the system */ -int iommu_detected __read_mostly; - -/* Dummy device used for NULL arguments (normally ISA). Better would - be probably a smaller DMA mask, but this is bug-to-bug compatible - to i386. */ -struct device fallback_dev = { - .bus_id = "fallback device", - .coherent_dma_mask = DMA_32BIT_MASK, - .dma_mask = &fallback_dev.coherent_dma_mask, -}; - -void __init pci_iommu_alloc(void) -{ - /* - * The order of these functions is important for - * fall-back/fail-over reasons - */ - detect_intel_iommu(); - -#ifdef CONFIG_SWIOTLB - pci_swiotlb_init(); -#endif -} - -static int __init pci_iommu_init(void) -{ - if (iommu_detected) - intel_iommu_init(); - - return 0; -} - -/* Must execute after PCI subsystem */ -fs_initcall(pci_iommu_init); - -void pci_iommu_shutdown(void) -{ - return; -} - -void __init -iommu_dma_init(void) -{ - return; -} - -struct dma_mapping_ops *dma_ops; -EXPORT_SYMBOL(dma_ops); - -int iommu_dma_supported(struct device *dev, u64 mask) -{ - struct dma_mapping_ops *ops = get_dma_ops(dev); - -#ifdef CONFIG_PCI - if (mask > 0xffffffff && forbid_dac > 0) { - dev_info(dev, "Disallowing DAC for device\n"); - return 0; - } -#endif - - if (ops->dma_supported_op) - return ops->dma_supported_op(dev, mask); - - /* Copied from i386. Doesn't make much sense, because it will - only work for pci_alloc_coherent. - The caller just has to use GFP_DMA in this case. */ - if (mask < DMA_24BIT_MASK) - return 0; - - /* Tell the device to use SAC when IOMMU force is on. This - allows the driver to use cheaper accesses in some cases. - - Problem with this is that if we overflow the IOMMU area and - return DAC as fallback address the device may not handle it - correctly. - - As a special case some controllers have a 39bit address - mode that is as efficient as 32bit (aic79xx). Don't force - SAC for these. Assume all masks <= 40 bits are of this - type. Normally this doesn't make any difference, but gives - more gentle handling of IOMMU overflow. */ - if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) { - dev_info(dev, "Force SAC with mask %lx\n", mask); - return 0; - } - - return 1; -} -EXPORT_SYMBOL(iommu_dma_supported); - -#endif diff --git a/trunk/arch/ia64/kernel/pci-swiotlb.c b/trunk/arch/ia64/kernel/pci-swiotlb.c deleted file mode 100644 index 16c50516dbc1..000000000000 --- a/trunk/arch/ia64/kernel/pci-swiotlb.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Glue code to lib/swiotlb.c */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -int swiotlb __read_mostly; -EXPORT_SYMBOL(swiotlb); - -struct dma_mapping_ops swiotlb_dma_ops = { - .mapping_error = swiotlb_dma_mapping_error, - .alloc_coherent = swiotlb_alloc_coherent, - .free_coherent = swiotlb_free_coherent, - .map_single = swiotlb_map_single, - .unmap_single = swiotlb_unmap_single, - .sync_single_for_cpu = swiotlb_sync_single_for_cpu, - .sync_single_for_device = swiotlb_sync_single_for_device, - .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, - .sync_single_range_for_device = swiotlb_sync_single_range_for_device, - .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, - .sync_sg_for_device = swiotlb_sync_sg_for_device, - .map_sg = swiotlb_map_sg, - .unmap_sg = swiotlb_unmap_sg, - .dma_supported_op = swiotlb_dma_supported, -}; - -void __init pci_swiotlb_init(void) -{ - if (!iommu_detected) { -#ifdef CONFIG_IA64_GENERIC - swiotlb = 1; - printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n"); - machvec_init("dig"); - swiotlb_init(); - dma_ops = &swiotlb_dma_ops; -#else - panic("Unable to find Intel IOMMU"); -#endif - } -} diff --git a/trunk/arch/ia64/kernel/perfmon.c b/trunk/arch/ia64/kernel/perfmon.c index ada4605d1223..fc8f3509df27 100644 --- a/trunk/arch/ia64/kernel/perfmon.c +++ b/trunk/arch/ia64/kernel/perfmon.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -3685,7 +3684,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) PFM_SET_WORK_PENDING(task, 1); - set_notify_resume(task); + tsk_set_notify_resume(task); /* * XXX: send reschedule if task runs on another CPU @@ -5045,6 +5044,8 @@ pfm_handle_work(void) PFM_SET_WORK_PENDING(current, 0); + tsk_clear_notify_resume(current); + regs = task_pt_regs(current); /* @@ -5413,7 +5414,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str * when coming from ctxsw, current still points to the * previous task, therefore we must work with task and not current. */ - set_notify_resume(task); + tsk_set_notify_resume(task); } /* * defer until state is changed (shorten spin window). the context is locked diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index c57162705147..3ab8373103ec 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -161,6 +160,21 @@ show_regs (struct pt_regs *regs) show_stack(NULL, NULL); } +void tsk_clear_notify_resume(struct task_struct *tsk) +{ +#ifdef CONFIG_PERFMON + if (tsk->thread.pfm_needs_checking) + return; +#endif + if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE)) + return; + clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); +} + +/* + * do_notify_resume_user(): + * Called from notify_resume_user at entry.S, with interrupts disabled. + */ void do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) { @@ -189,11 +203,6 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) ia64_do_signal(scr, in_syscall); } - if (test_thread_flag(TIF_NOTIFY_RESUME)) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(&scr->pt); - } - /* copy user rbs to kernel rbs */ if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { local_irq_enable(); /* force interrupt enable */ @@ -242,6 +251,7 @@ default_idle (void) /* We don't actually take CPU down, just spin without interrupts. */ static inline void play_dead(void) { + extern void ia64_cpu_local_tick (void); unsigned int this_cpu = smp_processor_id(); /* Ack it */ diff --git a/trunk/arch/ia64/kernel/ptrace.c b/trunk/arch/ia64/kernel/ptrace.c index 92c9689b7d97..2a9943b5947f 100644 --- a/trunk/arch/ia64/kernel/ptrace.c +++ b/trunk/arch/ia64/kernel/ptrace.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -604,7 +603,7 @@ void ia64_ptrace_stop(void) { if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE)) return; - set_notify_resume(current); + tsk_set_notify_resume(current); unw_init_running(do_sync_rbs, ia64_sync_user_rbs); } @@ -614,6 +613,7 @@ void ia64_ptrace_stop(void) void ia64_sync_krbs(void) { clear_tsk_thread_flag(current, TIF_RESTORE_RSE); + tsk_clear_notify_resume(current); unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs); } @@ -644,7 +644,7 @@ ptrace_attach_sync_user_rbs (struct task_struct *child) spin_lock_irq(&child->sighand->siglock); if (child->state == TASK_STOPPED && !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) { - set_notify_resume(child); + tsk_set_notify_resume(child); child->state = TASK_TRACED; stopped = 1; @@ -1232,16 +1232,37 @@ arch_ptrace (struct task_struct *child, long request, long addr, long data) } +static void +syscall_trace (void) +{ + /* + * The 0x80 provides a way for the tracing parent to + * distinguish between a syscall stop and SIGTRAP delivery. + */ + ptrace_notify(SIGTRAP + | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + + /* + * This isn't the same as continuing with a signal, but it + * will do for normal use. strace only continues with a + * signal if the stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} + /* "asmlinkage" so the input arguments are preserved... */ -asmlinkage long +asmlinkage void syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { - if (test_thread_flag(TIF_SYSCALL_TRACE)) - if (tracehook_report_syscall_entry(®s)) - return -ENOSYS; + if (test_thread_flag(TIF_SYSCALL_TRACE) + && (current->ptrace & PT_PTRACED)) + syscall_trace(); /* copy user rbs to kernel rbs */ if (test_thread_flag(TIF_RESTORE_RSE)) @@ -1262,7 +1283,6 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); } - return 0; } /* "asmlinkage" so the input arguments are preserved... */ @@ -1272,8 +1292,6 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { - int step; - if (unlikely(current->audit_context)) { int success = AUDITSC_RESULT(regs.r10); long result = regs.r8; @@ -1283,9 +1301,10 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, audit_syscall_exit(success, result); } - step = test_thread_flag(TIF_SINGLESTEP); - if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(®s, step); + if ((test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SINGLESTEP)) + && (current->ptrace & PT_PTRACED)) + syscall_trace(); /* copy user rbs to kernel rbs */ if (test_thread_flag(TIF_RESTORE_RSE)) @@ -1921,7 +1940,7 @@ gpregs_writeback(struct task_struct *target, { if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE)) return 0; - set_notify_resume(target); + tsk_set_notify_resume(target); return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, NULL, NULL); } @@ -2180,68 +2199,3 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *tsk) #endif return &user_ia64_view; } - -struct syscall_get_set_args { - unsigned int i; - unsigned int n; - unsigned long *args; - struct pt_regs *regs; - int rw; -}; - -static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) -{ - struct syscall_get_set_args *args = data; - struct pt_regs *pt = args->regs; - unsigned long *krbs, cfm, ndirty; - int i, count; - - if (unw_unwind_to_user(info) < 0) - return; - - cfm = pt->cr_ifs; - krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; - ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); - - count = 0; - if (in_syscall(pt)) - count = min_t(int, args->n, cfm & 0x7f); - - for (i = 0; i < count; i++) { - if (args->rw) - *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = - args->args[i]; - else - args->args[i] = *ia64_rse_skip_regs(krbs, - ndirty + i + args->i); - } - - if (!args->rw) { - while (i < args->n) { - args->args[i] = 0; - i++; - } - } -} - -void ia64_syscall_get_set_arguments(struct task_struct *task, - struct pt_regs *regs, unsigned int i, unsigned int n, - unsigned long *args, int rw) -{ - struct syscall_get_set_args data = { - .i = i, - .n = n, - .args = args, - .regs = regs, - .rw = rw, - }; - - if (task == current) - unw_init_running(syscall_get_set_args_cb, &data); - else { - struct unw_frame_info ufi; - memset(&ufi, 0, sizeof(ufi)); - unw_init_from_blocked_task(&ufi, task); - syscall_get_set_args_cb(&ufi, &data); - } -} diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index ae7911702bf8..916ba898237f 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -116,13 +116,6 @@ unsigned int num_io_spaces; */ #define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ unsigned long ia64_i_cache_stride_shift = ~0; -/* - * "clflush_cache_range()" needs to know what processor dependent stride size to - * use when it flushes cache lines including both d-cache and i-cache. - */ -/* Safest way to go: 32 bytes by 32 bytes */ -#define CACHE_STRIDE_SHIFT 5 -unsigned long ia64_cache_stride_shift = ~0; /* * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This @@ -859,14 +852,13 @@ setup_per_cpu_areas (void) } /* - * Do the following calculations: + * Calculate the max. cache line size. * - * 1. the max. cache line size. - * 2. the minimum of the i-cache stride sizes for "flush_icache_range()". - * 3. the minimum of the cache stride sizes for "clflush_cache_range()". + * In addition, the minimum of the i-cache stride sizes is calculated for + * "flush_icache_range()". */ static void __cpuinit -get_cache_info(void) +get_max_cacheline_size (void) { unsigned long line_size, max = 1; u64 l, levels, unique_caches; @@ -880,14 +872,12 @@ get_cache_info(void) max = SMP_CACHE_BYTES; /* Safest setup for "flush_icache_range()" */ ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; - /* Safest setup for "clflush_cache_range()" */ - ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; goto out; } for (l = 0; l < levels; ++l) { - /* cache_type (data_or_unified)=2 */ - status = ia64_pal_cache_config_info(l, 2, &cci); + status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, + &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", @@ -895,21 +885,15 @@ get_cache_info(void) max = SMP_CACHE_BYTES; /* The safest setup for "flush_icache_range()" */ cci.pcci_stride = I_CACHE_STRIDE_SHIFT; - /* The safest setup for "clflush_cache_range()" */ - ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; cci.pcci_unified = 1; - } else { - if (cci.pcci_stride < ia64_cache_stride_shift) - ia64_cache_stride_shift = cci.pcci_stride; - - line_size = 1 << cci.pcci_line_size; - if (line_size > max) - max = line_size; } - + line_size = 1 << cci.pcci_line_size; + if (line_size > max) + max = line_size; if (!cci.pcci_unified) { - /* cache_type (instruction)=1*/ - status = ia64_pal_cache_config_info(l, 1, &cci); + status = ia64_pal_cache_config_info(l, + /* cache_type (instruction)= */ 1, + &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", @@ -963,7 +947,7 @@ cpu_init (void) } #endif - get_cache_info(); + get_max_cacheline_size(); /* * We can't pass "local_cpu_data" to identify_cpu() because we haven't called diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index e12500a9c443..19c5a78636fc 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -440,13 +439,6 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - - /* - * Let tracing know that we've done the handler setup. - */ - tracehook_signal_handler(sig, info, ka, &scr->pt, - test_thread_flag(TIF_SINGLESTEP)); - return 1; } diff --git a/trunk/arch/ia64/lib/flush.S b/trunk/arch/ia64/lib/flush.S index 1d8c88860063..2a0d27f2f21b 100644 --- a/trunk/arch/ia64/lib/flush.S +++ b/trunk/arch/ia64/lib/flush.S @@ -60,58 +60,3 @@ GLOBAL_ENTRY(flush_icache_range) mov ar.lc=r3 // restore ar.lc br.ret.sptk.many rp END(flush_icache_range) - - /* - * clflush_cache_range(start,size) - * - * Flush cache lines from start to start+size-1. - * - * Must deal with range from start to start+size-1 but nothing else - * (need to be careful not to touch addresses that may be - * unmapped). - * - * Note: "in0" and "in1" are preserved for debugging purposes. - */ - .section .kprobes.text,"ax" -GLOBAL_ENTRY(clflush_cache_range) - - .prologue - alloc r2=ar.pfs,2,0,0,0 - movl r3=ia64_cache_stride_shift - mov r21=1 - add r22=in1,in0 - ;; - ld8 r20=[r3] // r20: stride shift - sub r22=r22,r0,1 // last byte address - ;; - shr.u r23=in0,r20 // start / (stride size) - shr.u r22=r22,r20 // (last byte address) / (stride size) - shl r21=r21,r20 // r21: stride size of the i-cache(s) - ;; - sub r8=r22,r23 // number of strides - 1 - shl r24=r23,r20 // r24: addresses for "fc" = - // "start" rounded down to stride - // boundary - .save ar.lc,r3 - mov r3=ar.lc // save ar.lc - ;; - - .body - mov ar.lc=r8 - ;; - /* - * 32 byte aligned loop, even number of (actually 2) bundles - */ -.Loop_fc: - fc r24 // issuable on M0 only - add r24=r21,r24 // we flush "stride size" bytes per iteration - nop.i 0 - br.cloop.sptk.few .Loop_fc - ;; - sync.i - ;; - srlz.i - ;; - mov ar.lc=r3 // restore ar.lc - br.ret.sptk.many rp -END(clflush_cache_range) diff --git a/trunk/arch/ia64/mm/tlb.c b/trunk/arch/ia64/mm/tlb.c index bd9818a36b47..8caf42471f0d 100644 --- a/trunk/arch/ia64/mm/tlb.c +++ b/trunk/arch/ia64/mm/tlb.c @@ -362,13 +362,9 @@ ia64_tlb_init (void) per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_dtr_entry+1; if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) { - static int justonce = 1; per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX; - if (justonce) { - justonce = 0; - printk(KERN_DEBUG "TR register number exceeds " - "IA64_TR_ALLOC_MAX!\n"); - } + printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!" + "IA64_TR_ALLOC_MAX should be extended\n"); } } diff --git a/trunk/arch/ia64/scripts/pvcheck.sed b/trunk/arch/ia64/scripts/pvcheck.sed deleted file mode 100644 index ba66ac2e4c60..000000000000 --- a/trunk/arch/ia64/scripts/pvcheck.sed +++ /dev/null @@ -1,32 +0,0 @@ -# -# Checker for paravirtualizations of privileged operations. -# -s/ssm.*psr\.ic.*/.warning \"ssm psr.ic should not be used directly\"/g -s/rsm.*psr\.ic.*/.warning \"rsm psr.ic should not be used directly\"/g -s/ssm.*psr\.i.*/.warning \"ssm psr.i should not be used directly\"/g -s/rsm.*psr\.i.*/.warning \"rsm psr.i should not be used directly\"/g -s/ssm.*psr\.dt.*/.warning \"ssm psr.dt should not be used directly\"/g -s/rsm.*psr\.dt.*/.warning \"rsm psr.dt should not be used directly\"/g -s/mov.*=.*cr\.ifa/.warning \"cr.ifa should not used directly\"/g -s/mov.*=.*cr\.itir/.warning \"cr.itir should not used directly\"/g -s/mov.*=.*cr\.isr/.warning \"cr.isr should not used directly\"/g -s/mov.*=.*cr\.iha/.warning \"cr.iha should not used directly\"/g -s/mov.*=.*cr\.ipsr/.warning \"cr.ipsr should not used directly\"/g -s/mov.*=.*cr\.iim/.warning \"cr.iim should not used directly\"/g -s/mov.*=.*cr\.iip/.warning \"cr.iip should not used directly\"/g -s/mov.*=.*cr\.ivr/.warning \"cr.ivr should not used directly\"/g -s/mov.*=[^\.]*psr/.warning \"psr should not used directly\"/g # avoid ar.fpsr -s/mov.*=.*ar\.eflags/.warning \"ar.eflags should not used directly\"/g -s/mov.*cr\.ifa.*=.*/.warning \"cr.ifa should not used directly\"/g -s/mov.*cr\.itir.*=.*/.warning \"cr.itir should not used directly\"/g -s/mov.*cr\.iha.*=.*/.warning \"cr.iha should not used directly\"/g -s/mov.*cr\.ipsr.*=.*/.warning \"cr.ipsr should not used directly\"/g -s/mov.*cr\.ifs.*=.*/.warning \"cr.ifs should not used directly\"/g -s/mov.*cr\.iip.*=.*/.warning \"cr.iip should not used directly\"/g -s/mov.*cr\.kr.*=.*/.warning \"cr.kr should not used directly\"/g -s/mov.*ar\.eflags.*=.*/.warning \"ar.eflags should not used directly\"/g -s/itc\.i.*/.warning \"itc.i should not be used directly.\"/g -s/itc\.d.*/.warning \"itc.d should not be used directly.\"/g -s/bsw\.0/.warning \"bsw.0 should not be used directly.\"/g -s/bsw\.1/.warning \"bsw.1 should not be used directly.\"/g -s/ptc\.ga.*/.warning \"ptc.ga should not be used directly.\"/g diff --git a/trunk/arch/ia64/xen/Kconfig b/trunk/arch/ia64/xen/Kconfig deleted file mode 100644 index f1683a20275b..000000000000 --- a/trunk/arch/ia64/xen/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# -# This Kconfig describes xen/ia64 options -# - -config XEN - bool "Xen hypervisor support" - default y - depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL - select XEN_XENCOMM - select NO_IDLE_HZ - - # those are required to save/restore. - select ARCH_SUSPEND_POSSIBLE - select SUSPEND - select PM_SLEEP - help - Enable Xen hypervisor support. Resulting kernel runs - both as a guest OS on Xen and natively on hardware. - -config XEN_XENCOMM - depends on XEN - bool - -config NO_IDLE_HZ - depends on XEN - bool diff --git a/trunk/arch/ia64/xen/Makefile b/trunk/arch/ia64/xen/Makefile deleted file mode 100644 index 0ad0224693d9..000000000000 --- a/trunk/arch/ia64/xen/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# -# Makefile for Xen components -# - -obj-y := hypercall.o xenivt.o xensetup.o xen_pv_ops.o irq_xen.o \ - hypervisor.o xencomm.o xcom_hcall.o grant-table.o time.o suspend.o - -obj-$(CONFIG_IA64_GENERIC) += machvec.o - -AFLAGS_xenivt.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN - -# xen multi compile -ASM_PARAVIRT_MULTI_COMPILE_SRCS = ivt.S entry.S -ASM_PARAVIRT_OBJS = $(addprefix xen-,$(ASM_PARAVIRT_MULTI_COMPILE_SRCS:.S=.o)) -obj-y += $(ASM_PARAVIRT_OBJS) -define paravirtualized_xen -AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_XEN -endef -$(foreach o,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_xen,$(o)))) - -$(obj)/xen-%.o: $(src)/../kernel/%.S FORCE - $(call if_changed_dep,as_o_S) diff --git a/trunk/arch/ia64/xen/grant-table.c b/trunk/arch/ia64/xen/grant-table.c deleted file mode 100644 index 777dd9a9108b..000000000000 --- a/trunk/arch/ia64/xen/grant-table.c +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/grant-table.c - * - * Copyright (c) 2006 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include - -#include -#include -#include - -#include - -struct vm_struct *xen_alloc_vm_area(unsigned long size) -{ - int order; - unsigned long virt; - unsigned long nr_pages; - struct vm_struct *area; - - order = get_order(size); - virt = __get_free_pages(GFP_KERNEL, order); - if (virt == 0) - goto err0; - nr_pages = 1 << order; - scrub_pages(virt, nr_pages); - - area = kmalloc(sizeof(*area), GFP_KERNEL); - if (area == NULL) - goto err1; - - area->flags = VM_IOREMAP; - area->addr = (void *)virt; - area->size = size; - area->pages = NULL; - area->nr_pages = nr_pages; - area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ - - return area; - -err1: - free_pages(virt, order); -err0: - return NULL; -} -EXPORT_SYMBOL_GPL(xen_alloc_vm_area); - -void xen_free_vm_area(struct vm_struct *area) -{ - unsigned int order = get_order(area->size); - unsigned long i; - unsigned long phys_addr = __pa(area->addr); - - /* This area is used for foreign page mappping. - * So underlying machine page may not be assigned. */ - for (i = 0; i < (1 << order); i++) { - unsigned long ret; - unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; - struct xen_memory_reservation reservation = { - .nr_extents = 1, - .address_bits = 0, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_xen_guest_handle(reservation.extent_start, &gpfn); - ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, - &reservation); - BUG_ON(ret != 1); - } - free_pages((unsigned long)area->addr, order); - kfree(area); -} -EXPORT_SYMBOL_GPL(xen_free_vm_area); - - -/**************************************************************************** - * grant table hack - * cmd: GNTTABOP_xxx - */ - -int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, - unsigned long max_nr_gframes, - struct grant_entry **__shared) -{ - *__shared = __va(frames[0] << PAGE_SHIFT); - return 0; -} - -void arch_gnttab_unmap_shared(struct grant_entry *shared, - unsigned long nr_gframes) -{ - /* nothing */ -} - -static void -gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) -{ - uint32_t flags; - - flags = uop->flags; - - if (flags & GNTMAP_host_map) { - if (flags & GNTMAP_application_map) { - printk(KERN_DEBUG - "GNTMAP_application_map is not supported yet: " - "flags 0x%x\n", flags); - BUG(); - } - if (flags & GNTMAP_contains_pte) { - printk(KERN_DEBUG - "GNTMAP_contains_pte is not supported yet: " - "flags 0x%x\n", flags); - BUG(); - } - } else if (flags & GNTMAP_device_map) { - printk("GNTMAP_device_map is not supported yet 0x%x\n", flags); - BUG(); /* not yet. actually this flag is not used. */ - } else { - BUG(); - } -} - -int -HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) -{ - if (cmd == GNTTABOP_map_grant_ref) { - unsigned int i; - for (i = 0; i < count; i++) { - gnttab_map_grant_ref_pre( - (struct gnttab_map_grant_ref *)uop + i); - } - } - return xencomm_hypercall_grant_table_op(cmd, uop, count); -} - -EXPORT_SYMBOL(HYPERVISOR_grant_table_op); diff --git a/trunk/arch/ia64/xen/hypercall.S b/trunk/arch/ia64/xen/hypercall.S deleted file mode 100644 index d4ff0b9e79f1..000000000000 --- a/trunk/arch/ia64/xen/hypercall.S +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Support routines for Xen hypercalls - * - * Copyright (C) 2005 Dan Magenheimer - * Copyright (C) 2008 Yaozu (Eddie) Dong - */ - -#include -#include -#include - -/* - * Hypercalls without parameter. - */ -#define __HCALL0(name,hcall) \ - GLOBAL_ENTRY(name); \ - break hcall; \ - br.ret.sptk.many rp; \ - END(name) - -/* - * Hypercalls with 1 parameter. - */ -#define __HCALL1(name,hcall) \ - GLOBAL_ENTRY(name); \ - mov r8=r32; \ - break hcall; \ - br.ret.sptk.many rp; \ - END(name) - -/* - * Hypercalls with 2 parameters. - */ -#define __HCALL2(name,hcall) \ - GLOBAL_ENTRY(name); \ - mov r8=r32; \ - mov r9=r33; \ - break hcall; \ - br.ret.sptk.many rp; \ - END(name) - -__HCALL0(xen_get_psr, HYPERPRIVOP_GET_PSR) -__HCALL0(xen_get_ivr, HYPERPRIVOP_GET_IVR) -__HCALL0(xen_get_tpr, HYPERPRIVOP_GET_TPR) -__HCALL0(xen_hyper_ssm_i, HYPERPRIVOP_SSM_I) - -__HCALL1(xen_set_tpr, HYPERPRIVOP_SET_TPR) -__HCALL1(xen_eoi, HYPERPRIVOP_EOI) -__HCALL1(xen_thash, HYPERPRIVOP_THASH) -__HCALL1(xen_set_itm, HYPERPRIVOP_SET_ITM) -__HCALL1(xen_get_rr, HYPERPRIVOP_GET_RR) -__HCALL1(xen_fc, HYPERPRIVOP_FC) -__HCALL1(xen_get_cpuid, HYPERPRIVOP_GET_CPUID) -__HCALL1(xen_get_pmd, HYPERPRIVOP_GET_PMD) - -__HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA) -__HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR) -__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR) - -#ifdef CONFIG_IA32_SUPPORT -__HCALL1(xen_get_eflag, HYPERPRIVOP_GET_EFLAG) -__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8 -#endif /* CONFIG_IA32_SUPPORT */ - -GLOBAL_ENTRY(xen_set_rr0_to_rr4) - mov r8=r32 - mov r9=r33 - mov r10=r34 - mov r11=r35 - mov r14=r36 - XEN_HYPER_SET_RR0_TO_RR4 - br.ret.sptk.many rp - ;; -END(xen_set_rr0_to_rr4) - -GLOBAL_ENTRY(xen_send_ipi) - mov r14=r32 - mov r15=r33 - mov r2=0x400 - break 0x1000 - ;; - br.ret.sptk.many rp - ;; -END(xen_send_ipi) - -GLOBAL_ENTRY(__hypercall) - mov r2=r37 - break 0x1000 - br.ret.sptk.many b0 - ;; -END(__hypercall) diff --git a/trunk/arch/ia64/xen/hypervisor.c b/trunk/arch/ia64/xen/hypervisor.c deleted file mode 100644 index cac4d97c0b5a..000000000000 --- a/trunk/arch/ia64/xen/hypervisor.c +++ /dev/null @@ -1,96 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/hypervisor.c - * - * Copyright (c) 2006 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include - -#include "irq_xen.h" - -struct shared_info *HYPERVISOR_shared_info __read_mostly = - (struct shared_info *)XSI_BASE; -EXPORT_SYMBOL(HYPERVISOR_shared_info); - -DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); - -struct start_info *xen_start_info; -EXPORT_SYMBOL(xen_start_info); - -EXPORT_SYMBOL(xen_domain_type); - -EXPORT_SYMBOL(__hypercall); - -/* Stolen from arch/x86/xen/enlighten.c */ -/* - * Flag to determine whether vcpu info placement is available on all - * VCPUs. We assume it is to start with, and then set it to zero on - * the first failure. This is because it can succeed on some VCPUs - * and not others, since it can involve hypervisor memory allocation, - * or because the guest failed to guarantee all the appropriate - * constraints on all VCPUs (ie buffer can't cross a page boundary). - * - * Note that any particular CPU may be using a placed vcpu structure, - * but we can only optimise if the all are. - * - * 0: not available, 1: available - */ - -static void __init xen_vcpu_setup(int cpu) -{ - /* - * WARNING: - * before changing MAX_VIRT_CPUS, - * check that shared_info fits on a page - */ - BUILD_BUG_ON(sizeof(struct shared_info) > PAGE_SIZE); - per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; -} - -void __init xen_setup_vcpu_info_placement(void) -{ - int cpu; - - for_each_possible_cpu(cpu) - xen_vcpu_setup(cpu); -} - -void __cpuinit -xen_cpu_init(void) -{ - xen_smp_intr_init(); -} - -/************************************************************************** - * opt feature - */ -void -xen_ia64_enable_opt_feature(void) -{ - /* Enable region 7 identity map optimizations in Xen */ - struct xen_ia64_opt_feature optf; - - optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; - optf.on = XEN_IA64_OPTF_ON; - optf.pgprot = pgprot_val(PAGE_KERNEL); - optf.key = 0; /* No key on linux. */ - HYPERVISOR_opt_feature(&optf); -} diff --git a/trunk/arch/ia64/xen/irq_xen.c b/trunk/arch/ia64/xen/irq_xen.c deleted file mode 100644 index af93aadb68bb..000000000000 --- a/trunk/arch/ia64/xen/irq_xen.c +++ /dev/null @@ -1,435 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/irq_xen.c - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include - -#include -#include -#include - -#include - -#include "irq_xen.h" - -/*************************************************************************** - * pv_irq_ops - * irq operations - */ - -static int -xen_assign_irq_vector(int irq) -{ - struct physdev_irq irq_op; - - irq_op.irq = irq; - if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) - return -ENOSPC; - - return irq_op.vector; -} - -static void -xen_free_irq_vector(int vector) -{ - struct physdev_irq irq_op; - - if (vector < IA64_FIRST_DEVICE_VECTOR || - vector > IA64_LAST_DEVICE_VECTOR) - return; - - irq_op.vector = vector; - if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op)) - printk(KERN_WARNING "%s: xen_free_irq_vecotr fail vector=%d\n", - __func__, vector); -} - - -static DEFINE_PER_CPU(int, timer_irq) = -1; -static DEFINE_PER_CPU(int, ipi_irq) = -1; -static DEFINE_PER_CPU(int, resched_irq) = -1; -static DEFINE_PER_CPU(int, cmc_irq) = -1; -static DEFINE_PER_CPU(int, cmcp_irq) = -1; -static DEFINE_PER_CPU(int, cpep_irq) = -1; -#define NAME_SIZE 15 -static DEFINE_PER_CPU(char[NAME_SIZE], timer_name); -static DEFINE_PER_CPU(char[NAME_SIZE], ipi_name); -static DEFINE_PER_CPU(char[NAME_SIZE], resched_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cmc_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cmcp_name); -static DEFINE_PER_CPU(char[NAME_SIZE], cpep_name); -#undef NAME_SIZE - -struct saved_irq { - unsigned int irq; - struct irqaction *action; -}; -/* 16 should be far optimistic value, since only several percpu irqs - * are registered early. - */ -#define MAX_LATE_IRQ 16 -static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ]; -static unsigned short late_irq_cnt; -static unsigned short saved_irq_cnt; -static int xen_slab_ready; - -#ifdef CONFIG_SMP -/* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ, - * it ends up to issue several memory accesses upon percpu data and - * thus adds unnecessary traffic to other paths. - */ -static irqreturn_t -xen_dummy_handler(int irq, void *dev_id) -{ - - return IRQ_HANDLED; -} - -static struct irqaction xen_ipi_irqaction = { - .handler = handle_IPI, - .flags = IRQF_DISABLED, - .name = "IPI" -}; - -static struct irqaction xen_resched_irqaction = { - .handler = xen_dummy_handler, - .flags = IRQF_DISABLED, - .name = "resched" -}; - -static struct irqaction xen_tlb_irqaction = { - .handler = xen_dummy_handler, - .flags = IRQF_DISABLED, - .name = "tlb_flush" -}; -#endif - -/* - * This is xen version percpu irq registration, which needs bind - * to xen specific evtchn sub-system. One trick here is that xen - * evtchn binding interface depends on kmalloc because related - * port needs to be freed at device/cpu down. So we cache the - * registration on BSP before slab is ready and then deal them - * at later point. For rest instances happening after slab ready, - * we hook them to xen evtchn immediately. - * - * FIXME: MCA is not supported by far, and thus "nomca" boot param is - * required. - */ -static void -__xen_register_percpu_irq(unsigned int cpu, unsigned int vec, - struct irqaction *action, int save) -{ - irq_desc_t *desc; - int irq = 0; - - if (xen_slab_ready) { - switch (vec) { - case IA64_TIMER_VECTOR: - snprintf(per_cpu(timer_name, cpu), - sizeof(per_cpu(timer_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, - action->handler, action->flags, - per_cpu(timer_name, cpu), action->dev_id); - per_cpu(timer_irq, cpu) = irq; - break; - case IA64_IPI_RESCHEDULE: - snprintf(per_cpu(resched_name, cpu), - sizeof(per_cpu(resched_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu, - action->handler, action->flags, - per_cpu(resched_name, cpu), action->dev_id); - per_cpu(resched_irq, cpu) = irq; - break; - case IA64_IPI_VECTOR: - snprintf(per_cpu(ipi_name, cpu), - sizeof(per_cpu(ipi_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu, - action->handler, action->flags, - per_cpu(ipi_name, cpu), action->dev_id); - per_cpu(ipi_irq, cpu) = irq; - break; - case IA64_CMC_VECTOR: - snprintf(per_cpu(cmc_name, cpu), - sizeof(per_cpu(cmc_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, - action->handler, - action->flags, - per_cpu(cmc_name, cpu), - action->dev_id); - per_cpu(cmc_irq, cpu) = irq; - break; - case IA64_CMCP_VECTOR: - snprintf(per_cpu(cmcp_name, cpu), - sizeof(per_cpu(cmcp_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu, - action->handler, - action->flags, - per_cpu(cmcp_name, cpu), - action->dev_id); - per_cpu(cmcp_irq, cpu) = irq; - break; - case IA64_CPEP_VECTOR: - snprintf(per_cpu(cpep_name, cpu), - sizeof(per_cpu(cpep_name, cpu)), - "%s%d", action->name, cpu); - irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu, - action->handler, - action->flags, - per_cpu(cpep_name, cpu), - action->dev_id); - per_cpu(cpep_irq, cpu) = irq; - break; - case IA64_CPE_VECTOR: - case IA64_MCA_RENDEZ_VECTOR: - case IA64_PERFMON_VECTOR: - case IA64_MCA_WAKEUP_VECTOR: - case IA64_SPURIOUS_INT_VECTOR: - /* No need to complain, these aren't supported. */ - break; - default: - printk(KERN_WARNING "Percpu irq %d is unsupported " - "by xen!\n", vec); - break; - } - BUG_ON(irq < 0); - - if (irq > 0) { - /* - * Mark percpu. Without this, migrate_irqs() will - * mark the interrupt for migrations and trigger it - * on cpu hotplug. - */ - desc = irq_desc + irq; - desc->status |= IRQ_PER_CPU; - } - } - - /* For BSP, we cache registered percpu irqs, and then re-walk - * them when initializing APs - */ - if (!cpu && save) { - BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); - saved_percpu_irqs[saved_irq_cnt].irq = vec; - saved_percpu_irqs[saved_irq_cnt].action = action; - saved_irq_cnt++; - if (!xen_slab_ready) - late_irq_cnt++; - } -} - -static void -xen_register_percpu_irq(ia64_vector vec, struct irqaction *action) -{ - __xen_register_percpu_irq(smp_processor_id(), vec, action, 1); -} - -static void -xen_bind_early_percpu_irq(void) -{ - int i; - - xen_slab_ready = 1; - /* There's no race when accessing this cached array, since only - * BSP will face with such step shortly - */ - for (i = 0; i < late_irq_cnt; i++) - __xen_register_percpu_irq(smp_processor_id(), - saved_percpu_irqs[i].irq, - saved_percpu_irqs[i].action, 0); -} - -/* FIXME: There's no obvious point to check whether slab is ready. So - * a hack is used here by utilizing a late time hook. - */ - -#ifdef CONFIG_HOTPLUG_CPU -static int __devinit -unbind_evtchn_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - - if (action == CPU_DEAD) { - /* Unregister evtchn. */ - if (per_cpu(cpep_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL); - per_cpu(cpep_irq, cpu) = -1; - } - if (per_cpu(cmcp_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL); - per_cpu(cmcp_irq, cpu) = -1; - } - if (per_cpu(cmc_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL); - per_cpu(cmc_irq, cpu) = -1; - } - if (per_cpu(ipi_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL); - per_cpu(ipi_irq, cpu) = -1; - } - if (per_cpu(resched_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(resched_irq, cpu), - NULL); - per_cpu(resched_irq, cpu) = -1; - } - if (per_cpu(timer_irq, cpu) >= 0) { - unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); - per_cpu(timer_irq, cpu) = -1; - } - } - return NOTIFY_OK; -} - -static struct notifier_block unbind_evtchn_notifier = { - .notifier_call = unbind_evtchn_callback, - .priority = 0 -}; -#endif - -void xen_smp_intr_init_early(unsigned int cpu) -{ -#ifdef CONFIG_SMP - unsigned int i; - - for (i = 0; i < saved_irq_cnt; i++) - __xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq, - saved_percpu_irqs[i].action, 0); -#endif -} - -void xen_smp_intr_init(void) -{ -#ifdef CONFIG_SMP - unsigned int cpu = smp_processor_id(); - struct callback_register event = { - .type = CALLBACKTYPE_event, - .address = { .ip = (unsigned long)&xen_event_callback }, - }; - - if (cpu == 0) { - /* Initialization was already done for boot cpu. */ -#ifdef CONFIG_HOTPLUG_CPU - /* Register the notifier only once. */ - register_cpu_notifier(&unbind_evtchn_notifier); -#endif - return; - } - - /* This should be piggyback when setup vcpu guest context */ - BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); -#endif /* CONFIG_SMP */ -} - -void __init -xen_irq_init(void) -{ - struct callback_register event = { - .type = CALLBACKTYPE_event, - .address = { .ip = (unsigned long)&xen_event_callback }, - }; - - xen_init_IRQ(); - BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); - late_time_init = xen_bind_early_percpu_irq; -} - -void -xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect) -{ -#ifdef CONFIG_SMP - /* TODO: we need to call vcpu_up here */ - if (unlikely(vector == ap_wakeup_vector)) { - /* XXX - * This should be in __cpu_up(cpu) in ia64 smpboot.c - * like x86. But don't want to modify it, - * keep it untouched. - */ - xen_smp_intr_init_early(cpu); - - xen_send_ipi(cpu, vector); - /* vcpu_prepare_and_up(cpu); */ - return; - } -#endif - - switch (vector) { - case IA64_IPI_VECTOR: - xen_send_IPI_one(cpu, XEN_IPI_VECTOR); - break; - case IA64_IPI_RESCHEDULE: - xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR); - break; - case IA64_CMCP_VECTOR: - xen_send_IPI_one(cpu, XEN_CMCP_VECTOR); - break; - case IA64_CPEP_VECTOR: - xen_send_IPI_one(cpu, XEN_CPEP_VECTOR); - break; - case IA64_TIMER_VECTOR: { - /* this is used only once by check_sal_cache_flush() - at boot time */ - static int used = 0; - if (!used) { - xen_send_ipi(cpu, IA64_TIMER_VECTOR); - used = 1; - break; - } - /* fallthrough */ - } - default: - printk(KERN_WARNING "Unsupported IPI type 0x%x\n", - vector); - notify_remote_via_irq(0); /* defaults to 0 irq */ - break; - } -} - -static void __init -xen_register_ipi(void) -{ -#ifdef CONFIG_SMP - register_percpu_irq(IA64_IPI_VECTOR, &xen_ipi_irqaction); - register_percpu_irq(IA64_IPI_RESCHEDULE, &xen_resched_irqaction); - register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &xen_tlb_irqaction); -#endif -} - -static void -xen_resend_irq(unsigned int vector) -{ - (void)resend_irq_on_evtchn(vector); -} - -const struct pv_irq_ops xen_irq_ops __initdata = { - .register_ipi = xen_register_ipi, - - .assign_irq_vector = xen_assign_irq_vector, - .free_irq_vector = xen_free_irq_vector, - .register_percpu_irq = xen_register_percpu_irq, - - .resend_irq = xen_resend_irq, -}; diff --git a/trunk/arch/ia64/xen/irq_xen.h b/trunk/arch/ia64/xen/irq_xen.h deleted file mode 100644 index 26110f330c87..000000000000 --- a/trunk/arch/ia64/xen/irq_xen.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/irq_xen.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef IRQ_XEN_H -#define IRQ_XEN_H - -extern void (*late_time_init)(void); -extern char xen_event_callback; -void __init xen_init_IRQ(void); - -extern const struct pv_irq_ops xen_irq_ops __initdata; -extern void xen_smp_intr_init(void); -extern void xen_send_ipi(int cpu, int vec); - -#endif /* IRQ_XEN_H */ diff --git a/trunk/arch/ia64/xen/machvec.c b/trunk/arch/ia64/xen/machvec.c deleted file mode 100644 index 4ad588a7c279..000000000000 --- a/trunk/arch/ia64/xen/machvec.c +++ /dev/null @@ -1,4 +0,0 @@ -#define MACHVEC_PLATFORM_NAME xen -#define MACHVEC_PLATFORM_HEADER -#include - diff --git a/trunk/arch/ia64/xen/suspend.c b/trunk/arch/ia64/xen/suspend.c deleted file mode 100644 index fd66b048c6fa..000000000000 --- a/trunk/arch/ia64/xen/suspend.c +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/suspend.c - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * suspend/resume - */ - -#include -#include -#include "time.h" - -void -xen_mm_pin_all(void) -{ - /* nothing */ -} - -void -xen_mm_unpin_all(void) -{ - /* nothing */ -} - -void xen_pre_device_suspend(void) -{ - /* nothing */ -} - -void -xen_pre_suspend() -{ - /* nothing */ -} - -void -xen_post_suspend(int suspend_cancelled) -{ - if (suspend_cancelled) - return; - - xen_ia64_enable_opt_feature(); - /* add more if necessary */ -} - -void xen_arch_resume(void) -{ - xen_timer_resume_on_aps(); -} diff --git a/trunk/arch/ia64/xen/time.c b/trunk/arch/ia64/xen/time.c deleted file mode 100644 index d15a94c330fb..000000000000 --- a/trunk/arch/ia64/xen/time.c +++ /dev/null @@ -1,213 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/time.c - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include "../kernel/fsyscall_gtod_data.h" - -DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); -DEFINE_PER_CPU(unsigned long, processed_stolen_time); -DEFINE_PER_CPU(unsigned long, processed_blocked_time); - -/* taken from i386/kernel/time-xen.c */ -static void xen_init_missing_ticks_accounting(int cpu) -{ - struct vcpu_register_runstate_memory_area area; - struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); - int rc; - - memset(runstate, 0, sizeof(*runstate)); - - area.addr.v = runstate; - rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, - &area); - WARN_ON(rc && rc != -ENOSYS); - - per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked]; - per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable] - + runstate->time[RUNSTATE_offline]; -} - -/* - * Runstate accounting - */ -/* stolen from arch/x86/xen/time.c */ -static void get_runstate_snapshot(struct vcpu_runstate_info *res) -{ - u64 state_time; - struct vcpu_runstate_info *state; - - BUG_ON(preemptible()); - - state = &__get_cpu_var(runstate); - - /* - * The runstate info is always updated by the hypervisor on - * the current CPU, so there's no need to use anything - * stronger than a compiler barrier when fetching it. - */ - do { - state_time = state->state_entry_time; - rmb(); - *res = *state; - rmb(); - } while (state->state_entry_time != state_time); -} - -#define NS_PER_TICK (1000000000LL/HZ) - -static unsigned long -consider_steal_time(unsigned long new_itm) -{ - unsigned long stolen, blocked; - unsigned long delta_itm = 0, stolentick = 0; - int cpu = smp_processor_id(); - struct vcpu_runstate_info runstate; - struct task_struct *p = current; - - get_runstate_snapshot(&runstate); - - /* - * Check for vcpu migration effect - * In this case, itc value is reversed. - * This causes huge stolen value. - * This function just checks and reject this effect. - */ - if (!time_after_eq(runstate.time[RUNSTATE_blocked], - per_cpu(processed_blocked_time, cpu))) - blocked = 0; - - if (!time_after_eq(runstate.time[RUNSTATE_runnable] + - runstate.time[RUNSTATE_offline], - per_cpu(processed_stolen_time, cpu))) - stolen = 0; - - if (!time_after(delta_itm + new_itm, ia64_get_itc())) - stolentick = ia64_get_itc() - new_itm; - - do_div(stolentick, NS_PER_TICK); - stolentick++; - - do_div(stolen, NS_PER_TICK); - - if (stolen > stolentick) - stolen = stolentick; - - stolentick -= stolen; - do_div(blocked, NS_PER_TICK); - - if (blocked > stolentick) - blocked = stolentick; - - if (stolen > 0 || blocked > 0) { - account_steal_time(NULL, jiffies_to_cputime(stolen)); - account_steal_time(idle_task(cpu), jiffies_to_cputime(blocked)); - run_local_timers(); - - if (rcu_pending(cpu)) - rcu_check_callbacks(cpu, user_mode(get_irq_regs())); - - scheduler_tick(); - run_posix_cpu_timers(p); - delta_itm += local_cpu_data->itm_delta * (stolen + blocked); - - if (cpu == time_keeper_id) { - write_seqlock(&xtime_lock); - do_timer(stolen + blocked); - local_cpu_data->itm_next = delta_itm + new_itm; - write_sequnlock(&xtime_lock); - } else { - local_cpu_data->itm_next = delta_itm + new_itm; - } - per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen; - per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked; - } - return delta_itm; -} - -static int xen_do_steal_accounting(unsigned long *new_itm) -{ - unsigned long delta_itm; - delta_itm = consider_steal_time(*new_itm); - *new_itm += delta_itm; - if (time_after(*new_itm, ia64_get_itc()) && delta_itm) - return 1; - - return 0; -} - -static void xen_itc_jitter_data_reset(void) -{ - u64 lcycle, ret; - - do { - lcycle = itc_jitter_data.itc_lastcycle; - ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0); - } while (unlikely(ret != lcycle)); -} - -struct pv_time_ops xen_time_ops __initdata = { - .init_missing_ticks_accounting = xen_init_missing_ticks_accounting, - .do_steal_accounting = xen_do_steal_accounting, - .clocksource_resume = xen_itc_jitter_data_reset, -}; - -/* Called after suspend, to resume time. */ -static void xen_local_tick_resume(void) -{ - /* Just trigger a tick. */ - ia64_cpu_local_tick(); - touch_softlockup_watchdog(); -} - -void -xen_timer_resume(void) -{ - unsigned int cpu; - - xen_local_tick_resume(); - - for_each_online_cpu(cpu) - xen_init_missing_ticks_accounting(cpu); -} - -static void ia64_cpu_local_tick_fn(void *unused) -{ - xen_local_tick_resume(); - xen_init_missing_ticks_accounting(smp_processor_id()); -} - -void -xen_timer_resume_on_aps(void) -{ - smp_call_function(&ia64_cpu_local_tick_fn, NULL, 1); -} diff --git a/trunk/arch/ia64/xen/time.h b/trunk/arch/ia64/xen/time.h deleted file mode 100644 index f98d7e1a42f0..000000000000 --- a/trunk/arch/ia64/xen/time.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/time.h - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -extern struct pv_time_ops xen_time_ops __initdata; -void xen_timer_resume_on_aps(void); diff --git a/trunk/arch/ia64/xen/xcom_hcall.c b/trunk/arch/ia64/xen/xcom_hcall.c deleted file mode 100644 index ccaf7431f7c8..000000000000 --- a/trunk/arch/ia64/xen/xcom_hcall.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Tristan Gingold - * - * Copyright (c) 2007 - * Isaku Yamahata - * VA Linux Systems Japan K.K. - * consolidate mini and inline version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Xencomm notes: - * This file defines hypercalls to be used by xencomm. The hypercalls simply - * create inlines or mini descriptors for pointers and then call the raw arch - * hypercall xencomm_arch_hypercall_XXX - * - * If the arch wants to directly use these hypercalls, simply define macros - * in asm/xen/hypercall.h, eg: - * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op - * - * The arch may also define HYPERVISOR_xxx as a function and do more operations - * before/after doing the hypercall. - * - * Note: because only inline or mini descriptors are created these functions - * must only be called with in kernel memory parameters. - */ - -int -xencomm_hypercall_console_io(int cmd, int count, char *str) -{ - /* xen early printk uses console io hypercall before - * xencomm initialization. In that case, we just ignore it. - */ - if (!xencomm_is_initialized()) - return 0; - - return xencomm_arch_hypercall_console_io - (cmd, count, xencomm_map_no_alloc(str, count)); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io); - -int -xencomm_hypercall_event_channel_op(int cmd, void *op) -{ - struct xencomm_handle *desc; - desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op)); - if (desc == NULL) - return -EINVAL; - - return xencomm_arch_hypercall_event_channel_op(cmd, desc); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op); - -int -xencomm_hypercall_xen_version(int cmd, void *arg) -{ - struct xencomm_handle *desc; - unsigned int argsize; - - switch (cmd) { - case XENVER_version: - /* do not actually pass an argument */ - return xencomm_arch_hypercall_xen_version(cmd, 0); - case XENVER_extraversion: - argsize = sizeof(struct xen_extraversion); - break; - case XENVER_compile_info: - argsize = sizeof(struct xen_compile_info); - break; - case XENVER_capabilities: - argsize = sizeof(struct xen_capabilities_info); - break; - case XENVER_changeset: - argsize = sizeof(struct xen_changeset_info); - break; - case XENVER_platform_parameters: - argsize = sizeof(struct xen_platform_parameters); - break; - case XENVER_get_features: - argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info); - break; - - default: - printk(KERN_DEBUG - "%s: unknown version op %d\n", __func__, cmd); - return -ENOSYS; - } - - desc = xencomm_map_no_alloc(arg, argsize); - if (desc == NULL) - return -EINVAL; - - return xencomm_arch_hypercall_xen_version(cmd, desc); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version); - -int -xencomm_hypercall_physdev_op(int cmd, void *op) -{ - unsigned int argsize; - - switch (cmd) { - case PHYSDEVOP_apic_read: - case PHYSDEVOP_apic_write: - argsize = sizeof(struct physdev_apic); - break; - case PHYSDEVOP_alloc_irq_vector: - case PHYSDEVOP_free_irq_vector: - argsize = sizeof(struct physdev_irq); - break; - case PHYSDEVOP_irq_status_query: - argsize = sizeof(struct physdev_irq_status_query); - break; - - default: - printk(KERN_DEBUG - "%s: unknown physdev op %d\n", __func__, cmd); - return -ENOSYS; - } - - return xencomm_arch_hypercall_physdev_op - (cmd, xencomm_map_no_alloc(op, argsize)); -} - -static int -xencommize_grant_table_op(struct xencomm_mini **xc_area, - unsigned int cmd, void *op, unsigned int count, - struct xencomm_handle **desc) -{ - struct xencomm_handle *desc1; - unsigned int argsize; - - switch (cmd) { - case GNTTABOP_map_grant_ref: - argsize = sizeof(struct gnttab_map_grant_ref); - break; - case GNTTABOP_unmap_grant_ref: - argsize = sizeof(struct gnttab_unmap_grant_ref); - break; - case GNTTABOP_setup_table: - { - struct gnttab_setup_table *setup = op; - - argsize = sizeof(*setup); - - if (count != 1) - return -EINVAL; - desc1 = __xencomm_map_no_alloc - (xen_guest_handle(setup->frame_list), - setup->nr_frames * - sizeof(*xen_guest_handle(setup->frame_list)), - *xc_area); - if (desc1 == NULL) - return -EINVAL; - (*xc_area)++; - set_xen_guest_handle(setup->frame_list, (void *)desc1); - break; - } - case GNTTABOP_dump_table: - argsize = sizeof(struct gnttab_dump_table); - break; - case GNTTABOP_transfer: - argsize = sizeof(struct gnttab_transfer); - break; - case GNTTABOP_copy: - argsize = sizeof(struct gnttab_copy); - break; - case GNTTABOP_query_size: - argsize = sizeof(struct gnttab_query_size); - break; - default: - printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n", - __func__, cmd); - BUG(); - } - - *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area); - if (*desc == NULL) - return -EINVAL; - (*xc_area)++; - - return 0; -} - -int -xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, - unsigned int count) -{ - int rc; - struct xencomm_handle *desc; - XENCOMM_MINI_ALIGNED(xc_area, 2); - - rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc); - if (rc) - return rc; - - return xencomm_arch_hypercall_grant_table_op(cmd, desc, count); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op); - -int -xencomm_hypercall_sched_op(int cmd, void *arg) -{ - struct xencomm_handle *desc; - unsigned int argsize; - - switch (cmd) { - case SCHEDOP_yield: - case SCHEDOP_block: - argsize = 0; - break; - case SCHEDOP_shutdown: - argsize = sizeof(struct sched_shutdown); - break; - case SCHEDOP_poll: - { - struct sched_poll *poll = arg; - struct xencomm_handle *ports; - - argsize = sizeof(struct sched_poll); - ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports), - sizeof(*xen_guest_handle(poll->ports))); - - set_xen_guest_handle(poll->ports, (void *)ports); - break; - } - default: - printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd); - return -ENOSYS; - } - - desc = xencomm_map_no_alloc(arg, argsize); - if (desc == NULL) - return -EINVAL; - - return xencomm_arch_hypercall_sched_op(cmd, desc); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op); - -int -xencomm_hypercall_multicall(void *call_list, int nr_calls) -{ - int rc; - int i; - struct multicall_entry *mce; - struct xencomm_handle *desc; - XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2); - - for (i = 0; i < nr_calls; i++) { - mce = (struct multicall_entry *)call_list + i; - - switch (mce->op) { - case __HYPERVISOR_update_va_mapping: - case __HYPERVISOR_mmu_update: - /* No-op on ia64. */ - break; - case __HYPERVISOR_grant_table_op: - rc = xencommize_grant_table_op - (&xc_area, - mce->args[0], (void *)mce->args[1], - mce->args[2], &desc); - if (rc) - return rc; - mce->args[1] = (unsigned long)desc; - break; - case __HYPERVISOR_memory_op: - default: - printk(KERN_DEBUG - "%s: unhandled multicall op entry op %lu\n", - __func__, mce->op); - return -ENOSYS; - } - } - - desc = xencomm_map_no_alloc(call_list, - nr_calls * sizeof(struct multicall_entry)); - if (desc == NULL) - return -EINVAL; - - return xencomm_arch_hypercall_multicall(desc, nr_calls); -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall); - -int -xencomm_hypercall_callback_op(int cmd, void *arg) -{ - unsigned int argsize; - switch (cmd) { - case CALLBACKOP_register: - argsize = sizeof(struct callback_register); - break; - case CALLBACKOP_unregister: - argsize = sizeof(struct callback_unregister); - break; - default: - printk(KERN_DEBUG - "%s: unknown callback op %d\n", __func__, cmd); - return -ENOSYS; - } - - return xencomm_arch_hypercall_callback_op - (cmd, xencomm_map_no_alloc(arg, argsize)); -} - -static int -xencommize_memory_reservation(struct xencomm_mini *xc_area, - struct xen_memory_reservation *mop) -{ - struct xencomm_handle *desc; - - desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start), - mop->nr_extents * - sizeof(*xen_guest_handle(mop->extent_start)), - xc_area); - if (desc == NULL) - return -EINVAL; - - set_xen_guest_handle(mop->extent_start, (void *)desc); - return 0; -} - -int -xencomm_hypercall_memory_op(unsigned int cmd, void *arg) -{ - GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} }; - struct xen_memory_reservation *xmr = NULL; - int rc; - struct xencomm_handle *desc; - unsigned int argsize; - XENCOMM_MINI_ALIGNED(xc_area, 2); - - switch (cmd) { - case XENMEM_increase_reservation: - case XENMEM_decrease_reservation: - case XENMEM_populate_physmap: - xmr = (struct xen_memory_reservation *)arg; - set_xen_guest_handle(extent_start_va[0], - xen_guest_handle(xmr->extent_start)); - - argsize = sizeof(*xmr); - rc = xencommize_memory_reservation(xc_area, xmr); - if (rc) - return rc; - xc_area++; - break; - - case XENMEM_maximum_ram_page: - argsize = 0; - break; - - case XENMEM_add_to_physmap: - argsize = sizeof(struct xen_add_to_physmap); - break; - - default: - printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd); - return -ENOSYS; - } - - desc = xencomm_map_no_alloc(arg, argsize); - if (desc == NULL) - return -EINVAL; - - rc = xencomm_arch_hypercall_memory_op(cmd, desc); - - switch (cmd) { - case XENMEM_increase_reservation: - case XENMEM_decrease_reservation: - case XENMEM_populate_physmap: - set_xen_guest_handle(xmr->extent_start, - xen_guest_handle(extent_start_va[0])); - break; - } - - return rc; -} -EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op); - -int -xencomm_hypercall_suspend(unsigned long srec) -{ - struct sched_shutdown arg; - - arg.reason = SHUTDOWN_suspend; - - return xencomm_arch_hypercall_sched_op( - SCHEDOP_shutdown, xencomm_map_no_alloc(&arg, sizeof(arg))); -} - -long -xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg) -{ - unsigned int argsize; - switch (cmd) { - case VCPUOP_register_runstate_memory_area: { - struct vcpu_register_runstate_memory_area *area = - (struct vcpu_register_runstate_memory_area *)arg; - argsize = sizeof(*arg); - set_xen_guest_handle(area->addr.h, - (void *)xencomm_map_no_alloc(area->addr.v, - sizeof(area->addr.v))); - break; - } - - default: - printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd); - return -ENOSYS; - } - - return xencomm_arch_hypercall_vcpu_op(cmd, cpu, - xencomm_map_no_alloc(arg, argsize)); -} - -long -xencomm_hypercall_opt_feature(void *arg) -{ - return xencomm_arch_hypercall_opt_feature( - xencomm_map_no_alloc(arg, - sizeof(struct xen_ia64_opt_feature))); -} diff --git a/trunk/arch/ia64/xen/xen_pv_ops.c b/trunk/arch/ia64/xen/xen_pv_ops.c deleted file mode 100644 index 04cd12350455..000000000000 --- a/trunk/arch/ia64/xen/xen_pv_ops.c +++ /dev/null @@ -1,364 +0,0 @@ -/****************************************************************************** - * arch/ia64/xen/xen_pv_ops.c - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "irq_xen.h" -#include "time.h" - -/*************************************************************************** - * general info - */ -static struct pv_info xen_info __initdata = { - .kernel_rpl = 2, /* or 1: determin at runtime */ - .paravirt_enabled = 1, - .name = "Xen/ia64", -}; - -#define IA64_RSC_PL_SHIFT 2 -#define IA64_RSC_PL_BIT_SIZE 2 -#define IA64_RSC_PL_MASK \ - (((1UL << IA64_RSC_PL_BIT_SIZE) - 1) << IA64_RSC_PL_SHIFT) - -static void __init -xen_info_init(void) -{ - /* Xenified Linux/ia64 may run on pl = 1 or 2. - * determin at run time. */ - unsigned long rsc = ia64_getreg(_IA64_REG_AR_RSC); - unsigned int rpl = (rsc & IA64_RSC_PL_MASK) >> IA64_RSC_PL_SHIFT; - xen_info.kernel_rpl = rpl; -} - -/*************************************************************************** - * pv_init_ops - * initialization hooks. - */ - -static void -xen_panic_hypercall(struct unw_frame_info *info, void *arg) -{ - current->thread.ksp = (__u64)info->sw - 16; - HYPERVISOR_shutdown(SHUTDOWN_crash); - /* we're never actually going to get here... */ -} - -static int -xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - unw_init_running(xen_panic_hypercall, NULL); - /* we're never actually going to get here... */ - return NOTIFY_DONE; -} - -static struct notifier_block xen_panic_block = { - xen_panic_event, NULL, 0 /* try to go last */ -}; - -static void xen_pm_power_off(void) -{ - local_irq_disable(); - HYPERVISOR_shutdown(SHUTDOWN_poweroff); -} - -static void __init -xen_banner(void) -{ - printk(KERN_INFO - "Running on Xen! pl = %d start_info_pfn=0x%lx nr_pages=%ld " - "flags=0x%x\n", - xen_info.kernel_rpl, - HYPERVISOR_shared_info->arch.start_info_pfn, - xen_start_info->nr_pages, xen_start_info->flags); -} - -static int __init -xen_reserve_memory(struct rsvd_region *region) -{ - region->start = (unsigned long)__va( - (HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT)); - region->end = region->start + PAGE_SIZE; - return 1; -} - -static void __init -xen_arch_setup_early(void) -{ - struct shared_info *s; - BUG_ON(!xen_pv_domain()); - - s = HYPERVISOR_shared_info; - xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT); - - /* Must be done before any hypercall. */ - xencomm_initialize(); - - xen_setup_features(); - /* Register a call for panic conditions. */ - atomic_notifier_chain_register(&panic_notifier_list, - &xen_panic_block); - pm_power_off = xen_pm_power_off; - - xen_ia64_enable_opt_feature(); -} - -static void __init -xen_arch_setup_console(char **cmdline_p) -{ - add_preferred_console("xenboot", 0, NULL); - add_preferred_console("tty", 0, NULL); - /* use hvc_xen */ - add_preferred_console("hvc", 0, NULL); - -#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE) - conswitchp = NULL; -#endif -} - -static int __init -xen_arch_setup_nomca(void) -{ - return 1; -} - -static void __init -xen_post_smp_prepare_boot_cpu(void) -{ - xen_setup_vcpu_info_placement(); -} - -static const struct pv_init_ops xen_init_ops __initdata = { - .banner = xen_banner, - - .reserve_memory = xen_reserve_memory, - - .arch_setup_early = xen_arch_setup_early, - .arch_setup_console = xen_arch_setup_console, - .arch_setup_nomca = xen_arch_setup_nomca, - - .post_smp_prepare_boot_cpu = xen_post_smp_prepare_boot_cpu, -}; - -/*************************************************************************** - * pv_cpu_ops - * intrinsics hooks. - */ - -static void xen_setreg(int regnum, unsigned long val) -{ - switch (regnum) { - case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: - xen_set_kr(regnum - _IA64_REG_AR_KR0, val); - break; -#ifdef CONFIG_IA32_SUPPORT - case _IA64_REG_AR_EFLAG: - xen_set_eflag(val); - break; -#endif - case _IA64_REG_CR_TPR: - xen_set_tpr(val); - break; - case _IA64_REG_CR_ITM: - xen_set_itm(val); - break; - case _IA64_REG_CR_EOI: - xen_eoi(val); - break; - default: - ia64_native_setreg_func(regnum, val); - break; - } -} - -static unsigned long xen_getreg(int regnum) -{ - unsigned long res; - - switch (regnum) { - case _IA64_REG_PSR: - res = xen_get_psr(); - break; -#ifdef CONFIG_IA32_SUPPORT - case _IA64_REG_AR_EFLAG: - res = xen_get_eflag(); - break; -#endif - case _IA64_REG_CR_IVR: - res = xen_get_ivr(); - break; - case _IA64_REG_CR_TPR: - res = xen_get_tpr(); - break; - default: - res = ia64_native_getreg_func(regnum); - break; - } - return res; -} - -/* turning on interrupts is a bit more complicated.. write to the - * memory-mapped virtual psr.i bit first (to avoid race condition), - * then if any interrupts were pending, we have to execute a hyperprivop - * to ensure the pending interrupt gets delivered; else we're done! */ -static void -xen_ssm_i(void) -{ - int old = xen_get_virtual_psr_i(); - xen_set_virtual_psr_i(1); - barrier(); - if (!old && xen_get_virtual_pend()) - xen_hyper_ssm_i(); -} - -/* turning off interrupts can be paravirtualized simply by writing - * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ -static void -xen_rsm_i(void) -{ - xen_set_virtual_psr_i(0); - barrier(); -} - -static unsigned long -xen_get_psr_i(void) -{ - return xen_get_virtual_psr_i() ? IA64_PSR_I : 0; -} - -static void -xen_intrin_local_irq_restore(unsigned long mask) -{ - if (mask & IA64_PSR_I) - xen_ssm_i(); - else - xen_rsm_i(); -} - -static const struct pv_cpu_ops xen_cpu_ops __initdata = { - .fc = xen_fc, - .thash = xen_thash, - .get_cpuid = xen_get_cpuid, - .get_pmd = xen_get_pmd, - .getreg = xen_getreg, - .setreg = xen_setreg, - .ptcga = xen_ptcga, - .get_rr = xen_get_rr, - .set_rr = xen_set_rr, - .set_rr0_to_rr4 = xen_set_rr0_to_rr4, - .ssm_i = xen_ssm_i, - .rsm_i = xen_rsm_i, - .get_psr_i = xen_get_psr_i, - .intrin_local_irq_restore - = xen_intrin_local_irq_restore, -}; - -/****************************************************************************** - * replacement of hand written assembly codes. - */ - -extern char xen_switch_to; -extern char xen_leave_syscall; -extern char xen_work_processed_syscall; -extern char xen_leave_kernel; - -const struct pv_cpu_asm_switch xen_cpu_asm_switch = { - .switch_to = (unsigned long)&xen_switch_to, - .leave_syscall = (unsigned long)&xen_leave_syscall, - .work_processed_syscall = (unsigned long)&xen_work_processed_syscall, - .leave_kernel = (unsigned long)&xen_leave_kernel, -}; - -/*************************************************************************** - * pv_iosapic_ops - * iosapic read/write hooks. - */ -static void -xen_pcat_compat_init(void) -{ - /* nothing */ -} - -static struct irq_chip* -xen_iosapic_get_irq_chip(unsigned long trigger) -{ - return NULL; -} - -static unsigned int -xen_iosapic_read(char __iomem *iosapic, unsigned int reg) -{ - struct physdev_apic apic_op; - int ret; - - apic_op.apic_physbase = (unsigned long)iosapic - - __IA64_UNCACHED_OFFSET; - apic_op.reg = reg; - ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); - if (ret) - return ret; - return apic_op.value; -} - -static void -xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) -{ - struct physdev_apic apic_op; - - apic_op.apic_physbase = (unsigned long)iosapic - - __IA64_UNCACHED_OFFSET; - apic_op.reg = reg; - apic_op.value = val; - HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op); -} - -static const struct pv_iosapic_ops xen_iosapic_ops __initdata = { - .pcat_compat_init = xen_pcat_compat_init, - .__get_irq_chip = xen_iosapic_get_irq_chip, - - .__read = xen_iosapic_read, - .__write = xen_iosapic_write, -}; - -/*************************************************************************** - * pv_ops initialization - */ - -void __init -xen_setup_pv_ops(void) -{ - xen_info_init(); - pv_info = xen_info; - pv_init_ops = xen_init_ops; - pv_cpu_ops = xen_cpu_ops; - pv_iosapic_ops = xen_iosapic_ops; - pv_irq_ops = xen_irq_ops; - pv_time_ops = xen_time_ops; - - paravirt_cpu_asm_init(&xen_cpu_asm_switch); -} diff --git a/trunk/arch/ia64/xen/xencomm.c b/trunk/arch/ia64/xen/xencomm.c deleted file mode 100644 index 1f5d7ac82e97..000000000000 --- a/trunk/arch/ia64/xen/xencomm.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2006 Hollis Blanchard , IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -static unsigned long kernel_virtual_offset; -static int is_xencomm_initialized; - -/* for xen early printk. It uses console io hypercall which uses xencomm. - * However early printk may use it before xencomm initialization. - */ -int -xencomm_is_initialized(void) -{ - return is_xencomm_initialized; -} - -void -xencomm_initialize(void) -{ - kernel_virtual_offset = KERNEL_START - ia64_tpa(KERNEL_START); - is_xencomm_initialized = 1; -} - -/* Translate virtual address to physical address. */ -unsigned long -xencomm_vtop(unsigned long vaddr) -{ - struct page *page; - struct vm_area_struct *vma; - - if (vaddr == 0) - return 0UL; - - if (REGION_NUMBER(vaddr) == 5) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *ptep; - - /* On ia64, TASK_SIZE refers to current. It is not initialized - during boot. - Furthermore the kernel is relocatable and __pa() doesn't - work on addresses. */ - if (vaddr >= KERNEL_START - && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) - return vaddr - kernel_virtual_offset; - - /* In kernel area -- virtually mapped. */ - pgd = pgd_offset_k(vaddr); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return ~0UL; - - pud = pud_offset(pgd, vaddr); - if (pud_none(*pud) || pud_bad(*pud)) - return ~0UL; - - pmd = pmd_offset(pud, vaddr); - if (pmd_none(*pmd) || pmd_bad(*pmd)) - return ~0UL; - - ptep = pte_offset_kernel(pmd, vaddr); - if (!ptep) - return ~0UL; - - return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK); - } - - if (vaddr > TASK_SIZE) { - /* percpu variables */ - if (REGION_NUMBER(vaddr) == 7 && - REGION_OFFSET(vaddr) >= (1ULL << IA64_MAX_PHYS_BITS)) - ia64_tpa(vaddr); - - /* kernel address */ - return __pa(vaddr); - } - - /* XXX double-check (lack of) locking */ - vma = find_extend_vma(current->mm, vaddr); - if (!vma) - return ~0UL; - - /* We assume the page is modified. */ - page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH); - if (!page) - return ~0UL; - - return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK); -} diff --git a/trunk/arch/ia64/xen/xenivt.S b/trunk/arch/ia64/xen/xenivt.S deleted file mode 100644 index 3e71d50584d9..000000000000 --- a/trunk/arch/ia64/xen/xenivt.S +++ /dev/null @@ -1,52 +0,0 @@ -/* - * arch/ia64/xen/ivt.S - * - * Copyright (C) 2005 Hewlett-Packard Co - * Dan Magenheimer - * - * Copyright (c) 2008 Isaku Yamahata - * VA Linux Systems Japan K.K. - * pv_ops. - */ - -#include -#include -#include - -#include "../kernel/minstate.h" - - .section .text,"ax" -GLOBAL_ENTRY(xen_event_callback) - mov r31=pr // prepare to save predicates - ;; - SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 - ;; - movl r3=XSI_PSR_IC - mov r14=1 - ;; - st4 [r3]=r14 - ;; - adds r3=8,r2 // set up second base pointer for SAVE_REST - srlz.i // ensure everybody knows psr.ic is back on - ;; - SAVE_REST - ;; -1: - alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group - add out0=16,sp // pass pointer to pt_regs as first arg - ;; - br.call.sptk.many b0=xen_evtchn_do_upcall - ;; - movl r20=XSI_PSR_I_ADDR - ;; - ld8 r20=[r20] - ;; - adds r20=-1,r20 // vcpu_info->evtchn_upcall_pending - ;; - ld1 r20=[r20] - ;; - cmp.ne p6,p0=r20,r0 // if there are pending events, - (p6) br.spnt.few 1b // call evtchn_do_upcall again. - br.sptk.many xen_leave_kernel // we know ia64_leave_kernel is - // paravirtualized as xen_leave_kernel -END(xen_event_callback) diff --git a/trunk/arch/ia64/xen/xensetup.S b/trunk/arch/ia64/xen/xensetup.S deleted file mode 100644 index 28fed1fcc079..000000000000 --- a/trunk/arch/ia64/xen/xensetup.S +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Support routines for Xen - * - * Copyright (C) 2005 Dan Magenheimer - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - .section .data.read_mostly - .align 8 - .global xen_domain_type -xen_domain_type: - data4 XEN_NATIVE_ASM - .previous - - __INIT -ENTRY(startup_xen) - // Calculate load offset. - // The constant, LOAD_OFFSET, can't be used because the boot - // loader doesn't always load to the LMA specified by the vmlinux.lds. - mov r9=ip // must be the first instruction to make sure - // that r9 = the physical address of startup_xen. - // Usually r9 = startup_xen - LOAD_OFFSET - movl r8=startup_xen - ;; - sub r9=r9,r8 // Usually r9 = -LOAD_OFFSET. - - mov r10=PARAVIRT_HYPERVISOR_TYPE_XEN - movl r11=_start - ;; - add r11=r11,r9 - movl r8=hypervisor_type - ;; - add r8=r8,r9 - mov b0=r11 - ;; - st8 [r8]=r10 - br.cond.sptk.many b0 - ;; -END(startup_xen) - - ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") - ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") - ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") - ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, data8.ua startup_xen - LOAD_OFFSET) - -#define isBP p3 // are we the Bootstrap Processor? - - .text - -GLOBAL_ENTRY(xen_setup_hook) - mov r8=XEN_PV_DOMAIN_ASM -(isBP) movl r9=xen_domain_type;; -(isBP) st4 [r9]=r8 - movl r10=xen_ivt;; - - mov cr.iva=r10 - - /* Set xsi base. */ -#define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600 -(isBP) mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA -(isBP) movl r28=XSI_BASE;; -(isBP) break 0x1000;; - - /* setup pv_ops */ -(isBP) mov r4=rp - ;; -(isBP) br.call.sptk.many rp=xen_setup_pv_ops - ;; -(isBP) mov rp=r4 - ;; - - br.ret.sptk.many rp - ;; -END(xen_setup_hook) diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index 644a70b1b04e..2bd1f6ef5db0 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -9,8 +9,6 @@ config PARISC def_bool y select HAVE_IDE select HAVE_OPROFILE - select RTC_CLASS - select RTC_DRV_PARISC help The PA-RISC microprocessor is designed by Hewlett-Packard and used in many of their workstations & servers (HP9000 700 and 800 series, diff --git a/trunk/arch/parisc/kernel/.gitignore b/trunk/arch/parisc/kernel/.gitignore deleted file mode 100644 index c5f676c3c224..000000000000 --- a/trunk/arch/parisc/kernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vmlinux.lds diff --git a/trunk/arch/parisc/kernel/asm-offsets.c b/trunk/arch/parisc/kernel/asm-offsets.c index 699cf8ef2118..3efc0b73e4ff 100644 --- a/trunk/arch/parisc/kernel/asm-offsets.c +++ b/trunk/arch/parisc/kernel/asm-offsets.c @@ -290,8 +290,5 @@ int main(void) DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); - BLANK(); - DEFINE(ASM_PDC_RESULT_SIZE, NUM_PDC_RESULT * sizeof(unsigned long)); - BLANK(); return 0; } diff --git a/trunk/arch/parisc/kernel/firmware.c b/trunk/arch/parisc/kernel/firmware.c index 03f26bd75bd8..7177a6cd1b7f 100644 --- a/trunk/arch/parisc/kernel/firmware.c +++ b/trunk/arch/parisc/kernel/firmware.c @@ -71,8 +71,8 @@ #include /* for boot_cpu_data */ static DEFINE_SPINLOCK(pdc_lock); -extern unsigned long pdc_result[NUM_PDC_RESULT]; -extern unsigned long pdc_result2[NUM_PDC_RESULT]; +static unsigned long pdc_result[32] __attribute__ ((aligned (8))); +static unsigned long pdc_result2[32] __attribute__ ((aligned (8))); #ifdef CONFIG_64BIT #define WIDE_FIRMWARE 0x1 @@ -150,40 +150,26 @@ static void convert_to_wide(unsigned long *addr) #endif } -#ifdef CONFIG_64BIT -void __init set_firmware_width_unlocked(void) -{ - int ret; - - ret = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, - __pa(pdc_result), 0); - convert_to_wide(pdc_result); - if (pdc_result[0] != NARROW_FIRMWARE) - parisc_narrow_firmware = 0; -} - /** * set_firmware_width - Determine if the firmware is wide or narrow. * - * This function must be called before any pdc_* function that uses the - * convert_to_wide function. + * This function must be called before any pdc_* function that uses the convert_to_wide + * function. */ void __init set_firmware_width(void) { +#ifdef CONFIG_64BIT + int retval; unsigned long flags; - spin_lock_irqsave(&pdc_lock, flags); - set_firmware_width_unlocked(); - spin_unlock_irqrestore(&pdc_lock, flags); -} -#else -void __init set_firmware_width_unlocked(void) { - return; -} -void __init set_firmware_width(void) { - return; + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + if(pdc_result[0] != NARROW_FIRMWARE) + parisc_narrow_firmware = 0; + spin_unlock_irqrestore(&pdc_lock, flags); +#endif } -#endif /*CONFIG_64BIT*/ /** * pdc_emergency_unlock - Unlock the linux pdc lock @@ -302,20 +288,6 @@ int pdc_chassis_warn(unsigned long *warn) return retval; } -int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) -{ - int ret; - - ret = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result)); - convert_to_wide(pdc_result); - pdc_coproc_info->ccr_functional = pdc_result[0]; - pdc_coproc_info->ccr_present = pdc_result[1]; - pdc_coproc_info->revision = pdc_result[17]; - pdc_coproc_info->model = pdc_result[18]; - - return ret; -} - /** * pdc_coproc_cfg - To identify coprocessors attached to the processor. * @pdc_coproc_info: Return buffer address. @@ -325,14 +297,19 @@ int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) */ int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) { - int ret; + int retval; unsigned long flags; - spin_lock_irqsave(&pdc_lock, flags); - ret = pdc_coproc_cfg_unlocked(pdc_coproc_info); - spin_unlock_irqrestore(&pdc_lock, flags); + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result)); + convert_to_wide(pdc_result); + pdc_coproc_info->ccr_functional = pdc_result[0]; + pdc_coproc_info->ccr_present = pdc_result[1]; + pdc_coproc_info->revision = pdc_result[17]; + pdc_coproc_info->model = pdc_result[18]; + spin_unlock_irqrestore(&pdc_lock, flags); - return ret; + return retval; } /** diff --git a/trunk/arch/parisc/kernel/head.S b/trunk/arch/parisc/kernel/head.S index 0e3d9f9b9e33..a84e31e82876 100644 --- a/trunk/arch/parisc/kernel/head.S +++ b/trunk/arch/parisc/kernel/head.S @@ -121,7 +121,7 @@ $pgt_fill_loop: copy %r0,%r2 /* And the RFI Target address too */ - load32 start_parisc,%r11 + load32 start_kernel,%r11 /* And the initial task pointer */ load32 init_thread_union,%r6 diff --git a/trunk/arch/parisc/kernel/ptrace.c b/trunk/arch/parisc/kernel/ptrace.c index 90904f9dfc50..49c637970789 100644 --- a/trunk/arch/parisc/kernel/ptrace.c +++ b/trunk/arch/parisc/kernel/ptrace.c @@ -4,7 +4,6 @@ * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. * Copyright (C) 2000 Matthew Wilcox * Copyright (C) 2000 David Huggins-Daines - * Copyright (C) 2008 Helge Deller */ #include @@ -28,149 +27,15 @@ /* PSW bits we allow the debugger to modify */ #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *task) -{ - task->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); - - /* make sure the trap bits are not set */ - pa_psw(task)->r = 0; - pa_psw(task)->t = 0; - pa_psw(task)->h = 0; - pa_psw(task)->l = 0; -} - -/* - * The following functions are called by ptrace_resume() when - * enabling or disabling single/block tracing. - */ -void user_disable_single_step(struct task_struct *task) -{ - ptrace_disable(task); -} - -void user_enable_single_step(struct task_struct *task) -{ - task->ptrace &= ~PT_BLOCKSTEP; - task->ptrace |= PT_SINGLESTEP; - - if (pa_psw(task)->n) { - struct siginfo si; - - /* Nullified, just crank over the queue. */ - task_regs(task)->iaoq[0] = task_regs(task)->iaoq[1]; - task_regs(task)->iasq[0] = task_regs(task)->iasq[1]; - task_regs(task)->iaoq[1] = task_regs(task)->iaoq[0] + 4; - pa_psw(task)->n = 0; - pa_psw(task)->x = 0; - pa_psw(task)->y = 0; - pa_psw(task)->z = 0; - pa_psw(task)->b = 0; - ptrace_disable(task); - /* Don't wake up the task, but let the - parent know something happened. */ - si.si_code = TRAP_TRACE; - si.si_addr = (void __user *) (task_regs(task)->iaoq[0] & ~3); - si.si_signo = SIGTRAP; - si.si_errno = 0; - force_sig_info(SIGTRAP, &si, task); - /* notify_parent(task, SIGCHLD); */ - return; - } - - /* Enable recovery counter traps. The recovery counter - * itself will be set to zero on a task switch. If the - * task is suspended on a syscall then the syscall return - * path will overwrite the recovery counter with a suitable - * value such that it traps once back in user space. We - * disable interrupts in the tasks PSW here also, to avoid - * interrupts while the recovery counter is decrementing. - */ - pa_psw(task)->r = 1; - pa_psw(task)->t = 0; - pa_psw(task)->h = 0; - pa_psw(task)->l = 0; -} - -void user_enable_block_step(struct task_struct *task) -{ - task->ptrace &= ~PT_SINGLESTEP; - task->ptrace |= PT_BLOCKSTEP; - - /* Enable taken branch trap. */ - pa_psw(task)->r = 0; - pa_psw(task)->t = 1; - pa_psw(task)->h = 0; - pa_psw(task)->l = 0; -} - -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - unsigned long tmp; - long ret = -EIO; - - switch (request) { - - /* Read the word at location addr in the USER area. For ptraced - processes, the kernel saves all regs on a syscall. */ - case PTRACE_PEEKUSR: - if ((addr & (sizeof(long)-1)) || - (unsigned long) addr >= sizeof(struct pt_regs)) - break; - tmp = *(unsigned long *) ((char *) task_regs(child) + addr); - ret = put_user(tmp, (unsigned long *) data); - break; - - /* Write the word at location addr in the USER area. This will need - to change when the kernel no longer saves all regs on a syscall. - FIXME. There is a problem at the moment in that r3-r18 are only - saved if the process is ptraced on syscall entry, and even then - those values are overwritten by actual register values on syscall - exit. */ - case PTRACE_POKEUSR: - /* Some register values written here may be ignored in - * entry.S:syscall_restore_rfi; e.g. iaoq is written with - * r31/r31+4, and not with the values in pt_regs. - */ - if (addr == PT_PSW) { - /* Allow writing to Nullify, Divide-step-correction, - * and carry/borrow bits. - * BEWARE, if you set N, and then single step, it won't - * stop on the nullified instruction. - */ - data &= USER_PSW_BITS; - task_regs(child)->gr[0] &= ~USER_PSW_BITS; - task_regs(child)->gr[0] |= data; - ret = 0; - break; - } - - if ((addr & (sizeof(long)-1)) || - (unsigned long) addr >= sizeof(struct pt_regs)) - break; - if ((addr >= PT_GR1 && addr <= PT_GR31) || - addr == PT_IAOQ0 || addr == PT_IAOQ1 || - (addr >= PT_FR0 && addr <= PT_FR31 + 4) || - addr == PT_SAR) { - *(unsigned long *) ((char *) task_regs(child) + addr) = data; - ret = 0; - } - break; - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} +#undef DEBUG_PTRACE +#ifdef DEBUG_PTRACE +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif -#ifdef CONFIG_COMPAT +#ifdef CONFIG_64BIT /* This function is needed to translate 32 bit pt_regs offsets in to * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel @@ -196,25 +61,106 @@ static long translate_usr_offset(long offset) else return -1; } +#endif -long compat_arch_ptrace(struct task_struct *child, compat_long_t request, - compat_ulong_t addr, compat_ulong_t data) +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) { - compat_uint_t tmp; - long ret = -EIO; + /* make sure the trap bits are not set */ + pa_psw(child)->r = 0; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; +} + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + long ret; +#ifdef DEBUG_PTRACE + long oaddr=addr, odata=data; +#endif switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { +#ifdef CONFIG_64BIT + if (__is_compat_task(child)) { + int copied; + unsigned int tmp; + + addr &= 0xffffffffL; + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + goto out_tsk; + ret = put_user(tmp,(unsigned int *) data); + DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", + request == PTRACE_PEEKTEXT ? "TEXT" : "DATA", + pid, oaddr, odata, ret, tmp); + } + else +#endif + ret = generic_ptrace_peekdata(child, addr, data); + goto out_tsk; + } - case PTRACE_PEEKUSR: - if (addr & (sizeof(compat_uint_t)-1)) - break; - addr = translate_usr_offset(addr); - if (addr < 0) - break; + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; +#ifdef CONFIG_64BIT + if (__is_compat_task(child)) { + unsigned int tmp = (unsigned int)data; + DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", + request == PTRACE_POKETEXT ? "TEXT" : "DATA", + pid, oaddr, odata); + addr &= 0xffffffffL; + if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp)) + goto out_tsk; + } + else +#endif + { + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + goto out_tsk; + } + ret = -EIO; + goto out_tsk; + + /* Read the word at location addr in the USER area. For ptraced + processes, the kernel saves all regs on a syscall. */ + case PTRACE_PEEKUSR: { + ret = -EIO; +#ifdef CONFIG_64BIT + if (__is_compat_task(child)) { + unsigned int tmp; + + if (addr & (sizeof(int)-1)) + goto out_tsk; + if ((addr = translate_usr_offset(addr)) < 0) + goto out_tsk; + + tmp = *(unsigned int *) ((char *) task_regs(child) + addr); + ret = put_user(tmp, (unsigned int *) data); + DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", + pid, oaddr, odata, ret, addr, tmp); + } + else +#endif + { + unsigned long tmp; - tmp = *(compat_uint_t *) ((char *) task_regs(child) + addr); - ret = put_user(tmp, (compat_uint_t *) (unsigned long) data); - break; + if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + tmp = *(unsigned long *) ((char *) task_regs(child) + addr); + ret = put_user(tmp, (unsigned long *) data); + } + goto out_tsk; + } /* Write the word at location addr in the USER area. This will need to change when the kernel no longer saves all regs on a syscall. @@ -223,46 +169,185 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, those values are overwritten by actual register values on syscall exit. */ case PTRACE_POKEUSR: + ret = -EIO; /* Some register values written here may be ignored in * entry.S:syscall_restore_rfi; e.g. iaoq is written with * r31/r31+4, and not with the values in pt_regs. */ + /* PT_PSW=0, so this is valid for 32 bit processes under 64 + * bit kernels. + */ if (addr == PT_PSW) { - /* Since PT_PSW==0, it is valid for 32 bit processes - * under 64 bit kernels as well. + /* PT_PSW=0, so this is valid for 32 bit processes + * under 64 bit kernels. + * + * Allow writing to Nullify, Divide-step-correction, + * and carry/borrow bits. + * BEWARE, if you set N, and then single step, it won't + * stop on the nullified instruction. */ - ret = arch_ptrace(child, request, addr, data); - } else { - if (addr & (sizeof(compat_uint_t)-1)) - break; - addr = translate_usr_offset(addr); - if (addr < 0) - break; + DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", + pid, oaddr, odata); + data &= USER_PSW_BITS; + task_regs(child)->gr[0] &= ~USER_PSW_BITS; + task_regs(child)->gr[0] |= data; + ret = 0; + goto out_tsk; + } +#ifdef CONFIG_64BIT + if (__is_compat_task(child)) { + if (addr & (sizeof(int)-1)) + goto out_tsk; + if ((addr = translate_usr_offset(addr)) < 0) + goto out_tsk; + DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", + pid, oaddr, odata, addr); if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { /* Special case, fp regs are 64 bits anyway */ - *(__u64 *) ((char *) task_regs(child) + addr) = data; + *(unsigned int *) ((char *) task_regs(child) + addr) = data; ret = 0; } else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 || addr == PT_SAR+4) { /* Zero the top 32 bits */ - *(__u32 *) ((char *) task_regs(child) + addr - 4) = 0; - *(__u32 *) ((char *) task_regs(child) + addr) = data; + *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0; + *(unsigned int *) ((char *) task_regs(child) + addr) = data; ret = 0; } + goto out_tsk; } - break; + else +#endif + { + if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + if ((addr >= PT_GR1 && addr <= PT_GR31) || + addr == PT_IAOQ0 || addr == PT_IAOQ1 || + (addr >= PT_FR0 && addr <= PT_FR31 + 4) || + addr == PT_SAR) { + *(unsigned long *) ((char *) task_regs(child) + addr) = data; + ret = 0; + } + goto out_tsk; + } + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: + ret = -EIO; + DBG("sys_ptrace(%s)\n", + request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"); + if (!valid_signal(data)) + goto out_tsk; + child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); + if (request == PTRACE_SYSCALL) { + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } else { + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } + child->exit_code = data; + goto out_wake_notrap; + + case PTRACE_KILL: + /* + * make the child exit. Best I can do is send it a + * sigkill. perhaps it should be put in the status + * that it wants to exit. + */ + ret = 0; + DBG("sys_ptrace(KILL)\n"); + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ + goto out_tsk; + child->exit_code = SIGKILL; + goto out_wake_notrap; + + case PTRACE_SINGLEBLOCK: + DBG("sys_ptrace(SINGLEBLOCK)\n"); + ret = -EIO; + if (!valid_signal(data)) + goto out_tsk; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->ptrace &= ~PT_SINGLESTEP; + child->ptrace |= PT_BLOCKSTEP; + child->exit_code = data; + + /* Enable taken branch trap. */ + pa_psw(child)->r = 0; + pa_psw(child)->t = 1; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; + goto out_wake; + + case PTRACE_SINGLESTEP: + DBG("sys_ptrace(SINGLESTEP)\n"); + ret = -EIO; + if (!valid_signal(data)) + goto out_tsk; + + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->ptrace &= ~PT_BLOCKSTEP; + child->ptrace |= PT_SINGLESTEP; + child->exit_code = data; + + if (pa_psw(child)->n) { + struct siginfo si; + + /* Nullified, just crank over the queue. */ + task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1]; + task_regs(child)->iasq[0] = task_regs(child)->iasq[1]; + task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4; + pa_psw(child)->n = 0; + pa_psw(child)->x = 0; + pa_psw(child)->y = 0; + pa_psw(child)->z = 0; + pa_psw(child)->b = 0; + ptrace_disable(child); + /* Don't wake up the child, but let the + parent know something happened. */ + si.si_code = TRAP_TRACE; + si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3); + si.si_signo = SIGTRAP; + si.si_errno = 0; + force_sig_info(SIGTRAP, &si, child); + //notify_parent(child, SIGCHLD); + //ret = 0; + goto out_wake; + } + + /* Enable recovery counter traps. The recovery counter + * itself will be set to zero on a task switch. If the + * task is suspended on a syscall then the syscall return + * path will overwrite the recovery counter with a suitable + * value such that it traps once back in user space. We + * disable interrupts in the childs PSW here also, to avoid + * interrupts while the recovery counter is decrementing. + */ + pa_psw(child)->r = 1; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; + /* give it a chance to run. */ + goto out_wake; + + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + goto out_tsk; default: - ret = compat_ptrace_request(child, request, addr, data); - break; + ret = ptrace_request(child, request, addr, data); + goto out_tsk; } +out_wake_notrap: + ptrace_disable(child); +out_wake: + wake_up_process(child); + ret = 0; +out_tsk: + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + request, pid, oaddr, odata, ret); return ret; } -#endif - void syscall_trace(void) { diff --git a/trunk/arch/parisc/kernel/real2.S b/trunk/arch/parisc/kernel/real2.S index 5f3d3a1f9037..7a92695d95a6 100644 --- a/trunk/arch/parisc/kernel/real2.S +++ b/trunk/arch/parisc/kernel/real2.S @@ -8,24 +8,12 @@ * */ -#include #include #include -#include #include - .section .bss - - .export pdc_result - .export pdc_result2 - .align 8 -pdc_result: - .block ASM_PDC_RESULT_SIZE -pdc_result2: - .block ASM_PDC_RESULT_SIZE - .export real_stack .export real32_stack .export real64_stack diff --git a/trunk/arch/parisc/kernel/setup.c b/trunk/arch/parisc/kernel/setup.c index 7d27853ff8c8..39e7c5a5946a 100644 --- a/trunk/arch/parisc/kernel/setup.c +++ b/trunk/arch/parisc/kernel/setup.c @@ -44,7 +44,6 @@ #include #include #include -#include static char __initdata command_line[COMMAND_LINE_SIZE]; @@ -124,7 +123,6 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_64BIT extern int parisc_narrow_firmware; #endif - unwind_init(); init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */ @@ -370,31 +368,6 @@ static int __init parisc_init(void) return 0; } -arch_initcall(parisc_init); - -void start_parisc(void) -{ - extern void start_kernel(void); - - int ret, cpunum; - struct pdc_coproc_cfg coproc_cfg; - - cpunum = smp_processor_id(); - - set_firmware_width_unlocked(); - ret = pdc_coproc_cfg_unlocked(&coproc_cfg); - if (ret >= 0 && coproc_cfg.ccr_functional) { - mtctl(coproc_cfg.ccr_functional, 10); - - cpu_data[cpunum].fp_rev = coproc_cfg.revision; - cpu_data[cpunum].fp_model = coproc_cfg.model; - - asm volatile ("fstd %fr0,8(%sp)"); - } else { - panic("must have an fpu to boot linux"); - } +arch_initcall(parisc_init); - start_kernel(); - // not reached -} diff --git a/trunk/arch/parisc/kernel/syscall_table.S b/trunk/arch/parisc/kernel/syscall_table.S index 303d2b647e41..c7e59f548817 100644 --- a/trunk/arch/parisc/kernel/syscall_table.S +++ b/trunk/arch/parisc/kernel/syscall_table.S @@ -87,7 +87,7 @@ ENTRY_SAME(setuid) ENTRY_SAME(getuid) ENTRY_COMP(stime) /* 25 */ - ENTRY_COMP(ptrace) + ENTRY_SAME(ptrace) ENTRY_SAME(alarm) /* see stat comment */ ENTRY_COMP(newfstat) @@ -407,12 +407,6 @@ ENTRY_SAME(timerfd_create) ENTRY_COMP(timerfd_settime) ENTRY_COMP(timerfd_gettime) - ENTRY_COMP(signalfd4) - ENTRY_SAME(eventfd2) /* 310 */ - ENTRY_SAME(epoll_create1) - ENTRY_SAME(dup3) - ENTRY_SAME(pipe2) - ENTRY_SAME(inotify_init1) /* Nothing yet */ diff --git a/trunk/arch/parisc/kernel/time.c b/trunk/arch/parisc/kernel/time.c index 4d09203bc693..24be86bba94d 100644 --- a/trunk/arch/parisc/kernel/time.c +++ b/trunk/arch/parisc/kernel/time.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -216,24 +215,6 @@ void __init start_cpu_itimer(void) cpu_data[cpu].it_value = next_tick; } -struct platform_device rtc_parisc_dev = { - .name = "rtc-parisc", - .id = -1, -}; - -static int __init rtc_init(void) -{ - int ret; - - ret = platform_device_register(&rtc_parisc_dev); - if (ret < 0) - printk(KERN_ERR "unable to register rtc device...\n"); - - /* not necessarily an error */ - return 0; -} -module_init(rtc_init); - void __init time_init(void) { static struct pdc_tod tod_data; @@ -264,3 +245,4 @@ void __init time_init(void) xtime.tv_nsec = 0; } } + diff --git a/trunk/arch/parisc/kernel/unwind.c b/trunk/arch/parisc/kernel/unwind.c index 6773c582e457..701b2d2d8882 100644 --- a/trunk/arch/parisc/kernel/unwind.c +++ b/trunk/arch/parisc/kernel/unwind.c @@ -170,7 +170,7 @@ void unwind_table_remove(struct unwind_table *table) } /* Called from setup_arch to import the kernel unwind info */ -int unwind_init(void) +static int unwind_init(void) { long start, stop; register unsigned long gp __asm__ ("r27"); @@ -417,3 +417,5 @@ int unwind_to_user(struct unwind_frame_info *info) return ret; } + +module_init(unwind_init); diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 5b1527883fcb..9391199d9e77 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -19,6 +19,9 @@ config WORD_SIZE default 64 if PPC64 default 32 if !PPC64 +config PPC_MERGE + def_bool y + config ARCH_PHYS_ADDR_T_64BIT def_bool PPC64 || PHYS_64BIT @@ -323,11 +326,13 @@ config KEXEC config CRASH_DUMP bool "Build a kdump crash kernel" - depends on PPC_MULTIPLATFORM && PPC64 && RELOCATABLE + depends on PPC_MULTIPLATFORM && PPC64 help Build a kernel suitable for use as a kdump capture kernel. - The same kernel binary can be used as production kernel and dump - capture kernel. + The kernel will be linked at a different address than normal, and + so can only be used for Kdump. + + Don't change this unless you know what you are doing. config PHYP_DUMP bool "Hypervisor-assisted dump (EXPERIMENTAL)" @@ -827,9 +832,11 @@ config PAGE_OFFSET default "0xc000000000000000" config KERNEL_START hex + default "0xc000000002000000" if CRASH_DUMP default "0xc000000000000000" config PHYSICAL_START hex + default "0x02000000" if CRASH_DUMP default "0x00000000" endif diff --git a/trunk/arch/powerpc/boot/Makefile b/trunk/arch/powerpc/boot/Makefile index 8fc6d72849ae..aac1406ccba5 100644 --- a/trunk/arch/powerpc/boot/Makefile +++ b/trunk/arch/powerpc/boot/Makefile @@ -68,8 +68,7 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \ - virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \ - cuboot-acadia.c + virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) @@ -212,7 +211,6 @@ image-$(CONFIG_DEFAULT_UIMAGE) += uImage # Board ports in arch/powerpc/platform/40x/Kconfig image-$(CONFIG_EP405) += dtbImage.ep405 image-$(CONFIG_WALNUT) += treeImage.walnut -image-$(CONFIG_ACADIA) += cuImage.acadia # Board ports in arch/powerpc/platform/44x/Kconfig image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony @@ -321,9 +319,6 @@ $(obj)/zImage.iseries: vmlinux $(obj)/uImage: vmlinux $(wrapperbits) $(call if_changed,wrap,uboot) -$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) - $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) - $(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb) diff --git a/trunk/arch/powerpc/boot/addnote.c b/trunk/arch/powerpc/boot/addnote.c index 3091d1d21aef..dcc9ab2ca823 100644 --- a/trunk/arch/powerpc/boot/addnote.c +++ b/trunk/arch/powerpc/boot/addnote.c @@ -11,7 +11,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Usage: addnote [-r realbase] zImage [note.elf] + * Usage: addnote zImage [note.elf] * * If note.elf is supplied, it is the name of an ELF file that contains * an RPA note to use instead of the built-in one. Alternatively, the @@ -153,31 +153,18 @@ unsigned char *read_rpanote(const char *fname, int *nnp) int main(int ac, char **av) { - int fd, n, i, ai; + int fd, n, i; int ph, ps, np; int nnote, nnote2, ns; unsigned char *rpap; - char *p, *endp; - - ai = 1; - if (ac >= ai + 2 && strcmp(av[ai], "-r") == 0) { - /* process -r realbase */ - p = av[ai + 1]; - descr[1] = strtol(p, &endp, 16); - if (endp == p || *endp != 0) { - fprintf(stderr, "Can't parse -r argument '%s' as hex\n", - p); - exit(1); - } - ai += 2; - } - if (ac != ai + 1 && ac != ai + 2) { - fprintf(stderr, "Usage: %s [-r realbase] elf-file [rpanote.elf]\n", av[0]); + + if (ac != 2 && ac != 3) { + fprintf(stderr, "Usage: %s elf-file [rpanote.elf]\n", av[0]); exit(1); } - fd = open(av[ai], O_RDWR); + fd = open(av[1], O_RDWR); if (fd < 0) { - perror(av[ai]); + perror(av[1]); exit(1); } @@ -197,12 +184,12 @@ main(int ac, char **av) if (buf[E_IDENT+EI_CLASS] != ELFCLASS32 || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) { fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", - av[ai]); + av[1]); exit(1); } - if (ac == ai + 2) - rpap = read_rpanote(av[ai + 1], &nnote2); + if (ac == 3) + rpap = read_rpanote(av[2], &nnote2); ph = GET_32BE(buf, E_PHOFF); ps = GET_16BE(buf, E_PHENTSIZE); @@ -215,7 +202,7 @@ main(int ac, char **av) for (i = 0; i < np; ++i) { if (GET_32BE(buf, ph + PH_TYPE) == PT_NOTE) { fprintf(stderr, "%s already has a note entry\n", - av[ai]); + av[1]); exit(0); } ph += ps; @@ -273,18 +260,18 @@ main(int ac, char **av) exit(1); } if (i < n) { - fprintf(stderr, "%s: write truncated\n", av[ai]); + fprintf(stderr, "%s: write truncated\n", av[1]); exit(1); } exit(0); notelf: - fprintf(stderr, "%s does not appear to be an ELF file\n", av[ai]); + fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]); exit(1); nospace: fprintf(stderr, "sorry, I can't find space in %s to put the note\n", - av[ai]); + av[1]); exit(1); } diff --git a/trunk/arch/powerpc/boot/cuboot-52xx.c b/trunk/arch/powerpc/boot/cuboot-52xx.c index 4c42ec8687be..a8611546a656 100644 --- a/trunk/arch/powerpc/boot/cuboot-52xx.c +++ b/trunk/arch/powerpc/boot/cuboot-52xx.c @@ -37,10 +37,6 @@ static void platform_fixups(void) * this can do a simple path lookup. */ soc = find_node_by_devtype(NULL, "soc"); - if (!soc) - soc = find_node_by_compatible(NULL, "fsl,mpc5200-immr"); - if (!soc) - soc = find_node_by_compatible(NULL, "fsl,mpc5200b-immr"); if (soc) { setprop(soc, "bus-frequency", &bd.bi_ipbfreq, sizeof(bd.bi_ipbfreq)); diff --git a/trunk/arch/powerpc/boot/cuboot-acadia.c b/trunk/arch/powerpc/boot/cuboot-acadia.c deleted file mode 100644 index 0634aba6348a..000000000000 --- a/trunk/arch/powerpc/boot/cuboot-acadia.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Old U-boot compatibility for Acadia - * - * Author: Josh Boyer - * - * Copyright 2008 IBM Corporation - * - * 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 "ops.h" -#include "io.h" -#include "dcr.h" -#include "stdio.h" -#include "4xx.h" -#include "44x.h" -#include "cuboot.h" - -#define TARGET_4xx -#include "ppcboot.h" - -static bd_t bd; - -#define CPR_PERD0_SPIDV_MASK 0x000F0000 /* SPI Clock Divider */ - -#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */ - -#define PLLD_FBDV_MASK 0x1F000000 /* PLL feedback divider value */ -#define PLLD_FWDVA_MASK 0x000F0000 /* PLL forward divider A value */ -#define PLLD_FWDVB_MASK 0x00000700 /* PLL forward divider B value */ - -#define PRIMAD_CPUDV_MASK 0x0F000000 /* CPU Clock Divisor Mask */ -#define PRIMAD_PLBDV_MASK 0x000F0000 /* PLB Clock Divisor Mask */ -#define PRIMAD_OPBDV_MASK 0x00000F00 /* OPB Clock Divisor Mask */ -#define PRIMAD_EBCDV_MASK 0x0000000F /* EBC Clock Divisor Mask */ - -#define PERD0_PWMDV_MASK 0xFF000000 /* PWM Divider Mask */ -#define PERD0_SPIDV_MASK 0x000F0000 /* SPI Divider Mask */ -#define PERD0_U0DV_MASK 0x0000FF00 /* UART 0 Divider Mask */ -#define PERD0_U1DV_MASK 0x000000FF /* UART 1 Divider Mask */ - -static void get_clocks(void) -{ - unsigned long sysclk, cpr_plld, cpr_pllc, cpr_primad, plloutb, i; - unsigned long pllFwdDiv, pllFwdDivB, pllFbkDiv, pllPlbDiv, pllExtBusDiv; - unsigned long pllOpbDiv, freqEBC, freqUART, freqOPB; - unsigned long div; /* total divisor udiv * bdiv */ - unsigned long umin; /* minimum udiv */ - unsigned short diff; /* smallest diff */ - unsigned long udiv; /* best udiv */ - unsigned short idiff; /* current diff */ - unsigned short ibdiv; /* current bdiv */ - unsigned long est; /* current estimate */ - unsigned long baud; - void *np; - - /* read the sysclk value from the CPLD */ - sysclk = (in_8((unsigned char *)0x80000000) == 0xc) ? 66666666 : 33333000; - - /* - * Read PLL Mode registers - */ - cpr_plld = CPR0_READ(DCRN_CPR0_PLLD); - cpr_pllc = CPR0_READ(DCRN_CPR0_PLLC); - - /* - * Determine forward divider A - */ - pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16); - - /* - * Determine forward divider B - */ - pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8); - if (pllFwdDivB == 0) - pllFwdDivB = 8; - - /* - * Determine FBK_DIV. - */ - pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24); - if (pllFbkDiv == 0) - pllFbkDiv = 256; - - /* - * Read CPR_PRIMAD register - */ - cpr_primad = CPR0_READ(DCRN_CPR0_PRIMAD); - - /* - * Determine PLB_DIV. - */ - pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16); - if (pllPlbDiv == 0) - pllPlbDiv = 16; - - /* - * Determine EXTBUS_DIV. - */ - pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK); - if (pllExtBusDiv == 0) - pllExtBusDiv = 16; - - /* - * Determine OPB_DIV. - */ - pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8); - if (pllOpbDiv == 0) - pllOpbDiv = 16; - - /* There is a bug in U-Boot that prevents us from using - * bd.bi_opbfreq because U-Boot doesn't populate it for - * 405EZ. We get to calculate it, yay! - */ - freqOPB = (sysclk *pllFbkDiv) /pllOpbDiv; - - freqEBC = (sysclk * pllFbkDiv) / pllExtBusDiv; - - plloutb = ((sysclk * ((cpr_pllc & PLLC_SRC_MASK) ? - pllFwdDivB : pllFwdDiv) * - pllFbkDiv) / pllFwdDivB); - - np = find_node_by_alias("serial0"); - if (getprop(np, "current-speed", &baud, sizeof(baud)) != sizeof(baud)) - fatal("no current-speed property\n\r"); - - udiv = 256; /* Assume lowest possible serial clk */ - div = plloutb / (16 * baud); /* total divisor */ - umin = (plloutb / freqOPB) << 1; /* 2 x OPB divisor */ - diff = 256; /* highest possible */ - - /* i is the test udiv value -- start with the largest - * possible (256) to minimize serial clock and constrain - * search to umin. - */ - for (i = 256; i > umin; i--) { - ibdiv = div / i; - est = i * ibdiv; - idiff = (est > div) ? (est-div) : (div-est); - if (idiff == 0) { - udiv = i; - break; /* can't do better */ - } else if (idiff < diff) { - udiv = i; /* best so far */ - diff = idiff; /* update lowest diff*/ - } - } - freqUART = plloutb / udiv; - - dt_fixup_cpu_clocks(bd.bi_procfreq, bd.bi_intfreq, bd.bi_plb_busfreq); - dt_fixup_clock("/plb/ebc", freqEBC); - dt_fixup_clock("/plb/opb", freqOPB); - dt_fixup_clock("/plb/opb/serial@ef600300", freqUART); - dt_fixup_clock("/plb/opb/serial@ef600400", freqUART); -} - -static void acadia_fixups(void) -{ - dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); - get_clocks(); - dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); -} - -void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - CUBOOT_INIT(); - platform_ops.fixups = acadia_fixups; - platform_ops.exit = ibm40x_dbcr_reset; - fdt_init(_dtb_start); - serial_console_init(); -} diff --git a/trunk/arch/powerpc/boot/dts/acadia.dts b/trunk/arch/powerpc/boot/dts/acadia.dts deleted file mode 100644 index 57291f61ffe7..000000000000 --- a/trunk/arch/powerpc/boot/dts/acadia.dts +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Device Tree Source for AMCC Acadia (405EZ) - * - * Copyright IBM Corp. 2008 - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -/dts-v1/; - -/ { - #address-cells = <1>; - #size-cells = <1>; - model = "amcc,acadia"; - compatible = "amcc,acadia"; - dcr-parent = <&{/cpus/cpu@0}>; - - aliases { - ethernet0 = &EMAC0; - serial0 = &UART0; - serial1 = &UART1; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - model = "PowerPC,405EZ"; - reg = <0x0>; - clock-frequency = <0>; /* Filled in by wrapper */ - timebase-frequency = <0>; /* Filled in by wrapper */ - i-cache-line-size = <32>; - d-cache-line-size = <32>; - i-cache-size = <16384>; - d-cache-size = <16384>; - dcr-controller; - dcr-access-method = "native"; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x0>; /* Filled in by wrapper */ - }; - - UIC0: interrupt-controller { - compatible = "ibm,uic-405ez", "ibm,uic"; - interrupt-controller; - dcr-reg = <0x0c0 0x009>; - cell-index = <0>; - #address-cells = <0>; - #size-cells = <0>; - #interrupt-cells = <2>; - }; - - plb { - compatible = "ibm,plb-405ez", "ibm,plb3"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - clock-frequency = <0>; /* Filled in by wrapper */ - - MAL0: mcmal { - compatible = "ibm,mcmal-405ez", "ibm,mcmal"; - dcr-reg = <0x380 0x62>; - num-tx-chans = <1>; - num-rx-chans = <1>; - interrupt-parent = <&UIC0>; - /* 405EZ has only 3 interrupts to the UIC, as - * SERR, TXDE, and RXDE are or'd together into - * one UIC bit - */ - interrupts = < - 0x13 0x4 /* TXEOB */ - 0x15 0x4 /* RXEOB */ - 0x12 0x4 /* SERR, TXDE, RXDE */>; - }; - - POB0: opb { - compatible = "ibm,opb-405ez", "ibm,opb"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - dcr-reg = <0x0a 0x05>; - clock-frequency = <0>; /* Filled in by wrapper */ - - UART0: serial@ef600300 { - device_type = "serial"; - compatible = "ns16550"; - reg = <0xef600300 0x8>; - virtual-reg = <0xef600300>; - clock-frequency = <0>; /* Filled in by wrapper */ - current-speed = <115200>; - interrupt-parent = <&UIC0>; - interrupts = <0x5 0x4>; - }; - - UART1: serial@ef600400 { - device_type = "serial"; - compatible = "ns16550"; - reg = <0xef600400 0x8>; - clock-frequency = <0>; /* Filled in by wrapper */ - current-speed = <115200>; - interrupt-parent = <&UIC0>; - interrupts = <0x6 0x4>; - }; - - IIC: i2c@ef600500 { - compatible = "ibm,iic-405ez", "ibm,iic"; - reg = <0xef600500 0x11>; - interrupt-parent = <&UIC0>; - interrupts = <0xa 0x4>; - }; - - GPIO0: gpio@ef600700 { - compatible = "ibm,gpio-405ez"; - reg = <0xef600700 0x20>; - }; - - GPIO1: gpio@ef600800 { - compatible = "ibm,gpio-405ez"; - reg = <0xef600800 0x20>; - }; - - EMAC0: ethernet@ef600900 { - device_type = "network"; - compatible = "ibm,emac-405ez", "ibm,emac"; - interrupt-parent = <&UIC0>; - interrupts = < - 0x10 0x4 /* Ethernet */ - 0x11 0x4 /* Ethernet Wake up */>; - local-mac-address = [000000000000]; /* Filled in by wrapper */ - reg = <0xef600900 0x70>; - mal-device = <&MAL0>; - mal-tx-channel = <0>; - mal-rx-channel = <0>; - cell-index = <0>; - max-frame-size = <1500>; - rx-fifo-size = <4096>; - tx-fifo-size = <2048>; - phy-mode = "mii"; - phy-map = <0x0>; - }; - - CAN0: can@ef601000 { - compatible = "amcc,can-405ez"; - reg = <0xef601000 0x620>; - interrupt-parent = <&UIC0>; - interrupts = <0x7 0x4>; - }; - - CAN1: can@ef601800 { - compatible = "amcc,can-405ez"; - reg = <0xef601800 0x620>; - interrupt-parent = <&UIC0>; - interrupts = <0x8 0x4>; - }; - - cameleon@ef602000 { - compatible = "amcc,cameleon-405ez"; - reg = <0xef602000 0x800>; - interrupt-parent = <&UIC0>; - interrupts = <0xb 0x4 0xc 0x4>; - }; - - ieee1588@ef602800 { - compatible = "amcc,ieee1588-405ez"; - reg = <0xef602800 0x60>; - interrupt-parent = <&UIC0>; - interrupts = <0x4 0x4>; - /* This thing is a bit weird. It has it's own UIC - * that it uses to generate snapshot triggers. We - * don't really support this device yet, and it needs - * work to figure this out. - */ - dcr-reg = <0xe0 0x9>; - }; - - usb@ef603000 { - compatible = "ohci-be"; - reg = <0xef603000 0x80>; - interrupts-parent = <&UIC0>; - interrupts = <0xd 0x4 0xe 0x4>; - }; - - dac@ef603300 { - compatible = "amcc,dac-405ez"; - reg = <0xef603300 0x40>; - interrupt-parent = <&UIC0>; - interrupts = <0x18 0x4>; - }; - - adc@ef603400 { - compatible = "amcc,adc-405ez"; - reg = <0xef603400 0x40>; - interrupt-parent = <&UIC0>; - interrupts = <0x17 0x4>; - }; - - spi@ef603500 { - compatible = "amcc,spi-405ez"; - reg = <0xef603500 0x100>; - interrupt-parent = <&UIC0>; - interrupts = <0x9 0x4>; - }; - }; - - EBC0: ebc { - compatible = "ibm,ebc-405ez", "ibm,ebc"; - dcr-reg = <0x12 0x2>; - #address-cells = <2>; - #size-cells = <1>; - clock-frequency = <0>; /* Filled in by wrapper */ - }; - }; - - chosen { - linux,stdout-path = "/plb/opb/serial@ef600300"; - }; -}; diff --git a/trunk/arch/powerpc/boot/dts/hcu4.dts b/trunk/arch/powerpc/boot/dts/hcu4.dts deleted file mode 100644 index 7988598da4c9..000000000000 --- a/trunk/arch/powerpc/boot/dts/hcu4.dts +++ /dev/null @@ -1,168 +0,0 @@ -/* -* Device Tree Source for Netstal Maschinen HCU4 -* based on the IBM Walnut -* -* Copyright 2008 -* Niklaus Giger -* -* Copyright 2007 IBM Corp. -* Josh Boyer -* -* This file is licensed under the terms of the GNU General Public -* License version 2. This program is licensed "as is" without -* any warranty of any kind, whether express or implied. -*/ - -/dts-v1/; - -/ { - #address-cells = <0x1>; - #size-cells = <0x1>; - model = "netstal,hcu4"; - compatible = "netstal,hcu4"; - dcr-parent = <0x1>; - - aliases { - ethernet0 = "/plb/opb/ethernet@ef600800"; - serial0 = "/plb/opb/serial@ef600300"; - }; - - cpus { - #address-cells = <0x1>; - #size-cells = <0x0>; - - cpu@0 { - device_type = "cpu"; - model = "PowerPC,405GPr"; - reg = <0x0>; - clock-frequency = <0>; /* Filled in by U-Boot */ - timebase-frequency = <0x0>; /* Filled in by U-Boot */ - i-cache-line-size = <0x20>; - d-cache-line-size = <0x20>; - i-cache-size = <0x4000>; - d-cache-size = <0x4000>; - dcr-controller; - dcr-access-method = "native"; - linux,phandle = <0x1>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x0>; /* Filled in by U-Boot */ - }; - - UIC0: interrupt-controller { - compatible = "ibm,uic"; - interrupt-controller; - cell-index = <0x0>; - dcr-reg = <0xc0 0x9>; - #address-cells = <0x0>; - #size-cells = <0x0>; - #interrupt-cells = <0x2>; - linux,phandle = <0x2>; - }; - - plb { - compatible = "ibm,plb3"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; - clock-frequency = <0x0>; /* Filled in by U-Boot */ - - SDRAM0: memory-controller { - compatible = "ibm,sdram-405gp"; - dcr-reg = <0x10 0x2>; - }; - - MAL: mcmal { - compatible = "ibm,mcmal-405gp", "ibm,mcmal"; - dcr-reg = <0x180 0x62>; - num-tx-chans = <0x1>; - num-rx-chans = <0x1>; - interrupt-parent = <0x2>; - interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>; - linux,phandle = <0x3>; - }; - - POB0: opb { - compatible = "ibm,opb-405gp", "ibm,opb"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges = <0xef600000 0xef600000 0xa00000>; - dcr-reg = <0xa0 0x5>; - clock-frequency = <0x0>; /* Filled in by U-Boot */ - - UART0: serial@ef600300 { - device_type = "serial"; - compatible = "ns16550"; - reg = <0xef600300 0x8>; - virtual-reg = <0xef600300>; - clock-frequency = <0x0>;/* Filled in by U-Boot */ - current-speed = <0>; /* Filled in by U-Boot */ - interrupt-parent = <0x2>; - interrupts = <0x0 0x4>; - }; - - IIC: i2c@ef600500 { - compatible = "ibm,iic-405gp", "ibm,iic"; - reg = <0xef600500 0x11>; - interrupt-parent = <0x2>; - interrupts = <0x2 0x4>; - }; - - GPIO: gpio@ef600700 { - compatible = "ibm,gpio-405gp"; - reg = <0xef600700 0x20>; - }; - - EMAC: ethernet@ef600800 { - device_type = "network"; - compatible = "ibm,emac-405gp", "ibm,emac"; - interrupt-parent = <0x2>; - interrupts = <0xf 0x4 0x9 0x4>; - local-mac-address = [00 00 00 00 00 00]; - reg = <0xef600800 0x70>; - mal-device = <0x3>; - mal-tx-channel = <0x0>; - mal-rx-channel = <0x0>; - cell-index = <0x0>; - max-frame-size = <0x5dc>; - rx-fifo-size = <0x1000>; - tx-fifo-size = <0x800>; - phy-mode = "rmii"; - phy-map = <0x1>; - }; - }; - - EBC0: ebc { - compatible = "ibm,ebc-405gp", "ibm,ebc"; - dcr-reg = <0x12 0x2>; - #address-cells = <0x2>; - #size-cells = <0x1>; - clock-frequency = <0x0>; /* Filled in by U-Boot */ - - sram@0,0 { - reg = <0x0 0x0 0x80000>; - }; - - flash@0,80000 { - compatible = "jedec-flash"; - bank-width = <0x1>; - reg = <0x0 0x80000 0x80000>; - #address-cells = <0x1>; - #size-cells = <0x1>; - - partition@0 { - label = "OpenBIOS"; - reg = <0x0 0x80000>; - read-only; - }; - }; - }; - }; - - chosen { - linux,stdout-path = "/plb/opb/serial@ef600300"; - }; -}; diff --git a/trunk/arch/powerpc/boot/dts/mpc8315erdb.dts b/trunk/arch/powerpc/boot/dts/mpc8315erdb.dts index 6b850670de1d..7449e54c1a90 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8315erdb.dts @@ -121,14 +121,6 @@ compatible = "dallas,ds1339"; reg = <0x68>; }; - - mcu_pio: mcu@a { - #gpio-cells = <2>; - compatible = "fsl,mc9s08qg8-mpc8315erdb", - "fsl,mcu-mpc8349emitx"; - reg = <0x0a>; - gpio-controller; - }; }; spi@7000 { diff --git a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts index 57c595bf1071..e4cc1768f241 100644 --- a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -60,7 +60,7 @@ }; bcsr@f8000000 { - compatible = "fsl,mpc8323mds-bcsr"; + device_type = "board-control"; reg = <0xf8000000 0x8000>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts b/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts index 2c9d54a35bc3..5cedf373a1d8 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -83,14 +83,6 @@ interrupts = <15 0x8>; interrupt-parent = <&ipic>; dfsrr; - - rtc@68 { - device_type = "rtc"; - compatible = "dallas,ds1339"; - reg = <0x68>; - interrupts = <18 0x8>; - interrupt-parent = <&ipic>; - }; }; spi@7000 { @@ -139,14 +131,6 @@ interrupt-parent = <&ipic>; interrupts = <71 8>; }; - - mcu_pio: mcu@a { - #gpio-cells = <2>; - compatible = "fsl,mc9s08qg8-mpc8349emitx", - "fsl,mcu-mpc8349emitx"; - reg = <0x0a>; - gpio-controller; - }; }; usb@22000 { diff --git a/trunk/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/trunk/arch/powerpc/boot/dts/mpc8349emitxgp.dts index fa40647ee62e..81ae1d3e9440 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8349emitxgp.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8349emitxgp.dts @@ -81,14 +81,6 @@ interrupts = <15 0x8>; interrupt-parent = <&ipic>; dfsrr; - - rtc@68 { - device_type = "rtc"; - compatible = "dallas,ds1339"; - reg = <0x68>; - interrupts = <18 0x8>; - interrupt-parent = <&ipic>; - }; }; spi@7000 { diff --git a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts index c986c541e9bb..04bfde3ea605 100644 --- a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -49,7 +49,7 @@ }; bcsr@e2400000 { - compatible = "fsl,mpc8349mds-bcsr"; + device_type = "board-control"; reg = <0xe2400000 0x8000>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts index 14534d04e4db..66a12d2631fb 100644 --- a/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -69,7 +69,7 @@ }; bcsr@1,0 { - compatible = "fsl,mpc8360mds-bcsr"; + device_type = "board-control"; reg = <1 0 0x8000>; }; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts index 435ef3dd022d..53191ba67aaa 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts @@ -121,14 +121,6 @@ compatible = "dallas,ds1339"; reg = <0x68>; }; - - mcu_pio: mcu@a { - #gpio-cells = <2>; - compatible = "fsl,mc9s08qg8-mpc8377erdb", - "fsl,mcu-mpc8349emitx"; - reg = <0x0a>; - gpio-controller; - }; }; i2c@3100 { diff --git a/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts index b11e68f56a06..4a09153d160c 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts @@ -121,14 +121,6 @@ compatible = "dallas,ds1339"; reg = <0x68>; }; - - mcu_pio: mcu@a { - #gpio-cells = <2>; - compatible = "fsl,mc9s08qg8-mpc8378erdb", - "fsl,mcu-mpc8349emitx"; - reg = <0x0a>; - gpio-controller; - }; }; i2c@3100 { diff --git a/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts index 337af6ea26d3..bbd884ac9dc0 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts @@ -121,14 +121,6 @@ compatible = "dallas,ds1339"; reg = <0x68>; }; - - mcu_pio: mcu@a { - #gpio-cells = <2>; - compatible = "fsl,mc9s08qg8-mpc8379erdb", - "fsl,mcu-mpc8349emitx"; - reg = <0x0a>; - gpio-controller; - }; }; i2c@3100 { diff --git a/trunk/arch/powerpc/boot/dts/mpc8536ds.dts b/trunk/arch/powerpc/boot/dts/mpc8536ds.dts index 35db1e5440c7..93fdd99901b6 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8536ds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8536ds.dts @@ -109,7 +109,7 @@ reg = <0x0 0x80>; cell-index = <0>; interrupt-parent = <&mpic>; - interrupts = <20 2>; + interrupts = <14 0x2>; }; dma-channel@80 { compatible = "fsl,mpc8536-dma-channel", @@ -117,7 +117,7 @@ reg = <0x80 0x80>; cell-index = <1>; interrupt-parent = <&mpic>; - interrupts = <21 2>; + interrupts = <15 0x2>; }; dma-channel@100 { compatible = "fsl,mpc8536-dma-channel", @@ -125,7 +125,7 @@ reg = <0x100 0x80>; cell-index = <2>; interrupt-parent = <&mpic>; - interrupts = <22 2>; + interrupts = <16 0x2>; }; dma-channel@180 { compatible = "fsl,mpc8536-dma-channel", @@ -133,7 +133,7 @@ reg = <0x180 0x80>; cell-index = <3>; interrupt-parent = <&mpic>; - interrupts = <23 2>; + interrupts = <17 0x2>; }; }; @@ -180,7 +180,7 @@ enet0: ethernet@24000 { cell-index = <0>; device_type = "network"; - model = "eTSEC"; + model = "TSEC"; compatible = "gianfar"; reg = <0x24000 0x1000>; local-mac-address = [ 00 00 00 00 00 00 ]; @@ -193,7 +193,7 @@ enet1: ethernet@26000 { cell-index = <1>; device_type = "network"; - model = "eTSEC"; + model = "TSEC"; compatible = "gianfar"; reg = <0x26000 0x1000>; local-mac-address = [ 00 00 00 00 00 00 ]; diff --git a/trunk/arch/powerpc/boot/dts/mpc8568mds.dts b/trunk/arch/powerpc/boot/dts/mpc8568mds.dts index c80158f7741d..a15f10343f53 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8568mds.dts @@ -52,7 +52,7 @@ }; bcsr@f8000000 { - compatible = "fsl,mpc8568mds-bcsr"; + device_type = "board-control"; reg = <0xf8000000 0x8000>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8572ds.dts b/trunk/arch/powerpc/boot/dts/mpc8572ds.dts index cadd4652a695..e124dd18fb5a 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8572ds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8572ds.dts @@ -13,8 +13,8 @@ / { model = "fsl,MPC8572DS"; compatible = "fsl,MPC8572DS"; - #address-cells = <2>; - #size-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; aliases { ethernet0 = &enet0; @@ -61,6 +61,7 @@ memory { device_type = "memory"; + reg = <0x0 0x0>; // Filled by U-Boot }; soc8572@ffe00000 { @@ -68,8 +69,8 @@ #size-cells = <1>; device_type = "soc"; compatible = "simple-bus"; - ranges = <0x0 0 0xffe00000 0x100000>; - reg = <0 0xffe00000 0 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed + ranges = <0x0 0xffe00000 0x100000>; + reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed bus-frequency = <0>; // Filled out by uboot. memory-controller@2000 { @@ -350,10 +351,10 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0 0xffe08000 0 0x1000>; + reg = <0xffe08000 0x1000>; bus-range = <0 255>; - ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000 - 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x00010000>; + ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 + 0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>; clock-frequency = <33333333>; interrupt-parent = <&mpic>; interrupts = <24 2>; @@ -560,10 +561,10 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0 0xffe09000 0 0x1000>; + reg = <0xffe09000 0x1000>; bus-range = <0 255>; - ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 - 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x00010000>; + ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000 + 0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>; clock-frequency = <33333333>; interrupt-parent = <&mpic>; interrupts = <26 2>; @@ -597,10 +598,10 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0 0xffe0a000 0 0x1000>; + reg = <0xffe0a000 0x1000>; bus-range = <0 255>; - ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 - 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x00010000>; + ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000 + 0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>; clock-frequency = <33333333>; interrupt-parent = <&mpic>; interrupts = <27 2>; diff --git a/trunk/arch/powerpc/boot/libfdt-wrapper.c b/trunk/arch/powerpc/boot/libfdt-wrapper.c index 9276327bc2bb..c541fd8a95d4 100644 --- a/trunk/arch/powerpc/boot/libfdt-wrapper.c +++ b/trunk/arch/powerpc/boot/libfdt-wrapper.c @@ -105,11 +105,6 @@ static int fdt_wrapper_setprop(const void *devp, const char *name, return check_err(rc); } -static int fdt_wrapper_del_node(const void *devp) -{ - return fdt_del_node(fdt, devp_offset(devp)); -} - static void *fdt_wrapper_get_parent(const void *devp) { return offset_devp(fdt_parent_offset(fdt, devp_offset(devp))); @@ -170,7 +165,6 @@ static unsigned long fdt_wrapper_finalize(void) void fdt_init(void *blob) { int err; - int bufsize; dt_ops.finddevice = fdt_wrapper_finddevice; dt_ops.getprop = fdt_wrapper_getprop; @@ -179,21 +173,21 @@ void fdt_init(void *blob) dt_ops.create_node = fdt_wrapper_create_node; dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value; dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible; - dt_ops.del_node = fdt_wrapper_del_node; dt_ops.get_path = fdt_wrapper_get_path; dt_ops.finalize = fdt_wrapper_finalize; /* Make sure the dt blob is the right version and so forth */ fdt = blob; - bufsize = fdt_totalsize(fdt) + 4; - buf = malloc(bufsize); - if(!buf) - fatal("malloc failed. can't relocate the device tree\n\r"); - - err = fdt_open_into(fdt, buf, bufsize); + err = fdt_open_into(fdt, fdt, fdt_totalsize(blob)); + if (err == -FDT_ERR_NOSPACE) { + int bufsize = fdt_totalsize(fdt) + 4; + buf = malloc(bufsize); + err = fdt_open_into(fdt, buf, bufsize); + } if (err != 0) fatal("fdt_init(): %s\n\r", fdt_strerror(err)); - fdt = buf; + if (buf) + fdt = buf; } diff --git a/trunk/arch/powerpc/boot/main.c b/trunk/arch/powerpc/boot/main.c index ae32801ebd69..9e7f3ddd9913 100644 --- a/trunk/arch/powerpc/boot/main.c +++ b/trunk/arch/powerpc/boot/main.c @@ -56,19 +56,9 @@ static struct addr_range prep_kernel(void) if (platform_ops.vmlinux_alloc) { addr = platform_ops.vmlinux_alloc(ei.memsize); } else { - /* - * Check if the kernel image (without bss) would overwrite the - * bootwrapper. The device tree has been moved in fdt_init() - * to an area allocated with malloc() (somewhere past _end). - */ - if ((unsigned long)_start < ei.loadsize) + if ((unsigned long)_start < ei.memsize) fatal("Insufficient memory for kernel at address 0!" - " (_start=%p, uncomressed size=%08x)\n\r", - _start, ei.loadsize); - - if ((unsigned long)_end < ei.memsize) - fatal("The final kernel image would overwrite the " - "device tree\n\r"); + " (_start=%p)\n\r", _start); } /* Finally, gunzip the kernel */ diff --git a/trunk/arch/powerpc/boot/ops.h b/trunk/arch/powerpc/boot/ops.h index b3218ce451bb..321e2f5afe71 100644 --- a/trunk/arch/powerpc/boot/ops.h +++ b/trunk/arch/powerpc/boot/ops.h @@ -40,7 +40,6 @@ struct dt_ops { const int buflen); int (*setprop)(const void *phandle, const char *name, const void *buf, const int buflen); - int (*del_node)(const void *phandle); void *(*get_parent)(const void *phandle); /* The node must not already exist. */ void *(*create_node)(const void *parent, const char *name); @@ -127,11 +126,6 @@ static inline int setprop_str(void *devp, const char *name, const char *buf) return -1; } -static inline int del_node(const void *devp) -{ - return dt_ops.del_node ? dt_ops.del_node(devp) : -1; -} - static inline void *get_parent(const char *devp) { return dt_ops.get_parent ? dt_ops.get_parent(devp) : NULL; diff --git a/trunk/arch/powerpc/boot/string.S b/trunk/arch/powerpc/boot/string.S index acc9428f2789..643e4cb2f11d 100644 --- a/trunk/arch/powerpc/boot/string.S +++ b/trunk/arch/powerpc/boot/string.S @@ -235,7 +235,7 @@ memchr: .globl memcmp memcmp: cmpwi 0,r5,0 - ble 2f + blelr mtctr r5 addi r6,r3,-1 addi r4,r4,-1 @@ -244,8 +244,6 @@ memcmp: subf. r3,r0,r3 bdnzt 2,1b blr -2: li r3,0 - blr /* diff --git a/trunk/arch/powerpc/boot/wrapper b/trunk/arch/powerpc/boot/wrapper index f39073511a49..ee0dc41d7c56 100755 --- a/trunk/arch/powerpc/boot/wrapper +++ b/trunk/arch/powerpc/boot/wrapper @@ -306,14 +306,11 @@ fi # post-processing needed for some platforms case "$platform" in -pseries) +pseries|chrp) ${CROSS}objcopy -O binary -j .fakeelf "$kernel" "$ofile".rpanote $objbin/addnote "$ofile" "$ofile".rpanote rm -r "$ofile".rpanote ;; -chrp) - $objbin/addnote -r c00000 "$ofile" - ;; coff) ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" $objbin/hack-coff "$ofile" diff --git a/trunk/arch/powerpc/configs/40x/acadia_defconfig b/trunk/arch/powerpc/configs/40x/acadia_defconfig deleted file mode 100644 index 39bd9eb453f0..000000000000 --- a/trunk/arch/powerpc/configs/40x/acadia_defconfig +++ /dev/null @@ -1,921 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc5 -# Mon Oct 13 13:47:16 2008 -# -# CONFIG_PPC64 is not set - -# -# Processor support -# -# CONFIG_6xx is not set -# CONFIG_PPC_85xx is not set -# CONFIG_PPC_8xx is not set -CONFIG_40x=y -# CONFIG_44x is not set -# CONFIG_E200 is not set -CONFIG_4xx=y -# CONFIG_PPC_MM_SLICES is not set -CONFIG_NOT_COHERENT_CACHE=y -CONFIG_PPC32=y -CONFIG_WORD_SIZE=32 -CONFIG_PPC_MERGE=y -CONFIG_MMU=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_HARDIRQS=y -# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set -CONFIG_IRQ_PER_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_ARCH_HAS_ILOG2_U32=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -# CONFIG_ARCH_NO_VIRT_TO_BUS is not set -CONFIG_PPC=y -CONFIG_EARLY_PRINTK=y -CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_PPC_OF=y -CONFIG_OF=y -CONFIG_PPC_UDBG_16550=y -# CONFIG_GENERIC_TBSYNC is not set -CONFIG_AUDIT_ARCH=y -CONFIG_GENERIC_BUG=y -# CONFIG_DEFAULT_UIMAGE is not set -CONFIG_PPC_DCR_NATIVE=y -# CONFIG_PPC_DCR_MMIO is not set -CONFIG_PPC_DCR=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_GROUP_SCHED=y -# CONFIG_FAIR_GROUP_SCHED is not set -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_COMPAT_BRK=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -# CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set -# CONFIG_HAVE_CLK is not set -CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y -CONFIG_BLOCK=y -CONFIG_LBD=y -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y -# CONFIG_PPC4xx_PCI_EXPRESS is not set - -# -# Platform support -# -# CONFIG_PPC_CELL is not set -# CONFIG_PPC_CELL_NATIVE is not set -# CONFIG_PQ2ADS is not set -CONFIG_ACADIA=y -# CONFIG_EP405 is not set -# CONFIG_KILAUEA is not set -# CONFIG_MAKALU is not set -# CONFIG_WALNUT is not set -# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set -CONFIG_PPC40x_SIMPLE=y -CONFIG_405EZ=y -# CONFIG_IPIC is not set -# CONFIG_MPIC is not set -# CONFIG_MPIC_WEIRD is not set -# CONFIG_PPC_I8259 is not set -# CONFIG_PPC_RTAS is not set -# CONFIG_MMIO_NVRAM is not set -# CONFIG_PPC_MPC106 is not set -# CONFIG_PPC_970_NAP is not set -# CONFIG_PPC_INDIRECT_IO is not set -# CONFIG_GENERIC_IOMAP is not set -# CONFIG_CPU_FREQ is not set -# CONFIG_FSL_ULI1575 is not set - -# -# Kernel options -# -# CONFIG_HIGHMEM is not set -# CONFIG_TICK_ONESHOT is not set -# CONFIG_NO_HZ is not set -# CONFIG_HIGH_RES_TIMERS is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=250 -# CONFIG_SCHED_HRTICK is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_MATH_EMULATION is not set -# CONFIG_IOMMU_HELPER is not set -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y -CONFIG_ARCH_HAS_WALK_MEMORY=y -CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_FORCE_MAX_ZONEORDER=11 -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set -CONFIG_EXTRA_TARGETS="" -# CONFIG_PM is not set -CONFIG_SECCOMP=y -CONFIG_ISA_DMA_API=y - -# -# Bus options -# -CONFIG_ZONE_DMA=y -CONFIG_PPC_INDIRECT_PCI=y -CONFIG_4xx_SOC=y -CONFIG_PPC_PCI_CHOICE=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_SYSCALL=y -# CONFIG_PCIEPORTBUS is not set -CONFIG_ARCH_SUPPORTS_MSI=y -# CONFIG_PCI_MSI is not set -CONFIG_PCI_LEGACY=y -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCCARD is not set -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HAS_RAPIDIO is not set - -# -# Advanced setup -# -# CONFIG_ADVANCED_OPTIONS is not set - -# -# Default settings for advanced configuration options are used -# -CONFIG_LOWMEM_SIZE=0x30000000 -CONFIG_PAGE_OFFSET=0xc0000000 -CONFIG_KERNEL_START=0xc0000000 -CONFIG_PHYSICAL_START=0x00000000 -CONFIG_TASK_SIZE=0xc0000000 -CONFIG_CONSISTENT_START=0xff100000 -CONFIG_CONSISTENT_SIZE=0x00200000 -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=y -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_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_OF_PARTS=y -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=m -CONFIG_MTD_BLOCK=m -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_MTD_OOPS is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_NAND is not set -# CONFIG_MTD_ONENAND is not set - -# -# UBI - Unsorted block images -# -# CONFIG_MTD_UBI is not set -CONFIG_OF_DEVICE=y -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# 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_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=35000 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_XILINX_SYSACE is not set -# CONFIG_BLK_DEV_HD is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# Enable only one of the two stacks, unless you know what you are doing -# -# CONFIG_FIREWIRE is not set -# CONFIG_IEEE1394 is not set -# CONFIG_I2O is not set -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set -# CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=256 -CONFIG_IBM_NEW_EMAC_TXB=256 -CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32 -CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256 -CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0 -CONFIG_IBM_NEW_EMAC_DEBUG=y -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL=y -CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT=y -CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR=y -# CONFIG_NET_PCI is not set -# CONFIG_B44 is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set -# 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_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -# CONFIG_INPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_NOZOMI is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_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_UARTLITE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_GEN_RTC is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y -# CONFIG_I2C is not set -# CONFIG_SPI is not set -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -# CONFIG_GPIOLIB is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -CONFIG_THERMAL=y -# CONFIG_WATCHDOG is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set - -# -# Graphics support -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_SOUND is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_INFINIBAND is not set -# CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set -# CONFIG_UIO 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 is not set -# CONFIG_EXT4DEV_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -CONFIG_DNOTIFY=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_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_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set - -# -# 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_JFFS2_FS is not set -CONFIG_CRAMFS=y -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=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 -# CONFIG_NLS is not set -# CONFIG_DLM is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_HAVE_LMB=y - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_SCHED_DEBUG=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_STATS is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_CODE_PATCHING_SELFTEST is not set -# CONFIG_FTR_FIXUP_SELFTEST is not set -# CONFIG_MSI_BITMAP_SELFTEST is not set -# CONFIG_XMON is not set -# CONFIG_IRQSTACKS is not set -# CONFIG_VIRQ_DEBUG is not set -# CONFIG_BDI_SWITCH is not set -# CONFIG_PPC_EARLY_DEBUG is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_MANAGER=y -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=y -# CONFIG_CRYPTO_LRW is not set -CONFIG_CRYPTO_PCBC=y -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set -CONFIG_CRYPTO_HW=y -# CONFIG_CRYPTO_DEV_HIFN_795X is not set -# CONFIG_PPC_CLOCK is not set -# CONFIG_VIRTUALIZATION is not set diff --git a/trunk/arch/powerpc/configs/40x/hcu4_defconfig b/trunk/arch/powerpc/configs/40x/hcu4_defconfig deleted file mode 100644 index 682fce02c73a..000000000000 --- a/trunk/arch/powerpc/configs/40x/hcu4_defconfig +++ /dev/null @@ -1,929 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.26.5 -# Tue Sep 16 00:44:33 2008 -# -# CONFIG_PPC64 is not set - -# -# Processor support -# -# CONFIG_6xx is not set -# CONFIG_PPC_85xx is not set -# CONFIG_PPC_8xx is not set -CONFIG_40x=y -# CONFIG_44x is not set -# CONFIG_E200 is not set -CONFIG_4xx=y -# CONFIG_PPC_MM_SLICES is not set -CONFIG_NOT_COHERENT_CACHE=y -CONFIG_PPC32=y -CONFIG_WORD_SIZE=32 -CONFIG_PPC_MERGE=y -CONFIG_MMU=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_HARDIRQS=y -# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set -CONFIG_IRQ_PER_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_ARCH_HAS_ILOG2_U32=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -# CONFIG_ARCH_NO_VIRT_TO_BUS is not set -CONFIG_PPC=y -CONFIG_EARLY_PRINTK=y -CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_PPC_OF=y -CONFIG_OF=y -CONFIG_PPC_UDBG_16550=y -# CONFIG_GENERIC_TBSYNC is not set -CONFIG_AUDIT_ARCH=y -CONFIG_GENERIC_BUG=y -# CONFIG_DEFAULT_UIMAGE is not set -CONFIG_PPC_DCR_NATIVE=y -# CONFIG_PPC_DCR_MMIO is not set -CONFIG_PPC_DCR=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -# CONFIG_LOGBUFFER is not set -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_COMPAT_BRK=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_DMA_ATTRS is not set -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y -CONFIG_BLOCK=y -CONFIG_LBD=y -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y -# CONFIG_PPC4xx_PCI_EXPRESS is not set - -# -# Platform support -# -# CONFIG_PPC_MPC512x is not set -# CONFIG_PPC_MPC5121 is not set -# CONFIG_PPC_CELL is not set -# CONFIG_PPC_CELL_NATIVE is not set -# CONFIG_PQ2ADS is not set -# CONFIG_EP405 is not set -CONFIG_HCU4=y -# CONFIG_KILAUEA is not set -# CONFIG_MAKALU is not set -# CONFIG_WALNUT is not set -# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set -# CONFIG_IPIC is not set -# CONFIG_MPIC is not set -# CONFIG_MPIC_WEIRD is not set -# CONFIG_PPC_I8259 is not set -# CONFIG_PPC_RTAS is not set -# CONFIG_MMIO_NVRAM is not set -# CONFIG_PPC_MPC106 is not set -# CONFIG_PPC_970_NAP is not set -# CONFIG_PPC_INDIRECT_IO is not set -# CONFIG_GENERIC_IOMAP is not set -# CONFIG_CPU_FREQ is not set -# CONFIG_FSL_ULI1575 is not set - -# -# Kernel options -# -# CONFIG_HIGHMEM is not set -# CONFIG_TICK_ONESHOT is not set -# CONFIG_NO_HZ is not set -# CONFIG_HIGH_RES_TIMERS is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=250 -# CONFIG_SCHED_HRTICK is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_MATH_EMULATION is not set -# CONFIG_IOMMU_HELPER is not set -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y -CONFIG_ARCH_HAS_WALK_MEMORY=y -CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_RESOURCES_64BIT=y -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_FORCE_MAX_ZONEORDER=11 -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set -# CONFIG_PM is not set -CONFIG_SECCOMP=y -CONFIG_ISA_DMA_API=y - -# -# Bus options -# -CONFIG_ZONE_DMA=y -CONFIG_PPC_INDIRECT_PCI=y -CONFIG_4xx_SOC=y -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_SYSCALL=y -# CONFIG_PCIEPORTBUS is not set -CONFIG_ARCH_SUPPORTS_MSI=y -# CONFIG_PCI_MSI is not set -# CONFIG_PCI_LEGACY is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCCARD is not set -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HAS_RAPIDIO is not set - -# -# Advanced setup -# -# CONFIG_ADVANCED_OPTIONS is not set - -# -# Default settings for advanced configuration options are used -# -CONFIG_LOWMEM_SIZE=0x30000000 -CONFIG_PAGE_OFFSET=0xc0000000 -CONFIG_KERNEL_START=0xc0000000 -CONFIG_PHYSICAL_START=0x00000000 -CONFIG_TASK_SIZE=0xc0000000 -CONFIG_CONSISTENT_START=0xff100000 -CONFIG_CONSISTENT_SIZE=0x00200000 - -# -# 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 is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=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_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_OF_PARTS=y -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=m -CONFIG_MTD_BLOCK=m -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_MTD_OOPS is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_NAND is not set -# CONFIG_MTD_ONENAND is not set - -# -# UBI - Unsorted block images -# -# CONFIG_MTD_UBI is not set -CONFIG_OF_DEVICE=y -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# 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_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=35000 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_XILINX_SYSACE is not set -CONFIG_MISC_DEVICES=y -# CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_ENCLOSURE_SERVICES is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# Enable only one of the two stacks, unless you know what you are doing -# -# CONFIG_FIREWIRE is not set -# CONFIG_IEEE1394 is not set -# CONFIG_I2O is not set -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set -# CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_IBM_NEW_EMAC=y -CONFIG_IBM_NEW_EMAC_RXB=128 -CONFIG_IBM_NEW_EMAC_TXB=64 -CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32 -CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256 -CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0 -# CONFIG_IBM_NEW_EMAC_DEBUG is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_NET_PCI is not set -# CONFIG_B44 is not set -CONFIG_NETDEV_1000=y -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_E1000E is not set -# CONFIG_E1000E_ENABLED is not set -# CONFIG_IP1000 is not set -# CONFIG_IGB is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set -# CONFIG_QLA3XXX is not set -# CONFIG_ATL1 is not set -CONFIG_NETDEV_10000=y -# CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 is not set -# CONFIG_IXGBE is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set -# CONFIG_MYRI10GE is not set -# CONFIG_NETXEN_NIC is not set -# CONFIG_NIU is not set -# CONFIG_MLX4_CORE is not set -# CONFIG_TEHUTI is not set -# CONFIG_BNX2X is not set -# CONFIG_SFC is not set -# CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set -# 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_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -# CONFIG_INPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_NOZOMI is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_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_UARTLITE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_GEN_RTC is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y -# CONFIG_I2C is not set -# CONFIG_SPI is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set -# CONFIG_WATCHDOG is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set -# CONFIG_HTC_PASIC3 is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set - -# -# Graphics support -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=m -# CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_INFINIBAND is not set -# CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set -# CONFIG_UIO 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 is not set -# CONFIG_EXT4DEV_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -CONFIG_DNOTIFY=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_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_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set - -# -# 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_YAFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=y -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set -# 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 -# CONFIG_NLS is not set -# CONFIG_DLM is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_HAVE_LMB=y - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_STATS is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUGGER is not set -# CONFIG_IRQSTACKS is not set -# CONFIG_VIRQ_DEBUG is not set -# CONFIG_BDI_SWITCH is not set -# CONFIG_PPC_EARLY_DEBUG is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_MANAGER=y -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=y -# CONFIG_CRYPTO_LRW is not set -CONFIG_CRYPTO_PCBC=y -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set -CONFIG_CRYPTO_HW=y -# CONFIG_CRYPTO_DEV_HIFN_795X is not set -# CONFIG_PPC_CLOCK is not set -# CONFIG_VIRTUALIZATION is not set diff --git a/trunk/arch/powerpc/include/asm/kdump.h b/trunk/arch/powerpc/include/asm/kdump.h index a503da9d56f3..f6c93c716898 100644 --- a/trunk/arch/powerpc/include/asm/kdump.h +++ b/trunk/arch/powerpc/include/asm/kdump.h @@ -9,12 +9,6 @@ * Reserve to the end of the FWNMI area, see head_64.S */ #define KDUMP_RESERVE_LIMIT 0x10000 /* 64K */ -/* - * Used to differentiate between relocatable kdump kernel and other - * kernels - */ -#define KDUMP_SIGNATURE 0xfeed1234 - #ifdef CONFIG_CRASH_DUMP #define KDUMP_TRAMPOLINE_START 0x0100 @@ -25,18 +19,17 @@ #endif /* CONFIG_CRASH_DUMP */ #ifndef __ASSEMBLY__ +#ifdef CONFIG_CRASH_DUMP -extern unsigned long __kdump_flag; - -#if defined(CONFIG_CRASH_DUMP) && !defined(CONFIG_RELOCATABLE) extern void reserve_kdump_trampoline(void); extern void setup_kdump_trampoline(void); -#else -/* !CRASH_DUMP || RELOCATABLE */ + +#else /* !CONFIG_CRASH_DUMP */ + static inline void reserve_kdump_trampoline(void) { ; } static inline void setup_kdump_trampoline(void) { ; } -#endif +#endif /* CONFIG_CRASH_DUMP */ #endif /* __ASSEMBLY__ */ #endif /* __PPC64_KDUMP_H */ diff --git a/trunk/arch/powerpc/include/asm/page.h b/trunk/arch/powerpc/include/asm/page.h index c0b8d4a29a91..5ac51e6efc1d 100644 --- a/trunk/arch/powerpc/include/asm/page.h +++ b/trunk/arch/powerpc/include/asm/page.h @@ -77,7 +77,6 @@ #if defined(CONFIG_RELOCATABLE) #ifndef __ASSEMBLY__ - extern phys_addr_t memstart_addr; extern phys_addr_t kernstart_addr; #endif diff --git a/trunk/arch/powerpc/include/asm/ptrace.h b/trunk/arch/powerpc/include/asm/ptrace.h index 280a90cc9894..734e0754fb9b 100644 --- a/trunk/arch/powerpc/include/asm/ptrace.h +++ b/trunk/arch/powerpc/include/asm/ptrace.h @@ -129,7 +129,7 @@ extern int ptrace_put_reg(struct task_struct *task, int regno, #define CHECK_FULL_REGS(regs) \ do { \ if ((regs)->trap & 1) \ - printk(KERN_CRIT "%s: partial register set\n", __func__); \ + printk(KERN_CRIT "%s: partial register set\n", __FUNCTION__); \ } while (0) #endif /* __powerpc64__ */ diff --git a/trunk/arch/powerpc/kernel/cputable.c b/trunk/arch/powerpc/kernel/cputable.c index b1eb834bc0fc..e70d0483fb4e 100644 --- a/trunk/arch/powerpc/kernel/cputable.c +++ b/trunk/arch/powerpc/kernel/cputable.c @@ -1277,19 +1277,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_4xx, .platform = "ppc405", }, - { - /* 405EZ */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x41510000, - .cpu_name = "405EZ", - .cpu_features = CPU_FTRS_40X, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - .icache_bsize = 32, - .dcache_bsize = 32, - .machine_check = machine_check_4xx, - .platform = "ppc405", - }, { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, diff --git a/trunk/arch/powerpc/kernel/crash_dump.c b/trunk/arch/powerpc/kernel/crash_dump.c index 19671aca6591..97e056379728 100644 --- a/trunk/arch/powerpc/kernel/crash_dump.c +++ b/trunk/arch/powerpc/kernel/crash_dump.c @@ -30,7 +30,6 @@ /* Stores the physical address of elf header of crash image. */ unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; -#ifndef CONFIG_RELOCATABLE void __init reserve_kdump_trampoline(void) { lmb_reserve(0, KDUMP_RESERVE_LIMIT); @@ -69,7 +68,6 @@ void __init setup_kdump_trampoline(void) DBG(" <- setup_kdump_trampoline()\n"); } -#endif /* CONFIG_RELOCATABLE */ /* * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by diff --git a/trunk/arch/powerpc/kernel/head_64.S b/trunk/arch/powerpc/kernel/head_64.S index 69489bd3210c..84856bee33a5 100644 --- a/trunk/arch/powerpc/kernel/head_64.S +++ b/trunk/arch/powerpc/kernel/head_64.S @@ -97,12 +97,6 @@ __secondary_hold_spinloop: __secondary_hold_acknowledge: .llong 0x0 - /* This flag is set by purgatory if we should be a kdump kernel. */ - /* Do not move this variable as purgatory knows about it. */ - .globl __kdump_flag -__kdump_flag: - .llong 0x0 - #ifdef CONFIG_PPC_ISERIES /* * At offset 0x20, there is a pointer to iSeries LPAR data. @@ -1390,13 +1384,7 @@ _STATIC(__after_prom_start) /* process relocations for the final address of the kernel */ lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ sldi r25,r25,32 -#ifdef CONFIG_CRASH_DUMP - ld r7,__kdump_flag-_stext(r26) - cmpldi cr0,r7,1 /* kdump kernel ? - stay where we are */ - bne 1f - add r25,r25,r26 -#endif -1: mr r3,r25 + mr r3,r25 bl .relocate #endif @@ -1410,25 +1398,10 @@ _STATIC(__after_prom_start) li r3,0 /* target addr */ mr. r4,r26 /* In some cases the loader may */ beq 9f /* have already put us at zero */ - li r6,0x100 /* Start offset, the first 0x100 */ - /* bytes were copied earlier. */ - -#ifdef CONFIG_CRASH_DUMP -/* - * Check if the kernel has to be running as relocatable kernel based on the - * variable __kdump_flag, if it is set the kernel is treated as relocatable - * kernel, otherwise it will be moved to PHYSICAL_START - */ - ld r7,__kdump_flag-_stext(r26) - cmpldi cr0,r7,1 - bne 3f - - li r5,__end_interrupts - _stext /* just copy interrupts */ - b 5f -3: -#endif lis r5,(copy_to_here - _stext)@ha addi r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */ + li r6,0x100 /* Start offset, the first 0x100 */ + /* bytes were copied earlier. */ bl .copy_and_flush /* copy the first n bytes */ /* this includes the code being */ @@ -1438,15 +1411,15 @@ _STATIC(__after_prom_start) mtctr r8 bctr -p_end: .llong _end - _stext - 4: /* Now copy the rest of the kernel up to _end */ addis r5,r26,(p_end - _stext)@ha ld r5,(p_end - _stext)@l(r5) /* get _end */ -5: bl .copy_and_flush /* copy the rest */ + bl .copy_and_flush /* copy the rest */ 9: b .start_here_multiplatform +p_end: .llong _end - _stext + /* * Copy routine used to copy the kernel to start at physical address 0 * and flush and invalidate the caches as needed. diff --git a/trunk/arch/powerpc/kernel/iommu.c b/trunk/arch/powerpc/kernel/iommu.c index 3857d7e2af0c..ea1ba89f9c90 100644 --- a/trunk/arch/powerpc/kernel/iommu.c +++ b/trunk/arch/powerpc/kernel/iommu.c @@ -458,42 +458,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, spin_unlock_irqrestore(&(tbl->it_lock), flags); } -static void iommu_table_clear(struct iommu_table *tbl) -{ - if (!__kdump_flag) { - /* Clear the table in case firmware left allocations in it */ - ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); - return; - } - -#ifdef CONFIG_CRASH_DUMP - if (ppc_md.tce_get) { - unsigned long index, tceval, tcecount = 0; - - /* Reserve the existing mappings left by the first kernel. */ - for (index = 0; index < tbl->it_size; index++) { - tceval = ppc_md.tce_get(tbl, index + tbl->it_offset); - /* - * Freed TCE entry contains 0x7fffffffffffffff on JS20 - */ - if (tceval && (tceval != 0x7fffffffffffffffUL)) { - __set_bit(index, tbl->it_map); - tcecount++; - } - } - - if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) { - printk(KERN_WARNING "TCE table is full; freeing "); - printk(KERN_WARNING "%d entries for the kdump boot\n", - KDUMP_MIN_TCE_ENTRIES); - for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES; - index < tbl->it_size; index++) - __clear_bit(index, tbl->it_map); - } - } -#endif -} - /* * Build a iommu_table structure. This contains a bit map which * is used to manage allocation of the tce space. @@ -520,7 +484,38 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) tbl->it_largehint = tbl->it_halfpoint; spin_lock_init(&tbl->it_lock); - iommu_table_clear(tbl); +#ifdef CONFIG_CRASH_DUMP + if (ppc_md.tce_get) { + unsigned long index; + unsigned long tceval; + unsigned long tcecount = 0; + + /* + * Reserve the existing mappings left by the first kernel. + */ + for (index = 0; index < tbl->it_size; index++) { + tceval = ppc_md.tce_get(tbl, index + tbl->it_offset); + /* + * Freed TCE entry contains 0x7fffffffffffffff on JS20 + */ + if (tceval && (tceval != 0x7fffffffffffffffUL)) { + __set_bit(index, tbl->it_map); + tcecount++; + } + } + if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) { + printk(KERN_WARNING "TCE table is full; "); + printk(KERN_WARNING "freeing %d entries for the kdump boot\n", + KDUMP_MIN_TCE_ENTRIES); + for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES; + index < tbl->it_size; index++) + __clear_bit(index, tbl->it_map); + } + } +#else + /* Clear the hardware table in case firmware left allocations in it */ + ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); +#endif if (!welcomed) { printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", diff --git a/trunk/arch/powerpc/kernel/machine_kexec.c b/trunk/arch/powerpc/kernel/machine_kexec.c index ac2a21f45c75..aab76887a842 100644 --- a/trunk/arch/powerpc/kernel/machine_kexec.c +++ b/trunk/arch/powerpc/kernel/machine_kexec.c @@ -88,13 +88,11 @@ void __init reserve_crashkernel(void) crash_size = crashk_res.end - crashk_res.start + 1; -#ifndef CONFIG_RELOCATABLE if (crashk_res.start != KDUMP_KERNELBASE) printk("Crash kernel location must be 0x%x\n", KDUMP_KERNELBASE); crashk_res.start = KDUMP_KERNELBASE; -#endif crash_size = PAGE_ALIGN(crash_size); crashk_res.end = crashk_res.start + crash_size - 1; diff --git a/trunk/arch/powerpc/kernel/machine_kexec_64.c b/trunk/arch/powerpc/kernel/machine_kexec_64.c index e6efec788c4d..a168514d8609 100644 --- a/trunk/arch/powerpc/kernel/machine_kexec_64.c +++ b/trunk/arch/powerpc/kernel/machine_kexec_64.c @@ -255,14 +255,11 @@ static union thread_union kexec_stack /* Our assembly helper, in kexec_stub.S */ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, void *image, void *control, - void (*clear_all)(void), - unsigned long kdump_flag) ATTRIB_NORET; + void (*clear_all)(void)) ATTRIB_NORET; /* too late to fail here */ void default_machine_kexec(struct kimage *image) { - unsigned long kdump_flag = 0; - /* prepare control code if any */ /* @@ -273,10 +270,8 @@ void default_machine_kexec(struct kimage *image) * using debugger IPI. */ - if (crashing_cpu == -1) - kexec_prepare_cpus(); - else - kdump_flag = KDUMP_SIGNATURE; + if (crashing_cpu == -1) + kexec_prepare_cpus(); /* switch to a staticly allocated stack. Based on irq stack code. * XXX: the task struct will likely be invalid once we do the copy! @@ -289,7 +284,7 @@ void default_machine_kexec(struct kimage *image) */ kexec_sequence(&kexec_stack, image->start, image, page_address(image->control_code_page), - ppc_md.hpte_clear_all, kdump_flag); + ppc_md.hpte_clear_all); /* NOTREACHED */ } @@ -317,24 +312,11 @@ static struct property kernel_end_prop = { static void __init export_htab_values(void) { struct device_node *node; - struct property *prop; node = of_find_node_by_path("/chosen"); if (!node) return; - /* remove any stale propertys so ours can be found */ - prop = of_find_property(node, kernel_end_prop.name, NULL); - if (prop) - prom_remove_property(node, prop); - prop = of_find_property(node, htab_base_prop.name, NULL); - if (prop) - prom_remove_property(node, prop); - prop = of_find_property(node, htab_size_prop.name, NULL); - if (prop) - prom_remove_property(node, prop); - - /* information needed by userspace when using default_machine_kexec */ kernel_end = __pa(_end); prom_add_property(node, &kernel_end_prop); diff --git a/trunk/arch/powerpc/kernel/misc_64.S b/trunk/arch/powerpc/kernel/misc_64.S index a243fd072a77..3053fe5c62f2 100644 --- a/trunk/arch/powerpc/kernel/misc_64.S +++ b/trunk/arch/powerpc/kernel/misc_64.S @@ -611,12 +611,10 @@ real_mode: /* assume normal blr return */ /* - * kexec_sequence(newstack, start, image, control, clear_all(), kdump_flag) + * kexec_sequence(newstack, start, image, control, clear_all()) * * does the grungy work with stack switching and real mode switches * also does simple calls to other code - * - * kdump_flag says whether the next kernel should be a kdump kernel. */ _GLOBAL(kexec_sequence) @@ -649,7 +647,7 @@ _GLOBAL(kexec_sequence) mr r29,r5 /* image (virt) */ mr r28,r6 /* control, unused */ mr r27,r7 /* clear_all() fn desc */ - mr r26,r8 /* kdump flag */ + mr r26,r8 /* spare */ lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ /* disable interrupts, we are overwriting kernel data next */ @@ -711,6 +709,5 @@ _GLOBAL(kexec_sequence) mr r4,r30 # start, aka phys mem offset mtlr 4 li r5,0 - mr r6,r26 /* kdump_flag */ - blr /* image->start(physid, image->start, 0, kdump_flag); */ + blr /* image->start(physid, image->start, 0); */ #endif /* CONFIG_KEXEC */ diff --git a/trunk/arch/powerpc/kernel/pci-common.c b/trunk/arch/powerpc/kernel/pci-common.c index 1ec73938a00f..3815d84a1ef4 100644 --- a/trunk/arch/powerpc/kernel/pci-common.c +++ b/trunk/arch/powerpc/kernel/pci-common.c @@ -610,8 +610,7 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus, pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset); vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE | _PAGE_GUARDED); + vma->vm_page_prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); diff --git a/trunk/arch/powerpc/kernel/prom_init.c b/trunk/arch/powerpc/kernel/prom_init.c index 23e0db203329..2fdbc18ae94a 100644 --- a/trunk/arch/powerpc/kernel/prom_init.c +++ b/trunk/arch/powerpc/kernel/prom_init.c @@ -487,6 +487,67 @@ static int __init prom_setprop(phandle node, const char *nodename, return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); } +/* We can't use the standard versions because of RELOC headaches. */ +#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ + || ('a' <= (c) && (c) <= 'f') \ + || ('A' <= (c) && (c) <= 'F')) + +#define isdigit(c) ('0' <= (c) && (c) <= '9') +#define islower(c) ('a' <= (c) && (c) <= 'z') +#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c)) + +unsigned long prom_strtoul(const char *cp, const char **endp) +{ + unsigned long result = 0, base = 10, value; + + if (*cp == '0') { + base = 8; + cp++; + if (toupper(*cp) == 'X') { + cp++; + base = 16; + } + } + + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) { + result = result * base + value; + cp++; + } + + if (endp) + *endp = cp; + + return result; +} + +unsigned long prom_memparse(const char *ptr, const char **retptr) +{ + unsigned long ret = prom_strtoul(ptr, retptr); + int shift = 0; + + /* + * We can't use a switch here because GCC *may* generate a + * jump table which won't work, because we're not running at + * the address we're linked at. + */ + if ('G' == **retptr || 'g' == **retptr) + shift = 30; + + if ('M' == **retptr || 'm' == **retptr) + shift = 20; + + if ('K' == **retptr || 'k' == **retptr) + shift = 10; + + if (shift) { + ret <<= shift; + (*retptr)++; + } + + return ret; +} + /* * Early parsing of the command line passed to the kernel, used for * "mem=x" and the options that affect the iommu diff --git a/trunk/arch/powerpc/kernel/prom_init_check.sh b/trunk/arch/powerpc/kernel/prom_init_check.sh index ea3a2ec03ffa..2c7e8e87f770 100644 --- a/trunk/arch/powerpc/kernel/prom_init_check.sh +++ b/trunk/arch/powerpc/kernel/prom_init_check.sh @@ -20,7 +20,7 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush _end enter_prom memcpy memset reloc_offset __secondary_hold __secondary_hold_acknowledge __secondary_hold_spinloop __start strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 -reloc_got2 kernstart_addr memstart_addr" +reloc_got2 kernstart_addr" NM="$1" OBJ="$2" diff --git a/trunk/arch/powerpc/kernel/setup-common.c b/trunk/arch/powerpc/kernel/setup-common.c index 705fc4bf3800..5ec56ff03e86 100644 --- a/trunk/arch/powerpc/kernel/setup-common.c +++ b/trunk/arch/powerpc/kernel/setup-common.c @@ -59,7 +59,6 @@ #include #include #include -#include #include "setup.h" @@ -191,12 +190,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (ppc_md.show_cpuinfo != NULL) ppc_md.show_cpuinfo(m); -#ifdef CONFIG_PPC32 - /* Display the amount of memory */ - seq_printf(m, "Memory\t\t: %d MB\n", - (unsigned int)(total_memory / (1024 * 1024))); -#endif - return 0; } diff --git a/trunk/arch/powerpc/kernel/signal_64.c b/trunk/arch/powerpc/kernel/signal_64.c index c6a8f2326b6f..65ad925c3a8f 100644 --- a/trunk/arch/powerpc/kernel/signal_64.c +++ b/trunk/arch/powerpc/kernel/signal_64.c @@ -235,6 +235,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, else for (i = 0; i < 32 ; i++) current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; + +#else #endif return err; } diff --git a/trunk/arch/powerpc/kernel/udbg_16550.c b/trunk/arch/powerpc/kernel/udbg_16550.c index 7b7da8cfd5e8..cb01ebc59387 100644 --- a/trunk/arch/powerpc/kernel/udbg_16550.c +++ b/trunk/arch/powerpc/kernel/udbg_16550.c @@ -142,7 +142,7 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) speed = (clock / prescaler) / (divisor * 16); /* sanity check */ - if (speed > (clock / 16)) + if (speed < 0 || speed > (clock / 16)) speed = 9600; return speed; diff --git a/trunk/arch/powerpc/mm/hash_utils_64.c b/trunk/arch/powerpc/mm/hash_utils_64.c index 8d5b4758c13a..5c64af174752 100644 --- a/trunk/arch/powerpc/mm/hash_utils_64.c +++ b/trunk/arch/powerpc/mm/hash_utils_64.c @@ -382,10 +382,8 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node, printk(KERN_INFO "Huge page(16GB) memory: " "addr = 0x%lX size = 0x%lX pages = %d\n", phys_addr, block_size, expected_pages); - if (phys_addr + (16 * GB) <= lmb_end_of_DRAM()) { - lmb_reserve(phys_addr, block_size * expected_pages); - add_gpage(phys_addr, block_size, expected_pages); - } + lmb_reserve(phys_addr, block_size * expected_pages); + add_gpage(phys_addr, block_size, expected_pages); return 0; } #endif /* CONFIG_HUGETLB_PAGE */ diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index eb505ad34a85..6cf5c71c431f 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -116,7 +116,6 @@ static int __init get_active_region_work_fn(unsigned long start_pfn, /* * get_node_active_region - Return active region containing start_pfn - * Active range returned is empty if none found. * @start_pfn: The page to return the region for. * @node_ar: Returned set to the active region containing start_pfn */ @@ -127,7 +126,6 @@ static void __init get_node_active_region(unsigned long start_pfn, node_ar->nid = nid; node_ar->start_pfn = start_pfn; - node_ar->end_pfn = start_pfn; work_with_active_regions(nid, get_active_region_work_fn, node_ar); } @@ -528,10 +526,12 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start, /* * We use lmb_end_of_DRAM() in here instead of memory_limit because * we've already adjusted it for the limit and it takes care of - * having memory holes below the limit. Also, in the case of - * iommu_is_off, memory_limit is not set but is implicitly enforced. + * having memory holes below the limit. */ + if (! memory_limit) + return size; + if (start + size <= lmb_end_of_DRAM()) return size; @@ -933,20 +933,18 @@ void __init do_init_bootmem(void) struct node_active_region node_ar; get_node_active_region(start_pfn, &node_ar); - while (start_pfn < end_pfn && - node_ar.start_pfn < node_ar.end_pfn) { - unsigned long reserve_size = size; + while (start_pfn < end_pfn) { /* * if reserved region extends past active region * then trim size to active region */ if (end_pfn > node_ar.end_pfn) - reserve_size = (node_ar.end_pfn << PAGE_SHIFT) + size = (node_ar.end_pfn << PAGE_SHIFT) - (start_pfn << PAGE_SHIFT); - dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, - reserve_size, node_ar.nid); + dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, size, + node_ar.nid); reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, - reserve_size, BOOTMEM_DEFAULT); + size, BOOTMEM_DEFAULT); /* * if reserved region is contained in the active region * then done. @@ -961,7 +959,6 @@ void __init do_init_bootmem(void) */ start_pfn = node_ar.end_pfn; physbase = start_pfn << PAGE_SHIFT; - size = size - reserve_size; get_node_active_region(start_pfn, &node_ar); } diff --git a/trunk/arch/powerpc/oprofile/cell/pr_util.h b/trunk/arch/powerpc/oprofile/cell/pr_util.h index 628009c01958..22e4e8d4eb2c 100644 --- a/trunk/arch/powerpc/oprofile/cell/pr_util.h +++ b/trunk/arch/powerpc/oprofile/cell/pr_util.h @@ -24,11 +24,6 @@ #define SKIP_GENERIC_SYNC 0 #define SYNC_START_ERROR -1 #define DO_GENERIC_SYNC 1 -#define SPUS_PER_NODE 8 -#define DEFAULT_TIMER_EXPIRE (HZ / 10) - -extern struct delayed_work spu_work; -extern int spu_prof_running; struct spu_overlay_info { /* map of sections within an SPU overlay */ unsigned int vma; /* SPU virtual memory address from elf */ @@ -67,14 +62,6 @@ struct vma_to_fileoffset_map { /* map of sections within an SPU program */ }; -struct spu_buffer { - int last_guard_val; - int ctx_sw_seen; - unsigned long *buff; - unsigned int head, tail; -}; - - /* The three functions below are for maintaining and accessing * the vma-to-fileoffset map. */ diff --git a/trunk/arch/powerpc/oprofile/cell/spu_profiler.c b/trunk/arch/powerpc/oprofile/cell/spu_profiler.c index 6edaebd5099a..380d7e217531 100644 --- a/trunk/arch/powerpc/oprofile/cell/spu_profiler.c +++ b/trunk/arch/powerpc/oprofile/cell/spu_profiler.c @@ -23,11 +23,12 @@ static u32 *samples; -int spu_prof_running; +static int spu_prof_running; static unsigned int profiling_interval; #define NUM_SPU_BITS_TRBUF 16 #define SPUS_PER_TB_ENTRY 4 +#define SPUS_PER_NODE 8 #define SPU_PC_MASK 0xFFFF @@ -207,7 +208,6 @@ int start_spu_profiling(unsigned int cycles_reset) spu_prof_running = 1; hrtimer_start(&timer, kt, HRTIMER_MODE_REL); - schedule_delayed_work(&spu_work, DEFAULT_TIMER_EXPIRE); return 0; } diff --git a/trunk/arch/powerpc/oprofile/cell/spu_task_sync.c b/trunk/arch/powerpc/oprofile/cell/spu_task_sync.c index 2949126d28d1..2a9b4a049329 100644 --- a/trunk/arch/powerpc/oprofile/cell/spu_task_sync.c +++ b/trunk/arch/powerpc/oprofile/cell/spu_task_sync.c @@ -35,102 +35,7 @@ static DEFINE_SPINLOCK(buffer_lock); static DEFINE_SPINLOCK(cache_lock); static int num_spu_nodes; int spu_prof_num_nodes; - -struct spu_buffer spu_buff[MAX_NUMNODES * SPUS_PER_NODE]; -struct delayed_work spu_work; -static unsigned max_spu_buff; - -static void spu_buff_add(unsigned long int value, int spu) -{ - /* spu buff is a circular buffer. Add entries to the - * head. Head is the index to store the next value. - * The buffer is full when there is one available entry - * in the queue, i.e. head and tail can't be equal. - * That way we can tell the difference between the - * buffer being full versus empty. - * - * ASSUPTION: the buffer_lock is held when this function - * is called to lock the buffer, head and tail. - */ - int full = 1; - - if (spu_buff[spu].head >= spu_buff[spu].tail) { - if ((spu_buff[spu].head - spu_buff[spu].tail) - < (max_spu_buff - 1)) - full = 0; - - } else if (spu_buff[spu].tail > spu_buff[spu].head) { - if ((spu_buff[spu].tail - spu_buff[spu].head) - > 1) - full = 0; - } - - if (!full) { - spu_buff[spu].buff[spu_buff[spu].head] = value; - spu_buff[spu].head++; - - if (spu_buff[spu].head >= max_spu_buff) - spu_buff[spu].head = 0; - } else { - /* From the user's perspective make the SPU buffer - * size management/overflow look like we are using - * per cpu buffers. The user uses the same - * per cpu parameter to adjust the SPU buffer size. - * Increment the sample_lost_overflow to inform - * the user the buffer size needs to be increased. - */ - oprofile_cpu_buffer_inc_smpl_lost(); - } -} - -/* This function copies the per SPU buffers to the - * OProfile kernel buffer. - */ -void sync_spu_buff(void) -{ - int spu; - unsigned long flags; - int curr_head; - - for (spu = 0; spu < num_spu_nodes; spu++) { - /* In case there was an issue and the buffer didn't - * get created skip it. - */ - if (spu_buff[spu].buff == NULL) - continue; - - /* Hold the lock to make sure the head/tail - * doesn't change while spu_buff_add() is - * deciding if the buffer is full or not. - * Being a little paranoid. - */ - spin_lock_irqsave(&buffer_lock, flags); - curr_head = spu_buff[spu].head; - spin_unlock_irqrestore(&buffer_lock, flags); - - /* Transfer the current contents to the kernel buffer. - * data can still be added to the head of the buffer. - */ - oprofile_put_buff(spu_buff[spu].buff, - spu_buff[spu].tail, - curr_head, max_spu_buff); - - spin_lock_irqsave(&buffer_lock, flags); - spu_buff[spu].tail = curr_head; - spin_unlock_irqrestore(&buffer_lock, flags); - } - -} - -static void wq_sync_spu_buff(struct work_struct *work) -{ - /* move data from spu buffers to kernel buffer */ - sync_spu_buff(); - - /* only reschedule if profiling is not done */ - if (spu_prof_running) - schedule_delayed_work(&spu_work, DEFAULT_TIMER_EXPIRE); -} +int last_guard_val[MAX_NUMNODES * 8]; /* Container for caching information about an active SPU task. */ struct cached_info { @@ -400,21 +305,14 @@ static int process_context_switch(struct spu *spu, unsigned long objectId) /* Record context info in event buffer */ spin_lock_irqsave(&buffer_lock, flags); - spu_buff_add(ESCAPE_CODE, spu->number); - spu_buff_add(SPU_CTX_SWITCH_CODE, spu->number); - spu_buff_add(spu->number, spu->number); - spu_buff_add(spu->pid, spu->number); - spu_buff_add(spu->tgid, spu->number); - spu_buff_add(app_dcookie, spu->number); - spu_buff_add(spu_cookie, spu->number); - spu_buff_add(offset, spu->number); - - /* Set flag to indicate SPU PC data can now be written out. If - * the SPU program counter data is seen before an SPU context - * record is seen, the postprocessing will fail. - */ - spu_buff[spu->number].ctx_sw_seen = 1; - + add_event_entry(ESCAPE_CODE); + add_event_entry(SPU_CTX_SWITCH_CODE); + add_event_entry(spu->number); + add_event_entry(spu->pid); + add_event_entry(spu->tgid); + add_event_entry(app_dcookie); + add_event_entry(spu_cookie); + add_event_entry(offset); spin_unlock_irqrestore(&buffer_lock, flags); smp_wmb(); /* insure spu event buffer updates are written */ /* don't want entries intermingled... */ @@ -462,47 +360,6 @@ static int number_of_online_nodes(void) return nodes; } -static int oprofile_spu_buff_create(void) -{ - int spu; - - max_spu_buff = oprofile_get_cpu_buffer_size(); - - for (spu = 0; spu < num_spu_nodes; spu++) { - /* create circular buffers to store the data in. - * use locks to manage accessing the buffers - */ - spu_buff[spu].head = 0; - spu_buff[spu].tail = 0; - - /* - * Create a buffer for each SPU. Can't reliably - * create a single buffer for all spus due to not - * enough contiguous kernel memory. - */ - - spu_buff[spu].buff = kzalloc((max_spu_buff - * sizeof(unsigned long)), - GFP_KERNEL); - - if (!spu_buff[spu].buff) { - printk(KERN_ERR "SPU_PROF: " - "%s, line %d: oprofile_spu_buff_create " - "failed to allocate spu buffer %d.\n", - __func__, __LINE__, spu); - - /* release the spu buffers that have been allocated */ - while (spu >= 0) { - kfree(spu_buff[spu].buff); - spu_buff[spu].buff = 0; - spu--; - } - return -ENOMEM; - } - } - return 0; -} - /* The main purpose of this function is to synchronize * OProfile with SPUFS by registering to be notified of * SPU task switches. @@ -515,35 +372,20 @@ static int oprofile_spu_buff_create(void) */ int spu_sync_start(void) { - int spu; + int k; int ret = SKIP_GENERIC_SYNC; int register_ret; unsigned long flags = 0; spu_prof_num_nodes = number_of_online_nodes(); num_spu_nodes = spu_prof_num_nodes * 8; - INIT_DELAYED_WORK(&spu_work, wq_sync_spu_buff); - - /* create buffer for storing the SPU data to put in - * the kernel buffer. - */ - ret = oprofile_spu_buff_create(); - if (ret) - goto out; spin_lock_irqsave(&buffer_lock, flags); - for (spu = 0; spu < num_spu_nodes; spu++) { - spu_buff_add(ESCAPE_CODE, spu); - spu_buff_add(SPU_PROFILING_CODE, spu); - spu_buff_add(num_spu_nodes, spu); - } + add_event_entry(ESCAPE_CODE); + add_event_entry(SPU_PROFILING_CODE); + add_event_entry(num_spu_nodes); spin_unlock_irqrestore(&buffer_lock, flags); - for (spu = 0; spu < num_spu_nodes; spu++) { - spu_buff[spu].ctx_sw_seen = 0; - spu_buff[spu].last_guard_val = 0; - } - /* Register for SPU events */ register_ret = spu_switch_event_register(&spu_active); if (register_ret) { @@ -551,6 +393,8 @@ int spu_sync_start(void) goto out; } + for (k = 0; k < (MAX_NUMNODES * 8); k++) + last_guard_val[k] = 0; pr_debug("spu_sync_start -- running.\n"); out: return ret; @@ -602,20 +446,13 @@ void spu_sync_buffer(int spu_num, unsigned int *samples, * use. We need to discard samples taken during the time * period which an overlay occurs (i.e., guard value changes). */ - if (grd_val && grd_val != spu_buff[spu_num].last_guard_val) { - spu_buff[spu_num].last_guard_val = grd_val; + if (grd_val && grd_val != last_guard_val[spu_num]) { + last_guard_val[spu_num] = grd_val; /* Drop the rest of the samples. */ break; } - /* We must ensure that the SPU context switch has been written - * out before samples for the SPU. Otherwise, the SPU context - * information is not available and the postprocessing of the - * SPU PC will fail with no available anonymous map information. - */ - if (spu_buff[spu_num].ctx_sw_seen) - spu_buff_add((file_offset | spu_num_shifted), - spu_num); + add_event_entry(file_offset | spu_num_shifted); } spin_unlock(&buffer_lock); out: @@ -626,41 +463,20 @@ void spu_sync_buffer(int spu_num, unsigned int *samples, int spu_sync_stop(void) { unsigned long flags = 0; - int ret; - int k; - - ret = spu_switch_event_unregister(&spu_active); - - if (ret) + int ret = spu_switch_event_unregister(&spu_active); + if (ret) { printk(KERN_ERR "SPU_PROF: " - "%s, line %d: spu_switch_event_unregister " \ - "returned %d\n", - __func__, __LINE__, ret); - - /* flush any remaining data in the per SPU buffers */ - sync_spu_buff(); + "%s, line %d: spu_switch_event_unregister returned %d\n", + __func__, __LINE__, ret); + goto out; + } spin_lock_irqsave(&cache_lock, flags); ret = release_cached_info(RELEASE_ALL); spin_unlock_irqrestore(&cache_lock, flags); - - /* remove scheduled work queue item rather then waiting - * for every queued entry to execute. Then flush pending - * system wide buffer to event buffer. - */ - cancel_delayed_work(&spu_work); - - for (k = 0; k < num_spu_nodes; k++) { - spu_buff[k].ctx_sw_seen = 0; - - /* - * spu_sys_buff will be null if there was a problem - * allocating the buffer. Only delete if it exists. - */ - kfree(spu_buff[k].buff); - spu_buff[k].buff = 0; - } +out: pr_debug("spu_sync_stop -- done.\n"); return ret; } + diff --git a/trunk/arch/powerpc/platforms/40x/Kconfig b/trunk/arch/powerpc/platforms/40x/Kconfig index 65730275e012..a9260e21451e 100644 --- a/trunk/arch/powerpc/platforms/40x/Kconfig +++ b/trunk/arch/powerpc/platforms/40x/Kconfig @@ -14,15 +14,6 @@ # help # This option enables support for the CPCI405 board. -config ACADIA - bool "Acadia" - depends on 40x - default n - select PPC40x_SIMPLE - select 405EZ - help - This option enables support for the AMCC 405EZ Acadia evaluation board. - config EP405 bool "EP405/EP405PC" depends on 40x @@ -32,14 +23,6 @@ config EP405 help This option enables support for the EP405/EP405PC boards. -config HCU4 - bool "Hcu4" - depends on 40x - default y - select 405GPR - help - This option enables support for the Nestal Maschinen HCU4 board. - config KILAUEA bool "Kilauea" depends on 40x @@ -110,13 +93,6 @@ config XILINX_VIRTEX_GENERIC_BOARD Most Virtex designs should use this unless it needs to do some special configuration at board probe time. -config PPC40x_SIMPLE - bool "Simple PowerPC 40x board support" - depends on 40x - default n - help - This option enables the simple PowerPC 40x platform support. - # 40x specific CPU modules, selected based on the board above. config NP405H bool @@ -142,12 +118,6 @@ config 405EX select IBM_NEW_EMAC_EMAC4 select IBM_NEW_EMAC_RGMII -config 405EZ - bool - select IBM_NEW_EMAC_NO_FLOW_CTRL - select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT - select IBM_NEW_EMAC_MAL_COMMON_ERR - config 405GPR bool @@ -169,14 +139,6 @@ config STB03xxx select IBM405_ERR77 select IBM405_ERR51 -config PPC4xx_GPIO - bool "PPC4xx GPIO support" - depends on 40x - select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO - help - Enable gpiolib support for ppc40x based boards - # 40x errata/workaround config symbols, selected by the CPU models above # All 405-based cores up until the 405GPR and 405EP have this errata. diff --git a/trunk/arch/powerpc/platforms/40x/Makefile b/trunk/arch/powerpc/platforms/40x/Makefile index 9bab76a652a6..5533a5c8ce4e 100644 --- a/trunk/arch/powerpc/platforms/40x/Makefile +++ b/trunk/arch/powerpc/platforms/40x/Makefile @@ -1,7 +1,5 @@ obj-$(CONFIG_KILAUEA) += kilauea.o -obj-$(CONFIG_HCU4) += hcu4.o obj-$(CONFIG_MAKALU) += makalu.o obj-$(CONFIG_WALNUT) += walnut.o obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o obj-$(CONFIG_EP405) += ep405.o -obj-$(CONFIG_PPC40x_SIMPLE) += ppc40x_simple.o diff --git a/trunk/arch/powerpc/platforms/40x/hcu4.c b/trunk/arch/powerpc/platforms/40x/hcu4.c deleted file mode 100644 index 60b2afecab75..000000000000 --- a/trunk/arch/powerpc/platforms/40x/hcu4.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Architecture- / platform-specific boot-time initialization code for - * IBM PowerPC 4xx based boards. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - * Copyright(c) 1999-2000 Grant Erickson - * - * Rewritten and ported to the merged powerpc tree: - * Copyright 2007 IBM Corporation - * Josh Boyer - * - * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -static __initdata struct of_device_id hcu4_of_bus[] = { - { .compatible = "ibm,plb3", }, - { .compatible = "ibm,opb", }, - { .compatible = "ibm,ebc", }, - {}, -}; - -static int __init hcu4_device_probe(void) -{ - of_platform_bus_probe(NULL, hcu4_of_bus, NULL); - return 0; -} -machine_device_initcall(hcu4, hcu4_device_probe); - -static int __init hcu4_probe(void) -{ - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "netstal,hcu4")) - return 0; - - return 1; -} - -define_machine(hcu4) { - .name = "HCU4", - .probe = hcu4_probe, - .progress = udbg_progress, - .init_IRQ = uic_init_tree, - .get_irq = uic_get_irq, - .restart = ppc4xx_reset_system, - .calibrate_decr = generic_calibrate_decr, -}; diff --git a/trunk/arch/powerpc/platforms/40x/ppc40x_simple.c b/trunk/arch/powerpc/platforms/40x/ppc40x_simple.c deleted file mode 100644 index 4498a86b46c3..000000000000 --- a/trunk/arch/powerpc/platforms/40x/ppc40x_simple.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Generic PowerPC 40x platform support - * - * Copyright 2008 IBM Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2 of the License. - * - * This implements simple platform support for PowerPC 44x chips. This is - * mostly used for eval boards or other simple and "generic" 44x boards. If - * your board has custom functions or hardware, then you will likely want to - * implement your own board.c file to accommodate it. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static __initdata struct of_device_id ppc40x_of_bus[] = { - { .compatible = "ibm,plb3", }, - { .compatible = "ibm,plb4", }, - { .compatible = "ibm,opb", }, - { .compatible = "ibm,ebc", }, - { .compatible = "simple-bus", }, - {}, -}; - -static int __init ppc40x_device_probe(void) -{ - of_platform_bus_probe(NULL, ppc40x_of_bus, NULL); - - return 0; -} -machine_device_initcall(ppc40x_simple, ppc40x_device_probe); - -/* This is the list of boards that can be supported by this simple - * platform code. This does _not_ mean the boards are compatible, - * as they most certainly are not from a device tree perspective. - * However, their differences are handled by the device tree and the - * drivers and therefore they don't need custom board support files. - * - * Again, if your board needs to do things differently then create a - * board.c file for it rather than adding it to this list. - */ -static char *board[] __initdata = { - "amcc,acadia" -}; - -static int __init ppc40x_probe(void) -{ - unsigned long root = of_get_flat_dt_root(); - int i = 0; - - for (i = 0; i < ARRAY_SIZE(board); i++) { - if (of_flat_dt_is_compatible(root, board[i])) { - ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC; - return 1; - } - } - - return 0; -} - -define_machine(ppc40x_simple) { - .name = "PowerPC 40x Platform", - .probe = ppc40x_probe, - .progress = udbg_progress, - .init_IRQ = uic_init_tree, - .get_irq = uic_get_irq, - .restart = ppc4xx_reset_system, - .calibrate_decr = generic_calibrate_decr, -}; diff --git a/trunk/arch/powerpc/platforms/44x/Kconfig b/trunk/arch/powerpc/platforms/44x/Kconfig index 3496bc05058e..79c1154f88d4 100644 --- a/trunk/arch/powerpc/platforms/44x/Kconfig +++ b/trunk/arch/powerpc/platforms/44x/Kconfig @@ -167,14 +167,6 @@ config PPC44x_SIMPLE help This option enables the simple PowerPC 44x platform support. -config PPC4xx_GPIO - bool "PPC4xx GPIO support" - depends on 44x - select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO - help - Enable gpiolib support for ppc440 based boards - # 44x specific CPU modules, selected based on the board above. config 440EP bool diff --git a/trunk/arch/powerpc/platforms/52xx/mpc52xx_common.c b/trunk/arch/powerpc/platforms/52xx/mpc52xx_common.c index ae7c34f37e1c..044b4e6e8743 100644 --- a/trunk/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/trunk/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -99,14 +99,11 @@ mpc5200_setup_xlb_arbiter(void) out_be32(&xlb->master_pri_enable, 0xff); out_be32(&xlb->master_priority, 0x11111111); - /* - * Disable XLB pipelining + /* Disable XLB pipelining * (cfr errate 292. We could do this only just before ATA PIO * transaction and re-enable it afterwards ...) - * Not needed on MPC5200B. */ - if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) - out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); + out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); iounmap(xlb); } diff --git a/trunk/arch/powerpc/platforms/85xx/ksi8560.c b/trunk/arch/powerpc/platforms/85xx/ksi8560.c index 81cee7bbf2d2..8a3b117b6ce2 100644 --- a/trunk/arch/powerpc/platforms/85xx/ksi8560.c +++ b/trunk/arch/powerpc/platforms/85xx/ksi8560.c @@ -193,6 +193,7 @@ static void __init ksi8560_setup_arch(void) static void ksi8560_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -214,6 +215,9 @@ static void ksi8560_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 21f009023e26..0293e3d3580f 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -207,6 +207,7 @@ static void __init mpc85xx_ads_setup_arch(void) static void mpc85xx_ads_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -218,6 +219,9 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c index aeb6a5bc5522..50d7ea8f922b 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -307,6 +307,7 @@ static void __init mpc85xx_cds_setup_arch(void) static void mpc85xx_cds_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -319,6 +320,9 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } diff --git a/trunk/arch/powerpc/platforms/85xx/sbc8548.c b/trunk/arch/powerpc/platforms/85xx/sbc8548.c index 7ec77ce12dad..b9246ea0928a 100644 --- a/trunk/arch/powerpc/platforms/85xx/sbc8548.c +++ b/trunk/arch/powerpc/platforms/85xx/sbc8548.c @@ -136,6 +136,7 @@ static void __init sbc8548_setup_arch(void) static void sbc8548_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -148,6 +149,9 @@ static void sbc8548_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/85xx/sbc8560.c b/trunk/arch/powerpc/platforms/85xx/sbc8560.c index 472f254a19d2..0c9a856f66b6 100644 --- a/trunk/arch/powerpc/platforms/85xx/sbc8560.c +++ b/trunk/arch/powerpc/platforms/85xx/sbc8560.c @@ -194,6 +194,7 @@ static void __init sbc8560_setup_arch(void) static void sbc8560_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -205,6 +206,9 @@ static void sbc8560_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/85xx/stx_gp3.c b/trunk/arch/powerpc/platforms/85xx/stx_gp3.c index 0cca8f5cb272..18499d7c9d9e 100644 --- a/trunk/arch/powerpc/platforms/85xx/stx_gp3.c +++ b/trunk/arch/powerpc/platforms/85xx/stx_gp3.c @@ -130,6 +130,7 @@ static void __init stx_gp3_setup_arch(void) static void stx_gp3_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -141,6 +142,9 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/85xx/tqm85xx.c b/trunk/arch/powerpc/platforms/85xx/tqm85xx.c index 2933a8e827d9..d850880d6964 100644 --- a/trunk/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/trunk/arch/powerpc/platforms/85xx/tqm85xx.c @@ -138,6 +138,7 @@ static void __init tqm85xx_setup_arch(void) static void tqm85xx_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; + uint memsize = total_memory; pvid = mfspr(SPRN_PVR); svid = mfspr(SPRN_SVR); @@ -149,6 +150,9 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m) /* Display cpu Pll setting */ phid1 = mfspr(SPRN_HID1); seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static struct of_device_id __initdata of_bus_ids[] = { diff --git a/trunk/arch/powerpc/platforms/86xx/gef_sbc610.c b/trunk/arch/powerpc/platforms/86xx/gef_sbc610.c index fb371f5ce132..821c45fac18b 100644 --- a/trunk/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/trunk/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -127,6 +127,7 @@ static unsigned int gef_sbc610_get_fpga_rev(void) static void gef_sbc610_show_cpuinfo(struct seq_file *m) { + uint memsize = total_memory; uint svid = mfspr(SPRN_SVR); seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n"); @@ -136,6 +137,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m) seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc610_get_fpga_rev()); seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev) diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 27e0e682d8e1..2672829a71dc 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -101,11 +101,13 @@ mpc86xx_hpcn_setup_arch(void) static void mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) { + uint memsize = total_memory; uint svid = mfspr(SPRN_SVR); seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } diff --git a/trunk/arch/powerpc/platforms/86xx/sbc8641d.c b/trunk/arch/powerpc/platforms/86xx/sbc8641d.c index 5fd7ed40986f..da677a74e2d1 100644 --- a/trunk/arch/powerpc/platforms/86xx/sbc8641d.c +++ b/trunk/arch/powerpc/platforms/86xx/sbc8641d.c @@ -63,11 +63,13 @@ sbc8641_setup_arch(void) static void sbc8641_show_cpuinfo(struct seq_file *m) { + uint memsize = total_memory; uint svid = mfspr(SPRN_SVR); seq_printf(m, "Vendor\t\t: Wind River Systems\n"); seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } diff --git a/trunk/arch/powerpc/platforms/cell/ras.c b/trunk/arch/powerpc/platforms/cell/ras.c index 665af1c4195b..2a14b052abcd 100644 --- a/trunk/arch/powerpc/platforms/cell/ras.c +++ b/trunk/arch/powerpc/platforms/cell/ras.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "ras.h" @@ -112,8 +111,9 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order) int ret = -ENOMEM; unsigned long addr; - if (__kdump_flag) - rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); +#ifdef CONFIG_CRASH_DUMP + rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); +#endif area = kmalloc(sizeof(*area), GFP_KERNEL); if (!area) diff --git a/trunk/arch/powerpc/platforms/cell/smp.c b/trunk/arch/powerpc/platforms/cell/smp.c index c0d86e1f56ea..efb3964457b1 100644 --- a/trunk/arch/powerpc/platforms/cell/smp.c +++ b/trunk/arch/powerpc/platforms/cell/smp.c @@ -54,8 +54,8 @@ #endif /* - * The Primary thread of each non-boot processor was started from the OF client - * interface by prom_hold_cpus and is spinning on secondary_hold_spinloop. + * The primary thread of each non-boot processor is recorded here before + * smp init. */ static cpumask_t of_spin_map; @@ -208,7 +208,11 @@ void __init smp_init_cell(void) /* Mark threads which are still spinning in hold loops. */ if (cpu_has_feature(CPU_FTR_SMT)) { for_each_present_cpu(i) { - if (cpu_thread_in_core(i) == 0) + if (i % 2 == 0) + /* + * Even-numbered logical cpus correspond to + * primary threads. + */ cpu_set(i, of_spin_map); } } else { diff --git a/trunk/arch/powerpc/platforms/cell/spufs/file.c b/trunk/arch/powerpc/platforms/cell/spufs/file.c index b73c369cc6f1..010a51f59796 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/file.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/file.c @@ -548,11 +548,6 @@ spufs_regs_read(struct file *file, char __user *buffer, int ret; struct spu_context *ctx = file->private_data; - /* pre-check for file position: if we'd return EOF, there's no point - * causing a deschedule */ - if (*pos >= sizeof(ctx->csa.lscsa->gprs)) - return 0; - ret = spu_acquire_saved(ctx); if (ret) return ret; @@ -2431,49 +2426,38 @@ static inline int spufs_switch_log_avail(struct spu_context *ctx) static int spufs_switch_log_open(struct inode *inode, struct file *file) { struct spu_context *ctx = SPUFS_I(inode)->i_ctx; - int rc; - - rc = spu_acquire(ctx); - if (rc) - return rc; + /* + * We (ab-)use the mapping_lock here because it serves the similar + * purpose for synchronizing open/close elsewhere. Maybe it should + * be renamed eventually. + */ + mutex_lock(&ctx->mapping_lock); if (ctx->switch_log) { - rc = -EBUSY; - goto out; - } - - ctx->switch_log = kmalloc(sizeof(struct switch_log) + - SWITCH_LOG_BUFSIZE * sizeof(struct switch_log_entry), - GFP_KERNEL); - - if (!ctx->switch_log) { - rc = -ENOMEM; - goto out; + spin_lock(&ctx->switch_log->lock); + ctx->switch_log->head = 0; + ctx->switch_log->tail = 0; + spin_unlock(&ctx->switch_log->lock); + } else { + /* + * We allocate the switch log data structures on first open. + * They will never be free because we assume a context will + * be traced until it goes away. + */ + ctx->switch_log = kzalloc(sizeof(struct switch_log) + + SWITCH_LOG_BUFSIZE * sizeof(struct switch_log_entry), + GFP_KERNEL); + if (!ctx->switch_log) + goto out; + spin_lock_init(&ctx->switch_log->lock); + init_waitqueue_head(&ctx->switch_log->wait); } - - ctx->switch_log->head = ctx->switch_log->tail = 0; - init_waitqueue_head(&ctx->switch_log->wait); - rc = 0; - -out: - spu_release(ctx); - return rc; -} - -static int spufs_switch_log_release(struct inode *inode, struct file *file) -{ - struct spu_context *ctx = SPUFS_I(inode)->i_ctx; - int rc; - - rc = spu_acquire(ctx); - if (rc) - return rc; - - kfree(ctx->switch_log); - ctx->switch_log = NULL; - spu_release(ctx); + mutex_unlock(&ctx->mapping_lock); return 0; + out: + mutex_unlock(&ctx->mapping_lock); + return -ENOMEM; } static int switch_log_sprint(struct spu_context *ctx, char *tbuf, int n) @@ -2501,54 +2485,42 @@ static ssize_t spufs_switch_log_read(struct file *file, char __user *buf, if (!buf || len < 0) return -EINVAL; - error = spu_acquire(ctx); - if (error) - return error; - while (cnt < len) { char tbuf[128]; int width; - if (spufs_switch_log_used(ctx) == 0) { - if (cnt > 0) { - /* If there's data ready to go, we can - * just return straight away */ - break; - - } else if (file->f_flags & O_NONBLOCK) { - error = -EAGAIN; + if (file->f_flags & O_NONBLOCK) { + if (spufs_switch_log_used(ctx) <= 0) + return cnt ? cnt : -EAGAIN; + } else { + /* Wait for data in buffer */ + error = wait_event_interruptible(ctx->switch_log->wait, + spufs_switch_log_used(ctx) > 0); + if (error) break; + } - } else { - /* spufs_wait will drop the mutex and - * re-acquire, but since we're in read(), the - * file cannot be _released (and so - * ctx->switch_log is stable). - */ - error = spufs_wait(ctx->switch_log->wait, - spufs_switch_log_used(ctx) > 0); - - /* On error, spufs_wait returns without the - * state mutex held */ - if (error) - return error; - - /* We may have had entries read from underneath - * us while we dropped the mutex in spufs_wait, - * so re-check */ - if (spufs_switch_log_used(ctx) == 0) - continue; - } + spin_lock(&ctx->switch_log->lock); + if (ctx->switch_log->head == ctx->switch_log->tail) { + /* multiple readers race? */ + spin_unlock(&ctx->switch_log->lock); + continue; } width = switch_log_sprint(ctx, tbuf, sizeof(tbuf)); - if (width < len) + if (width < len) { ctx->switch_log->tail = (ctx->switch_log->tail + 1) % SWITCH_LOG_BUFSIZE; - else - /* If the record is greater than space available return - * partial buffer (so far) */ + } + + spin_unlock(&ctx->switch_log->lock); + + /* + * If the record is greater than space available return + * partial buffer (so far) + */ + if (width >= len) break; error = copy_to_user(buf + cnt, tbuf, width); @@ -2557,8 +2529,6 @@ static ssize_t spufs_switch_log_read(struct file *file, char __user *buf, cnt += width; } - spu_release(ctx); - return cnt == 0 ? error : cnt; } @@ -2567,41 +2537,29 @@ static unsigned int spufs_switch_log_poll(struct file *file, poll_table *wait) struct inode *inode = file->f_path.dentry->d_inode; struct spu_context *ctx = SPUFS_I(inode)->i_ctx; unsigned int mask = 0; - int rc; poll_wait(file, &ctx->switch_log->wait, wait); - rc = spu_acquire(ctx); - if (rc) - return rc; - if (spufs_switch_log_used(ctx) > 0) mask |= POLLIN; - spu_release(ctx); - return mask; } static const struct file_operations spufs_switch_log_fops = { - .owner = THIS_MODULE, - .open = spufs_switch_log_open, - .read = spufs_switch_log_read, - .poll = spufs_switch_log_poll, - .release = spufs_switch_log_release, + .owner = THIS_MODULE, + .open = spufs_switch_log_open, + .read = spufs_switch_log_read, + .poll = spufs_switch_log_poll, }; -/** - * Log a context switch event to a switch log reader. - * - * Must be called with ctx->state_mutex held. - */ void spu_switch_log_notify(struct spu *spu, struct spu_context *ctx, u32 type, u32 val) { if (!ctx->switch_log) return; + spin_lock(&ctx->switch_log->lock); if (spufs_switch_log_avail(ctx) > 1) { struct switch_log_entry *p; @@ -2615,6 +2573,7 @@ void spu_switch_log_notify(struct spu *spu, struct spu_context *ctx, ctx->switch_log->head = (ctx->switch_log->head + 1) % SWITCH_LOG_BUFSIZE; } + spin_unlock(&ctx->switch_log->lock); wake_up(&ctx->switch_log->wait); } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/run.c b/trunk/arch/powerpc/platforms/cell/spufs/run.c index c58bd36b0c5b..c9bb7cfd3dca 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/run.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/run.c @@ -249,7 +249,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 *npc, spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); clear_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags); - spu_switch_log_notify(NULL, ctx, SWITCH_LOG_EXIT, *status); spu_release(ctx); if (signal_pending(current)) @@ -418,6 +417,8 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) ret = spu_run_fini(ctx, npc, &status); spu_yield(ctx); + spu_switch_log_notify(NULL, ctx, SWITCH_LOG_EXIT, status); + if ((status & SPU_STATUS_STOPPED_BY_STOP) && (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100)) ctx->stats.libassist++; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/sched.c b/trunk/arch/powerpc/platforms/cell/spufs/sched.c index 2ad914c47493..67595bc380dc 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/sched.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/sched.c @@ -312,15 +312,6 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff, */ node = cpu_to_node(raw_smp_processor_id()); for (n = 0; n < MAX_NUMNODES; n++, node++) { - /* - * "available_spus" counts how many spus are not potentially - * going to be used by other affinity gangs whose reference - * context is already in place. Although this code seeks to - * avoid having affinity gangs with a summed amount of - * contexts bigger than the amount of spus in the node, - * this may happen sporadically. In this case, available_spus - * becomes negative, which is harmless. - */ int available_spus; node = (node < MAX_NUMNODES) ? node : 0; @@ -330,10 +321,12 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff, available_spus = 0; mutex_lock(&cbe_spu_info[node].list_mutex); list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { - if (spu->ctx && spu->ctx->gang && !spu->ctx->aff_offset - && spu->ctx->gang->aff_ref_spu) - available_spus -= spu->ctx->gang->contexts; - available_spus++; + if (spu->ctx && spu->ctx->gang + && spu->ctx->aff_offset == 0) + available_spus -= + (spu->ctx->gang->contexts - 1); + else + available_spus++; } if (available_spus < ctx->gang->contexts) { mutex_unlock(&cbe_spu_info[node].list_mutex); @@ -444,11 +437,6 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) atomic_dec(&cbe_spu_info[spu->node].reserved_spus); if (ctx->gang) - /* - * If ctx->gang->aff_sched_count is positive, SPU affinity is - * being considered in this gang. Using atomic_dec_if_positive - * allow us to skip an explicit check for affinity in this gang - */ atomic_dec_if_positive(&ctx->gang->aff_sched_count); spu_switch_notify(spu, NULL); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h index 15c62d3ca129..8ae8ef9dfc22 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h @@ -65,6 +65,7 @@ enum { }; struct switch_log { + spinlock_t lock; wait_queue_head_t wait; unsigned long head; unsigned long tail; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/sputrace.c b/trunk/arch/powerpc/platforms/cell/spufs/sputrace.c index d0b1f3f4d9c8..2ece399f2862 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/sputrace.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/sputrace.c @@ -40,7 +40,6 @@ static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait); static ktime_t sputrace_start; static unsigned long sputrace_head, sputrace_tail; static struct sputrace *sputrace_log; -static int sputrace_logging; static int sputrace_used(void) { @@ -80,11 +79,6 @@ static ssize_t sputrace_read(struct file *file, char __user *buf, char tbuf[128]; int width; - /* If we have data ready to return, don't block waiting - * for more */ - if (cnt > 0 && sputrace_used() == 0) - break; - error = wait_event_interruptible(sputrace_wait, sputrace_used() > 0); if (error) @@ -115,49 +109,24 @@ static ssize_t sputrace_read(struct file *file, char __user *buf, static int sputrace_open(struct inode *inode, struct file *file) { - int rc; - spin_lock(&sputrace_lock); - if (sputrace_logging) { - rc = -EBUSY; - goto out; - } - - sputrace_logging = 1; sputrace_head = sputrace_tail = 0; sputrace_start = ktime_get(); - rc = 0; - -out: spin_unlock(&sputrace_lock); - return rc; -} -static int sputrace_release(struct inode *inode, struct file *file) -{ - spin_lock(&sputrace_lock); - sputrace_logging = 0; - spin_unlock(&sputrace_lock); return 0; } static const struct file_operations sputrace_fops = { - .owner = THIS_MODULE, - .open = sputrace_open, - .read = sputrace_read, - .release = sputrace_release, + .owner = THIS_MODULE, + .open = sputrace_open, + .read = sputrace_read, }; static void sputrace_log_item(const char *name, struct spu_context *ctx, struct spu *spu) { spin_lock(&sputrace_lock); - - if (!sputrace_logging) { - spin_unlock(&sputrace_lock); - return; - } - if (sputrace_avail() > 1) { struct sputrace *t = sputrace_log + sputrace_head; diff --git a/trunk/arch/powerpc/platforms/embedded6xx/c2k.c b/trunk/arch/powerpc/platforms/embedded6xx/c2k.c index 32ba0fa0ad03..d0b25b8c39d1 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/c2k.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/c2k.c @@ -116,7 +116,10 @@ static void c2k_restart(char *cmd) void c2k_show_cpuinfo(struct seq_file *m) { + uint memsize = total_memory; + seq_printf(m, "Vendor\t\t: GEFanuc\n"); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); seq_printf(m, "coherency\t: %s\n", COHERENCY_SETTING); } diff --git a/trunk/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/trunk/arch/powerpc/platforms/embedded6xx/prpmc2800.c index 4c485e984236..5a19b9a1457c 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/prpmc2800.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/prpmc2800.c @@ -119,7 +119,10 @@ static void prpmc2800_restart(char *cmd) void prpmc2800_show_cpuinfo(struct seq_file *m) { + uint memsize = total_memory; + seq_printf(m, "Vendor\t\t: Motorola\n"); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); seq_printf(m, "coherency\t: %s\n", PPRPM2800_COHERENCY_SETTING); } diff --git a/trunk/arch/powerpc/platforms/pseries/hotplug-memory.c b/trunk/arch/powerpc/platforms/pseries/hotplug-memory.c index a623ad256e9e..140d02a5232a 100644 --- a/trunk/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/trunk/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -22,12 +22,6 @@ static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size) int ret; start_pfn = base >> PAGE_SHIFT; - - if (!pfn_valid(start_pfn)) { - lmb_remove(base, lmb_size); - return 0; - } - zone = page_zone(pfn_to_page(start_pfn)); /* diff --git a/trunk/arch/powerpc/platforms/pseries/iommu.c b/trunk/arch/powerpc/platforms/pseries/iommu.c index d56491d182d3..a8c446697f9e 100644 --- a/trunk/arch/powerpc/platforms/pseries/iommu.c +++ b/trunk/arch/powerpc/platforms/pseries/iommu.c @@ -44,7 +44,6 @@ #include #include #include -#include #include "plpar_wrappers.h" @@ -292,8 +291,9 @@ static void iommu_table_setparms(struct pci_controller *phb, tbl->it_base = (unsigned long)__va(*basep); - if (!__kdump_flag) - memset((void *)tbl->it_base, 0, *sizep); +#ifndef CONFIG_CRASH_DUMP + memset((void *)tbl->it_base, 0, *sizep); +#endif tbl->it_busno = phb->bus->number; diff --git a/trunk/arch/powerpc/platforms/pseries/smp.c b/trunk/arch/powerpc/platforms/pseries/smp.c index 1a231c389ba0..e00f96baa381 100644 --- a/trunk/arch/powerpc/platforms/pseries/smp.c +++ b/trunk/arch/powerpc/platforms/pseries/smp.c @@ -52,8 +52,8 @@ /* - * The Primary thread of each non-boot processor was started from the OF client - * interface by prom_hold_cpus and is spinning on secondary_hold_spinloop. + * The primary thread of each non-boot processor is recorded here before + * smp init. */ static cpumask_t of_spin_map; @@ -161,7 +161,8 @@ static void __devinit smp_pSeries_kick_cpu(int nr) static int smp_pSeries_cpu_bootable(unsigned int nr) { /* Special case - we inhibit secondary thread startup - * during boot if the user requests it. + * during boot if the user requests it. Odd-numbered + * cpus are assumed to be secondary threads. */ if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT) && @@ -198,7 +199,11 @@ static void __init smp_init_pseries(void) /* Mark threads which are still spinning in hold loops. */ if (cpu_has_feature(CPU_FTR_SMT)) { for_each_present_cpu(i) { - if (cpu_thread_in_core(i) == 0) + if (i % 2 == 0) + /* + * Even-numbered logical cpus correspond to + * primary threads. + */ cpu_set(i, of_spin_map); } } else { diff --git a/trunk/arch/powerpc/sysdev/Makefile b/trunk/arch/powerpc/sysdev/Makefile index 5afce115ab1f..a44709a94f97 100644 --- a/trunk/arch/powerpc/sysdev/Makefile +++ b/trunk/arch/powerpc/sysdev/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o ifeq ($(CONFIG_PCI),y) obj-$(CONFIG_4xx) += ppc4xx_pci.o endif -obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o obj-$(CONFIG_CPM) += cpm_common.o obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o diff --git a/trunk/arch/powerpc/sysdev/ppc4xx_gpio.c b/trunk/arch/powerpc/sysdev/ppc4xx_gpio.c deleted file mode 100644 index 110efe2a54fc..000000000000 --- a/trunk/arch/powerpc/sysdev/ppc4xx_gpio.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * PPC4xx gpio driver - * - * Copyright (c) 2008 Harris Corporation - * Copyright (c) 2008 Sascha Hauer , Pengutronix - * Copyright (c) MontaVista Software, Inc. 2008. - * - * Author: Steve Falco - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define GPIO_MASK(gpio) (0x80000000 >> (gpio)) -#define GPIO_MASK2(gpio) (0xc0000000 >> ((gpio) * 2)) - -/* Physical GPIO register layout */ -struct ppc4xx_gpio { - __be32 or; - __be32 tcr; - __be32 osrl; - __be32 osrh; - __be32 tsrl; - __be32 tsrh; - __be32 odr; - __be32 ir; - __be32 rr1; - __be32 rr2; - __be32 rr3; - __be32 reserved1; - __be32 isr1l; - __be32 isr1h; - __be32 isr2l; - __be32 isr2h; - __be32 isr3l; - __be32 isr3h; -}; - -struct ppc4xx_gpio_chip { - struct of_mm_gpio_chip mm_gc; - spinlock_t lock; -}; - -/* - * GPIO LIB API implementation for GPIOs - * - * There are a maximum of 32 gpios in each gpio controller. - */ - -static inline struct ppc4xx_gpio_chip * -to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc) -{ - return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc); -} - -static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio __iomem *regs = mm_gc->regs; - - return in_be32(®s->ir) & GPIO_MASK(gpio); -} - -static inline void -__ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio __iomem *regs = mm_gc->regs; - - if (val) - setbits32(®s->or, GPIO_MASK(gpio)); - else - clrbits32(®s->or, GPIO_MASK(gpio)); -} - -static void -ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - __ppc4xx_gpio_set(gc, gpio, val); - - spin_unlock_irqrestore(&chip->lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); -} - -static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); - struct ppc4xx_gpio __iomem *regs = mm_gc->regs; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - /* Disable open-drain function */ - clrbits32(®s->odr, GPIO_MASK(gpio)); - - /* Float the pin */ - clrbits32(®s->tcr, GPIO_MASK(gpio)); - - /* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */ - if (gpio < 16) { - clrbits32(®s->osrl, GPIO_MASK2(gpio)); - clrbits32(®s->tsrl, GPIO_MASK2(gpio)); - } else { - clrbits32(®s->osrh, GPIO_MASK2(gpio)); - clrbits32(®s->tsrh, GPIO_MASK2(gpio)); - } - - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -static int -ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); - struct ppc4xx_gpio __iomem *regs = mm_gc->regs; - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - /* First set initial value */ - __ppc4xx_gpio_set(gc, gpio, val); - - /* Disable open-drain function */ - clrbits32(®s->odr, GPIO_MASK(gpio)); - - /* Drive the pin */ - setbits32(®s->tcr, GPIO_MASK(gpio)); - - /* Bits 0-15 use TSRL, bits 16-31 use TSRH */ - if (gpio < 16) { - clrbits32(®s->osrl, GPIO_MASK2(gpio)); - clrbits32(®s->tsrl, GPIO_MASK2(gpio)); - } else { - clrbits32(®s->osrh, GPIO_MASK2(gpio)); - clrbits32(®s->tsrh, GPIO_MASK2(gpio)); - } - - spin_unlock_irqrestore(&chip->lock, flags); - - pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); - - return 0; -} - -static int __init ppc4xx_add_gpiochips(void) -{ - struct device_node *np; - - for_each_compatible_node(np, NULL, "ibm,ppc4xx-gpio") { - int ret; - struct ppc4xx_gpio_chip *ppc4xx_gc; - struct of_mm_gpio_chip *mm_gc; - struct of_gpio_chip *of_gc; - struct gpio_chip *gc; - - ppc4xx_gc = kzalloc(sizeof(*ppc4xx_gc), GFP_KERNEL); - if (!ppc4xx_gc) { - ret = -ENOMEM; - goto err; - } - - spin_lock_init(&ppc4xx_gc->lock); - - mm_gc = &ppc4xx_gc->mm_gc; - of_gc = &mm_gc->of_gc; - gc = &of_gc->gc; - - of_gc->gpio_cells = 2; - gc->ngpio = 32; - gc->direction_input = ppc4xx_gpio_dir_in; - gc->direction_output = ppc4xx_gpio_dir_out; - gc->get = ppc4xx_gpio_get; - gc->set = ppc4xx_gpio_set; - - ret = of_mm_gpiochip_add(np, mm_gc); - if (ret) - goto err; - continue; -err: - pr_err("%s: registration failed with status %d\n", - np->full_name, ret); - kfree(ppc4xx_gc); - /* try others anyway */ - } - return 0; -} -arch_initcall(ppc4xx_add_gpiochips); diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 6c873dceb177..a213260b51e5 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -64,12 +64,7 @@ choice default XTENSA_VARIANT_FSF config XTENSA_VARIANT_FSF - bool "fsf - default (not generic) configuration" - -config XTENSA_VARIANT_DC232B - bool "dc232b - Diamond 232L Standard Core Rev.B (LE)" - help - This variant refers to Tensilica's Diamond 232L Standard core Rev.B (LE). + bool "fsf" endchoice config MMU diff --git a/trunk/arch/xtensa/Makefile b/trunk/arch/xtensa/Makefile index 015b6b2a26b9..4bd1e14c6b90 100644 --- a/trunk/arch/xtensa/Makefile +++ b/trunk/arch/xtensa/Makefile @@ -14,7 +14,6 @@ # (Use VAR= to use another default compiler.) variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf -variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom VARIANT = $(variant-y) diff --git a/trunk/arch/xtensa/kernel/irq.c b/trunk/arch/xtensa/kernel/irq.c index 5fbcde59a92d..c9ea73b7031b 100644 --- a/trunk/arch/xtensa/kernel/irq.c +++ b/trunk/arch/xtensa/kernel/irq.c @@ -48,7 +48,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) if (irq >= NR_IRQS) { printk(KERN_EMERG "%s: cannot handle IRQ %d\n", - __func__, irq); + __FUNCTION__, irq); } irq_enter(); diff --git a/trunk/arch/xtensa/platforms/iss/network.c b/trunk/arch/xtensa/platforms/iss/network.c index 11a20adc1409..a2e252217428 100644 --- a/trunk/arch/xtensa/platforms/iss/network.c +++ b/trunk/arch/xtensa/platforms/iss/network.c @@ -640,7 +640,7 @@ static int iss_net_configure(int index, char *init) *lp = ((struct iss_net_private) { .device_list = LIST_HEAD_INIT(lp->device_list), .opened_list = LIST_HEAD_INIT(lp->opened_list), - .lock = __SPIN_LOCK_UNLOCKED(lp.lock), + .lock = SPIN_LOCK_UNLOCKED, .dev = dev, .index = index, //.fd = -1, diff --git a/trunk/drivers/Kconfig b/trunk/drivers/Kconfig index d38f43f593d4..d19b6f5a1106 100644 --- a/trunk/drivers/Kconfig +++ b/trunk/drivers/Kconfig @@ -78,8 +78,6 @@ source "drivers/hid/Kconfig" source "drivers/usb/Kconfig" -source "drivers/uwb/Kconfig" - source "drivers/mmc/Kconfig" source "drivers/memstick/Kconfig" diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index cadc64fe8f68..46c8681a07f4 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -100,4 +100,3 @@ obj-$(CONFIG_SSB) += ssb/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_REGULATOR) += regulator/ obj-$(CONFIG_STAGING) += staging/ -obj-$(CONFIG_UWB) += uwb/ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index bbb3cae57492..1ee9499bd343 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -5373,8 +5373,6 @@ struct ata_port *ata_port_alloc(struct ata_host *host) #ifdef CONFIG_ATA_SFF INIT_DELAYED_WORK(&ap->port_task, ata_pio_task); -#else - INIT_DELAYED_WORK(&ap->port_task, NULL); #endif INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); diff --git a/trunk/drivers/ata/libata-eh.c b/trunk/drivers/ata/libata-eh.c index 5d687d7cffae..a93247cc395a 100644 --- a/trunk/drivers/ata/libata-eh.c +++ b/trunk/drivers/ata/libata-eh.c @@ -1206,10 +1206,7 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, ata_eh_clear_action(link, dev, ehi, action); - /* About to take EH action, set RECOVERED. Ignore actions on - * slave links as master will do them again. - */ - if (!(ehc->i.flags & ATA_EHI_QUIET) && link != ap->slave_link) + if (!(ehc->i.flags & ATA_EHI_QUIET)) ap->pflags |= ATA_PFLAG_RECOVERED; spin_unlock_irqrestore(ap->lock, flags); @@ -2013,13 +2010,8 @@ void ata_eh_autopsy(struct ata_port *ap) struct ata_eh_context *mehc = &ap->link.eh_context; struct ata_eh_context *sehc = &ap->slave_link->eh_context; - /* transfer control flags from master to slave */ - sehc->i.flags |= mehc->i.flags & ATA_EHI_TO_SLAVE_MASK; - - /* perform autopsy on the slave link */ ata_eh_link_autopsy(ap->slave_link); - /* transfer actions from slave to master and clear slave */ ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS); mehc->i.action |= sehc->i.action; mehc->i.dev_action[1] |= sehc->i.dev_action[1]; @@ -2455,14 +2447,14 @@ int ata_eh_reset(struct ata_link *link, int classify, dev->pio_mode = XFER_PIO_0; dev->flags &= ~ATA_DFLAG_SLEEPING; - if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { - /* apply class override */ - if (lflags & ATA_LFLAG_ASSUME_ATA) - classes[dev->devno] = ATA_DEV_ATA; - else if (lflags & ATA_LFLAG_ASSUME_SEMB) - classes[dev->devno] = ATA_DEV_SEMB_UNSUP; - } else - classes[dev->devno] = ATA_DEV_NONE; + if (ata_phys_link_offline(ata_dev_phys_link(dev))) + continue; + + /* apply class override */ + if (lflags & ATA_LFLAG_ASSUME_ATA) + classes[dev->devno] = ATA_DEV_ATA; + else if (lflags & ATA_LFLAG_ASSUME_SEMB) + classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */ } /* record current link speed */ diff --git a/trunk/drivers/ata/libata-sff.c b/trunk/drivers/ata/libata-sff.c index 4b4739486327..2a4c516894f0 100644 --- a/trunk/drivers/ata/libata-sff.c +++ b/trunk/drivers/ata/libata-sff.c @@ -2153,17 +2153,8 @@ void ata_sff_error_handler(struct ata_port *ap) */ void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc) { - struct ata_port *ap = qc->ap; - unsigned long flags; - - spin_lock_irqsave(ap->lock, flags); - - ap->hsm_task_state = HSM_ST_IDLE; - - if (ap->ioaddr.bmdma_addr) + if (qc->ap->ioaddr.bmdma_addr) ata_bmdma_stop(qc); - - spin_unlock_irqrestore(ap->lock, flags); } /** diff --git a/trunk/drivers/ata/sata_via.c b/trunk/drivers/ata/sata_via.c index 5b72e734300a..1cfa74535d91 100644 --- a/trunk/drivers/ata/sata_via.c +++ b/trunk/drivers/ata/sata_via.c @@ -70,7 +70,6 @@ enum { static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); -static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); static void svia_noop_freeze(struct ata_port *ap); static int vt6420_prereset(struct ata_link *link, unsigned long deadline); static int vt6421_pata_cable_detect(struct ata_port *ap); @@ -104,26 +103,21 @@ static struct scsi_host_template svia_sht = { ATA_BMDMA_SHT(DRV_NAME), }; -static struct ata_port_operations svia_base_ops = { - .inherits = &ata_bmdma_port_ops, - .sff_tf_load = svia_tf_load, -}; - static struct ata_port_operations vt6420_sata_ops = { - .inherits = &svia_base_ops, + .inherits = &ata_bmdma_port_ops, .freeze = svia_noop_freeze, .prereset = vt6420_prereset, }; static struct ata_port_operations vt6421_pata_ops = { - .inherits = &svia_base_ops, + .inherits = &ata_bmdma_port_ops, .cable_detect = vt6421_pata_cable_detect, .set_piomode = vt6421_set_pio_mode, .set_dmamode = vt6421_set_dma_mode, }; static struct ata_port_operations vt6421_sata_ops = { - .inherits = &svia_base_ops, + .inherits = &ata_bmdma_port_ops, .scr_read = svia_scr_read, .scr_write = svia_scr_write, }; @@ -174,29 +168,6 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) return 0; } -/** - * svia_tf_load - send taskfile registers to host controller - * @ap: Port to which output is sent - * @tf: ATA taskfile register set - * - * Outputs ATA taskfile to standard ATA host controller. - * - * This is to fix the internal bug of via chipsets, which will - * reset the device register after changing the IEN bit on ctl - * register. - */ -static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) -{ - struct ata_taskfile ttf; - - if (tf->ctl != ap->last_ctl) { - ttf = *tf; - ttf.flags |= ATA_TFLAG_DEVICE; - tf = &ttf; - } - ata_sff_tf_load(ap, tf); -} - static void svia_noop_freeze(struct ata_port *ap) { /* Some VIA controllers choke if ATA_NIEN is manipulated in diff --git a/trunk/drivers/char/agp/parisc-agp.c b/trunk/drivers/char/agp/parisc-agp.c index db60539bf67a..f2492ecf0824 100644 --- a/trunk/drivers/char/agp/parisc-agp.c +++ b/trunk/drivers/char/agp/parisc-agp.c @@ -20,8 +20,8 @@ #include #include -#include -#include +#include +#include #include "agp.h" diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c index 5b819b12675a..bf70450a49cc 100644 --- a/trunk/drivers/char/hvc_console.c +++ b/trunk/drivers/char/hvc_console.c @@ -161,7 +161,7 @@ static void hvc_console_print(struct console *co, const char *b, } } else { r = cons_ops[index]->put_chars(vtermnos[index], c, i); - if (r <= 0) { + if (r < 0) { /* throw away chars on error */ i = 0; } else if (r > 0) { @@ -374,9 +374,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) if (hp->ops->notifier_del) hp->ops->notifier_del(hp, hp->data); - /* cancel pending tty resize work */ - cancel_work_sync(&hp->tty_resize); - /* * Chain calls chars_in_buffer() and returns immediately if * there is no buffered data otherwise sleeps on a wait queue @@ -402,9 +399,6 @@ static void hvc_hangup(struct tty_struct *tty) if (!hp) return; - /* cancel pending tty resize work */ - cancel_work_sync(&hp->tty_resize); - spin_lock_irqsave(&hp->lock, flags); /* @@ -424,8 +418,8 @@ static void hvc_hangup(struct tty_struct *tty) spin_unlock_irqrestore(&hp->lock, flags); - if (hp->ops->notifier_hangup) - hp->ops->notifier_hangup(hp, hp->data); + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); while(temp_open_count) { --temp_open_count; @@ -437,7 +431,7 @@ static void hvc_hangup(struct tty_struct *tty) * Push buffered characters whether they were just recently buffered or waiting * on a blocked hypervisor. Call this function with hp->lock held. */ -static int hvc_push(struct hvc_struct *hp) +static void hvc_push(struct hvc_struct *hp) { int n; @@ -445,7 +439,7 @@ static int hvc_push(struct hvc_struct *hp) if (n <= 0) { if (n == 0) { hp->do_wakeup = 1; - return 0; + return; } /* throw away output on error; this happens when there is no session connected to the vterm. */ @@ -456,8 +450,6 @@ static int hvc_push(struct hvc_struct *hp) memmove(hp->outbuf, hp->outbuf + n, hp->n_outbuf); else hp->do_wakeup = 1; - - return n; } static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -500,39 +492,6 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count return written; } -/** - * hvc_set_winsz() - Resize the hvc tty terminal window. - * @work: work structure. - * - * The routine shall not be called within an atomic context because it - * might sleep. - * - * Locking: hp->lock - */ -static void hvc_set_winsz(struct work_struct *work) -{ - struct hvc_struct *hp; - unsigned long hvc_flags; - struct tty_struct *tty; - struct winsize ws; - - hp = container_of(work, struct hvc_struct, tty_resize); - if (!hp) - return; - - spin_lock_irqsave(&hp->lock, hvc_flags); - if (!hp->tty) { - spin_unlock_irqrestore(&hp->lock, hvc_flags); - return; - } - ws = hp->ws; - tty = tty_kref_get(hp->tty); - spin_unlock_irqrestore(&hp->lock, hvc_flags); - - tty_do_resize(tty, tty, &ws); - tty_kref_put(tty); -} - /* * This is actually a contract between the driver and the tty layer outlining * how much write room the driver can guarantee will be sent OR BUFFERED. This @@ -579,20 +538,16 @@ int hvc_poll(struct hvc_struct *hp) char buf[N_INBUF] __ALIGNED__; unsigned long flags; int read_total = 0; - int written_total = 0; spin_lock_irqsave(&hp->lock, flags); /* Push pending writes */ if (hp->n_outbuf > 0) - written_total = hvc_push(hp); + hvc_push(hp); /* Reschedule us if still some write pending */ - if (hp->n_outbuf > 0) { + if (hp->n_outbuf > 0) poll_mask |= HVC_POLL_WRITE; - /* If hvc_push() was not able to write, sleep a few msecs */ - timeout = (written_total) ? 0 : MIN_TIMEOUT; - } /* No tty attached, just skip */ tty = hp->tty; @@ -677,24 +632,6 @@ int hvc_poll(struct hvc_struct *hp) } EXPORT_SYMBOL_GPL(hvc_poll); -/** - * hvc_resize() - Update terminal window size information. - * @hp: HVC console pointer - * @ws: Terminal window size structure - * - * Stores the specified window size information in the hvc structure of @hp. - * The function schedule the tty resize update. - * - * Locking: Locking free; the function MUST be called holding hp->lock - */ -void hvc_resize(struct hvc_struct *hp, struct winsize ws) -{ - if ((hp->ws.ws_row != ws.ws_row) || (hp->ws.ws_col != ws.ws_col)) { - hp->ws = ws; - schedule_work(&hp->tty_resize); - } -} - /* * This kthread is either polling or interrupt driven. This is determined by * calling hvc_poll() who determines whether a console adapter support @@ -722,6 +659,10 @@ static int khvcd(void *unused) poll_mask |= HVC_POLL_READ; if (hvc_kicked) continue; + if (poll_mask & HVC_POLL_WRITE) { + yield(); + continue; + } set_current_state(TASK_INTERRUPTIBLE); if (!hvc_kicked) { if (poll_mask == 0) @@ -777,7 +718,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, kref_init(&hp->kref); - INIT_WORK(&hp->tty_resize, hvc_set_winsz); spin_lock_init(&hp->lock); spin_lock(&hvc_structs_lock); @@ -803,7 +743,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, } EXPORT_SYMBOL_GPL(hvc_alloc); -int hvc_remove(struct hvc_struct *hp) +int __devexit hvc_remove(struct hvc_struct *hp) { unsigned long flags; struct tty_struct *tty; @@ -856,7 +796,7 @@ static int hvc_init(void) drv->minor_start = HVC_MINOR; drv->type = TTY_DRIVER_TYPE_SYSTEM; drv->init_termios = tty_std_termios; - drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; + drv->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(drv, &hvc_ops); /* Always start the kthread because there can be hotplug vty adapters diff --git a/trunk/drivers/char/hvc_console.h b/trunk/drivers/char/hvc_console.h index 8297dbc2e6ec..9790201718ae 100644 --- a/trunk/drivers/char/hvc_console.h +++ b/trunk/drivers/char/hvc_console.h @@ -27,7 +27,6 @@ #ifndef HVC_CONSOLE_H #define HVC_CONSOLE_H #include -#include /* * This is the max number of console adapters that can/will be found as @@ -57,8 +56,6 @@ struct hvc_struct { struct hv_ops *ops; int irq_requested; int data; - struct winsize ws; - struct work_struct tty_resize; struct list_head next; struct kref kref; /* ref count & hvc_struct lifetime */ }; @@ -68,10 +65,9 @@ struct hv_ops { int (*get_chars)(uint32_t vtermno, char *buf, int count); int (*put_chars)(uint32_t vtermno, const char *buf, int count); - /* Callbacks for notification. Called in open, close and hangup */ + /* Callbacks for notification. Called in open and close */ int (*notifier_add)(struct hvc_struct *hp, int irq); void (*notifier_del)(struct hvc_struct *hp, int irq); - void (*notifier_hangup)(struct hvc_struct *hp, int irq); }; /* Register a vterm and a slot index for use as a console (console_init) */ @@ -81,19 +77,15 @@ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, struct hv_ops *ops, int outbuf_size); /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ -extern int hvc_remove(struct hvc_struct *hp); +extern int __devexit hvc_remove(struct hvc_struct *hp); /* data available */ int hvc_poll(struct hvc_struct *hp); void hvc_kick(void); -/* Resize hvc tty terminal window */ -extern void hvc_resize(struct hvc_struct *hp, struct winsize ws); - /* default notifier for irq based notification */ extern int notifier_add_irq(struct hvc_struct *hp, int data); extern void notifier_del_irq(struct hvc_struct *hp, int data); -extern void notifier_hangup_irq(struct hvc_struct *hp, int data); #if defined(CONFIG_XMON) && defined(CONFIG_SMP) diff --git a/trunk/drivers/char/hvc_irq.c b/trunk/drivers/char/hvc_irq.c index d09e5688d449..73a59cdb8947 100644 --- a/trunk/drivers/char/hvc_irq.c +++ b/trunk/drivers/char/hvc_irq.c @@ -42,8 +42,3 @@ void notifier_del_irq(struct hvc_struct *hp, int irq) free_irq(irq, hp); hp->irq_requested = 0; } - -void notifier_hangup_irq(struct hvc_struct *hp, int irq) -{ - notifier_del_irq(hp, irq); -} diff --git a/trunk/drivers/char/hvc_iseries.c b/trunk/drivers/char/hvc_iseries.c index b74a2f8ab908..b71c610fe5ae 100644 --- a/trunk/drivers/char/hvc_iseries.c +++ b/trunk/drivers/char/hvc_iseries.c @@ -202,7 +202,6 @@ static struct hv_ops hvc_get_put_ops = { .put_chars = put_chars, .notifier_add = notifier_add_irq, .notifier_del = notifier_del_irq, - .notifier_hangup = notifier_hangup_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/trunk/drivers/char/hvc_vio.c b/trunk/drivers/char/hvc_vio.c index 019e0b58593d..93f3840c1682 100644 --- a/trunk/drivers/char/hvc_vio.c +++ b/trunk/drivers/char/hvc_vio.c @@ -82,7 +82,6 @@ static struct hv_ops hvc_get_put_ops = { .put_chars = hvc_put_chars, .notifier_add = notifier_add_irq, .notifier_del = notifier_del_irq, - .notifier_hangup = notifier_hangup_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/trunk/drivers/char/hvc_xen.c b/trunk/drivers/char/hvc_xen.c index eba999f8598d..538ceea5e7df 100644 --- a/trunk/drivers/char/hvc_xen.c +++ b/trunk/drivers/char/hvc_xen.c @@ -102,7 +102,6 @@ static struct hv_ops hvc_ops = { .put_chars = write_console, .notifier_add = notifier_add_irq, .notifier_del = notifier_del_irq, - .notifier_hangup = notifier_hangup_irq, }; static int __init xen_init(void) diff --git a/trunk/drivers/char/tty_port.c b/trunk/drivers/char/tty_port.c index c8f8024cb40e..553b0e9d8d17 100644 --- a/trunk/drivers/char/tty_port.c +++ b/trunk/drivers/char/tty_port.c @@ -90,7 +90,7 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); if (port->tty) tty_kref_put(port->tty); - port->tty = tty_kref_get(tty); + port->tty = tty; spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL(tty_port_tty_set); diff --git a/trunk/drivers/char/virtio_console.c b/trunk/drivers/char/virtio_console.c index 3fb0d2c88ba5..d0f4eb6fdb7f 100644 --- a/trunk/drivers/char/virtio_console.c +++ b/trunk/drivers/char/virtio_console.c @@ -198,7 +198,6 @@ static int __devinit virtcons_probe(struct virtio_device *dev) virtio_cons.put_chars = put_chars; virtio_cons.notifier_add = notifier_add_vio; virtio_cons.notifier_del = notifier_del_vio; - virtio_cons.notifier_hangup = notifier_del_vio; /* The first argument of hvc_alloc() is the virtual console number, so * we use zero. The second argument is the parameter for the diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index 7f2ee27fe76b..dbd42d6c93a7 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -127,13 +127,6 @@ config GPIO_PCF857X This driver provides an in-kernel interface to those GPIOs using platform-neutral GPIO calls. -config GPIO_TWL4030 - tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" - depends on TWL4030_CORE - help - Say yes here to access the GPIO signals of various multi-function - power management chips from Texas Instruments. - comment "PCI GPIO expanders:" config GPIO_BT8XX diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile index 6aafdeb9ad03..01b4bbde1956 100644 --- a/trunk/drivers/gpio/Makefile +++ b/trunk/drivers/gpio/Makefile @@ -9,5 +9,4 @@ obj-$(CONFIG_GPIO_MAX732X) += max732x.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o -obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o diff --git a/trunk/drivers/gpio/twl4030-gpio.c b/trunk/drivers/gpio/twl4030-gpio.c deleted file mode 100644 index 37d3eec8730a..000000000000 --- a/trunk/drivers/gpio/twl4030-gpio.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips - * - * Copyright (C) 2006-2007 Texas Instruments, Inc. - * Copyright (C) 2006 MontaVista Software, Inc. - * - * Code re-arranged and cleaned up by: - * Syed Mohammed Khasim - * - * Initial Code: - * Andy Lowe / Nishanth Menon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -/* - * The GPIO "subchip" supports 18 GPIOs which can be configured as - * inputs or outputs, with pullups or pulldowns on each pin. Each - * GPIO can trigger interrupts on either or both edges. - * - * GPIO interrupts can be fed to either of two IRQ lines; this is - * intended to support multiple hosts. - * - * There are also two LED pins used sometimes as output-only GPIOs. - */ - - -static struct gpio_chip twl_gpiochip; -static int twl4030_gpio_irq_base; - -/* genirq interfaces are not available to modules */ -#ifdef MODULE -#define is_module() true -#else -#define is_module() false -#endif - -/* GPIO_CTRL Fields */ -#define MASK_GPIO_CTRL_GPIO0CD1 BIT(0) -#define MASK_GPIO_CTRL_GPIO1CD2 BIT(1) -#define MASK_GPIO_CTRL_GPIO_ON BIT(2) - -/* Mask for GPIO registers when aggregated into a 32-bit integer */ -#define GPIO_32_MASK 0x0003ffff - -/* Data structures */ -static DEFINE_MUTEX(gpio_lock); - -/* store usage of each GPIO. - each bit represents one GPIO */ -static unsigned int gpio_usage_count; - -/*----------------------------------------------------------------------*/ - -/* - * To configure TWL4030 GPIO module registers - */ -static inline int gpio_twl4030_write(u8 address, u8 data) -{ - return twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); -} - -/*----------------------------------------------------------------------*/ - -/* - * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB})) - * PWMs A and B are dedicated to LEDs A and B, respectively. - */ - -#define TWL4030_LED_LEDEN 0x0 - -/* LEDEN bits */ -#define LEDEN_LEDAON BIT(0) -#define LEDEN_LEDBON BIT(1) -#define LEDEN_LEDAEXT BIT(2) -#define LEDEN_LEDBEXT BIT(3) -#define LEDEN_LEDAPWM BIT(4) -#define LEDEN_LEDBPWM BIT(5) -#define LEDEN_PWM_LENGTHA BIT(6) -#define LEDEN_PWM_LENGTHB BIT(7) - -#define TWL4030_PWMx_PWMxON 0x0 -#define TWL4030_PWMx_PWMxOFF 0x1 - -#define PWMxON_LENGTH BIT(7) - -/*----------------------------------------------------------------------*/ - -/* - * To read a TWL4030 GPIO module register - */ -static inline int gpio_twl4030_read(u8 address) -{ - u8 data; - int ret = 0; - - ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); - return (ret < 0) ? ret : data; -} - -/*----------------------------------------------------------------------*/ - -static u8 cached_leden; /* protected by gpio_lock */ - -/* The LED lines are open drain outputs ... a FET pulls to GND, so an - * external pullup is needed. We could also expose the integrated PWM - * as a LED brightness control; we initialize it as "always on". - */ -static void twl4030_led_set_value(int led, int value) -{ - u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM; - int status; - - if (led) - mask <<= 1; - - mutex_lock(&gpio_lock); - if (value) - cached_leden &= ~mask; - else - cached_leden |= mask; - status = twl4030_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, - TWL4030_LED_LEDEN); - mutex_unlock(&gpio_lock); -} - -static int twl4030_set_gpio_direction(int gpio, int is_input) -{ - u8 d_bnk = gpio >> 3; - u8 d_msk = BIT(gpio & 0x7); - u8 reg = 0; - u8 base = REG_GPIODATADIR1 + d_bnk; - int ret = 0; - - mutex_lock(&gpio_lock); - ret = gpio_twl4030_read(base); - if (ret >= 0) { - if (is_input) - reg = ret & ~d_msk; - else - reg = ret | d_msk; - - ret = gpio_twl4030_write(base, reg); - } - mutex_unlock(&gpio_lock); - return ret; -} - -static int twl4030_set_gpio_dataout(int gpio, int enable) -{ - u8 d_bnk = gpio >> 3; - u8 d_msk = BIT(gpio & 0x7); - u8 base = 0; - - if (enable) - base = REG_SETGPIODATAOUT1 + d_bnk; - else - base = REG_CLEARGPIODATAOUT1 + d_bnk; - - return gpio_twl4030_write(base, d_msk); -} - -static int twl4030_get_gpio_datain(int gpio) -{ - u8 d_bnk = gpio >> 3; - u8 d_off = gpio & 0x7; - u8 base = 0; - int ret = 0; - - if (unlikely((gpio >= TWL4030_GPIO_MAX) - || !(gpio_usage_count & BIT(gpio)))) - return -EPERM; - - base = REG_GPIODATAIN1 + d_bnk; - ret = gpio_twl4030_read(base); - if (ret > 0) - ret = (ret >> d_off) & 0x1; - - return ret; -} - -/* - * Configure debounce timing value for a GPIO pin on TWL4030 - */ -int twl4030_set_gpio_debounce(int gpio, int enable) -{ - u8 d_bnk = gpio >> 3; - u8 d_msk = BIT(gpio & 0x7); - u8 reg = 0; - u8 base = 0; - int ret = 0; - - if (unlikely((gpio >= TWL4030_GPIO_MAX) - || !(gpio_usage_count & BIT(gpio)))) - return -EPERM; - - base = REG_GPIO_DEBEN1 + d_bnk; - mutex_lock(&gpio_lock); - ret = gpio_twl4030_read(base); - if (ret >= 0) { - if (enable) - reg = ret | d_msk; - else - reg = ret & ~d_msk; - - ret = gpio_twl4030_write(base, reg); - } - mutex_unlock(&gpio_lock); - return ret; -} -EXPORT_SYMBOL(twl4030_set_gpio_debounce); - -/*----------------------------------------------------------------------*/ - -static int twl_request(struct gpio_chip *chip, unsigned offset) -{ - int status = 0; - - mutex_lock(&gpio_lock); - - /* Support the two LED outputs as output-only GPIOs. */ - if (offset >= TWL4030_GPIO_MAX) { - u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT - | LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA; - u8 module = TWL4030_MODULE_PWMA; - - offset -= TWL4030_GPIO_MAX; - if (offset) { - ledclr_mask <<= 1; - module = TWL4030_MODULE_PWMB; - } - - /* initialize PWM to always-drive */ - status = twl4030_i2c_write_u8(module, 0x7f, - TWL4030_PWMx_PWMxOFF); - if (status < 0) - goto done; - status = twl4030_i2c_write_u8(module, 0x7f, - TWL4030_PWMx_PWMxON); - if (status < 0) - goto done; - - /* init LED to not-driven (high) */ - module = TWL4030_MODULE_LED; - status = twl4030_i2c_read_u8(module, &cached_leden, - TWL4030_LED_LEDEN); - if (status < 0) - goto done; - cached_leden &= ~ledclr_mask; - status = twl4030_i2c_write_u8(module, cached_leden, - TWL4030_LED_LEDEN); - if (status < 0) - goto done; - - status = 0; - goto done; - } - - /* on first use, turn GPIO module "on" */ - if (!gpio_usage_count) { - struct twl4030_gpio_platform_data *pdata; - u8 value = MASK_GPIO_CTRL_GPIO_ON; - - /* optionally have the first two GPIOs switch vMMC1 - * and vMMC2 power supplies based on card presence. - */ - pdata = chip->dev->platform_data; - value |= pdata->mmc_cd & 0x03; - - status = gpio_twl4030_write(REG_GPIO_CTRL, value); - } - - if (!status) - gpio_usage_count |= (0x1 << offset); - -done: - mutex_unlock(&gpio_lock); - return status; -} - -static void twl_free(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= TWL4030_GPIO_MAX) { - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); - return; - } - - mutex_lock(&gpio_lock); - - gpio_usage_count &= ~BIT(offset); - - /* on last use, switch off GPIO module */ - if (!gpio_usage_count) - gpio_twl4030_write(REG_GPIO_CTRL, 0x0); - - mutex_unlock(&gpio_lock); -} - -static int twl_direction_in(struct gpio_chip *chip, unsigned offset) -{ - return (offset < TWL4030_GPIO_MAX) - ? twl4030_set_gpio_direction(offset, 1) - : -EINVAL; -} - -static int twl_get(struct gpio_chip *chip, unsigned offset) -{ - int status = 0; - - if (offset < TWL4030_GPIO_MAX) - status = twl4030_get_gpio_datain(offset); - else if (offset == TWL4030_GPIO_MAX) - status = cached_leden & LEDEN_LEDAON; - else - status = cached_leden & LEDEN_LEDBON; - return (status < 0) ? 0 : status; -} - -static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) -{ - if (offset < TWL4030_GPIO_MAX) { - twl4030_set_gpio_dataout(offset, value); - return twl4030_set_gpio_direction(offset, 0); - } else { - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); - return 0; - } -} - -static void twl_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (offset < TWL4030_GPIO_MAX) - twl4030_set_gpio_dataout(offset, value); - else - twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); -} - -static int twl_to_irq(struct gpio_chip *chip, unsigned offset) -{ - return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX)) - ? (twl4030_gpio_irq_base + offset) - : -EINVAL; -} - -static struct gpio_chip twl_gpiochip = { - .label = "twl4030", - .owner = THIS_MODULE, - .request = twl_request, - .free = twl_free, - .direction_input = twl_direction_in, - .get = twl_get, - .direction_output = twl_direction_out, - .set = twl_set, - .to_irq = twl_to_irq, - .can_sleep = 1, -}; - -/*----------------------------------------------------------------------*/ - -static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs) -{ - u8 message[6]; - unsigned i, gpio_bit; - - /* For most pins, a pulldown was enabled by default. - * We should have data that's specific to this board. - */ - for (gpio_bit = 1, i = 1; i < 6; i++) { - u8 bit_mask; - unsigned j; - - for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) { - if (ups & gpio_bit) - bit_mask |= 1 << (j + 1); - else if (downs & gpio_bit) - bit_mask |= 1 << (j + 0); - } - message[i] = bit_mask; - } - - return twl4030_i2c_write(TWL4030_MODULE_GPIO, message, - REG_GPIOPUPDCTR1, 5); -} - -static int gpio_twl4030_remove(struct platform_device *pdev); - -static int __devinit gpio_twl4030_probe(struct platform_device *pdev) -{ - struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; - int ret; - - /* maybe setup IRQs */ - if (pdata->irq_base) { - if (is_module()) { - dev_err(&pdev->dev, - "can't dispatch IRQs from modules\n"); - goto no_irqs; - } - ret = twl4030_sih_setup(TWL4030_MODULE_GPIO); - if (ret < 0) - return ret; - WARN_ON(ret != pdata->irq_base); - twl4030_gpio_irq_base = ret; - } - -no_irqs: - /* - * NOTE: boards may waste power if they don't set pullups - * and pulldowns correctly ... default for non-ULPI pins is - * pulldown, and some other pins may have external pullups - * or pulldowns. Careful! - */ - ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); - if (ret) - dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", - pdata->pullups, pdata->pulldowns, - ret); - - twl_gpiochip.base = pdata->gpio_base; - twl_gpiochip.ngpio = TWL4030_GPIO_MAX; - twl_gpiochip.dev = &pdev->dev; - - /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE, - * is (still) clear if use_leds is set. - */ - if (pdata->use_leds) - twl_gpiochip.ngpio += 2; - - ret = gpiochip_add(&twl_gpiochip); - if (ret < 0) { - dev_err(&pdev->dev, - "could not register gpiochip, %d\n", - ret); - twl_gpiochip.ngpio = 0; - gpio_twl4030_remove(pdev); - } else if (pdata->setup) { - int status; - - status = pdata->setup(&pdev->dev, - pdata->gpio_base, TWL4030_GPIO_MAX); - if (status) - dev_dbg(&pdev->dev, "setup --> %d\n", status); - } - - return ret; -} - -static int __devexit gpio_twl4030_remove(struct platform_device *pdev) -{ - struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; - int status; - - if (pdata->teardown) { - status = pdata->teardown(&pdev->dev, - pdata->gpio_base, TWL4030_GPIO_MAX); - if (status) { - dev_dbg(&pdev->dev, "teardown --> %d\n", status); - return status; - } - } - - status = gpiochip_remove(&twl_gpiochip); - if (status < 0) - return status; - - if (is_module()) - return 0; - - /* REVISIT no support yet for deregistering all the IRQs */ - WARN_ON(1); - return -EIO; -} - -/* Note: this hardware lives inside an I2C-based multi-function device. */ -MODULE_ALIAS("platform:twl4030_gpio"); - -static struct platform_driver gpio_twl4030_driver = { - .driver.name = "twl4030_gpio", - .driver.owner = THIS_MODULE, - .probe = gpio_twl4030_probe, - .remove = __devexit_p(gpio_twl4030_remove), -}; - -static int __init gpio_twl4030_init(void) -{ - return platform_driver_register(&gpio_twl4030_driver); -} -subsys_initcall(gpio_twl4030_init); - -static void __exit gpio_twl4030_exit(void) -{ - platform_driver_unregister(&gpio_twl4030_driver); -} -module_exit(gpio_twl4030_exit); - -MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("GPIO interface for TWL4030"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/Kconfig b/trunk/drivers/gpu/drm/Kconfig index a8b33c2ec8d2..9097500de5f4 100644 --- a/trunk/drivers/gpu/drm/Kconfig +++ b/trunk/drivers/gpu/drm/Kconfig @@ -6,7 +6,7 @@ # menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" - depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU + depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && SHMEM help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index dc2e6fdb6ca3..49c5a1798ac4 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -182,8 +182,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, * happens to let us map card memory without taking IPIs. When the vmap * rework lands we should be able to dump this hack. */ -static inline int fast_user_write(unsigned long pfn, char __user *user_data, - int l, int o) +static inline int fast_user_write(unsigned long pfn, char __user *user_data, int l) { #ifdef CONFIG_HIGHMEM unsigned long unwritten; @@ -252,7 +251,7 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, pfn = (dev->agp->base >> PAGE_SHIFT) + i; - if (!fast_user_write(pfn, user_data, l, o)) { + if (!fast_user_write(pfn, user_data, l)) { unsigned long unwritten; char __iomem *vaddr; diff --git a/trunk/drivers/i2c/busses/i2c-cpm.c b/trunk/drivers/i2c/busses/i2c-cpm.c index 228f75723063..8164de1f4d72 100644 --- a/trunk/drivers/i2c/busses/i2c-cpm.c +++ b/trunk/drivers/i2c/busses/i2c-cpm.c @@ -423,6 +423,7 @@ static const struct i2c_adapter cpm_ops = { .owner = THIS_MODULE, .name = "i2c-cpm", .algo = &cpm_i2c_algo, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, }; static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index 5c54fc2350be..49c45feccd5b 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -406,15 +406,19 @@ static int register_snoop_agent(struct ib_mad_qp_info *qp_info, if (i == qp_info->snoop_table_size) { /* Grow table. */ - new_snoop_table = krealloc(qp_info->snoop_table, - sizeof mad_snoop_priv * - (qp_info->snoop_table_size + 1), - GFP_ATOMIC); + new_snoop_table = kmalloc(sizeof mad_snoop_priv * + qp_info->snoop_table_size + 1, + GFP_ATOMIC); if (!new_snoop_table) { i = -ENOMEM; goto out; } - + if (qp_info->snoop_table) { + memcpy(new_snoop_table, qp_info->snoop_table, + sizeof mad_snoop_priv * + qp_info->snoop_table_size); + kfree(qp_info->snoop_table); + } qp_info->snoop_table = new_snoop_table; qp_info->snoop_table_size++; } diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c index 4346a24568fb..3ddacf39b7ba 100644 --- a/trunk/drivers/infiniband/core/ucma.c +++ b/trunk/drivers/infiniband/core/ucma.c @@ -904,8 +904,8 @@ static ssize_t ucma_join_multicast(struct ucma_file *file, mutex_lock(&file->mut); mc = ucma_alloc_multicast(ctx); - if (!mc) { - ret = -ENOMEM; + if (IS_ERR(mc)) { + ret = PTR_ERR(mc); goto err1; } diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c index 44e936e48a31..c325c44807e8 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1942,7 +1942,6 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) fail3: cxgb3_free_atid(ep->com.tdev, ep->atid); fail2: - cm_id->rem_ref(cm_id); put_ep(&ep->com); out: return err; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index 4df887af66a5..5d7b7855afb9 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -128,8 +128,6 @@ struct ehca_shca { /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */ u32 hca_cap_mr_pgsize; int max_mtu; - int max_num_qps; - int max_num_cqs; atomic_t num_cqs; atomic_t num_qps; }; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c index 2f4c28a30271..33647a95eb9a 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c @@ -132,9 +132,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) return ERR_PTR(-EINVAL); - if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) { + if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) { ehca_err(device, "Unable to create CQ, max number of %i " - "CQs reached.", shca->max_num_cqs); + "CQs reached.", ehca_max_cq); ehca_err(device, "To increase the maximum number of CQs " "use the number_of_cqs module parameter.\n"); return ERR_PTR(-ENOSPC); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index bb02a86aa526..598844d2edc9 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -44,8 +44,6 @@ #include #endif -#include -#include #include "ehca_classes.h" #include "ehca_iverbs.h" #include "ehca_mrmw.h" @@ -368,23 +366,22 @@ static int ehca_sense_attributes(struct ehca_shca *shca) shca->hca_cap_mr_pgsize |= pgsize_map[i + 1]; /* Set maximum number of CQs and QPs to calculate EQ size */ - if (shca->max_num_qps == -1) - shca->max_num_qps = min_t(int, rblock->max_qp, - EHCA_MAX_NUM_QUEUES); - else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) { - ehca_gen_warn("The requested number of QPs is out of range " - "(1 - %i) specified by HW. Value is set to %i", - rblock->max_qp, rblock->max_qp); - shca->max_num_qps = rblock->max_qp; + if (ehca_max_qp == -1) + ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES); + else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) { + ehca_gen_err("Requested number of QPs is out of range (1 - %i) " + "specified by HW", rblock->max_qp); + ret = -EINVAL; + goto sense_attributes1; } - if (shca->max_num_cqs == -1) - shca->max_num_cqs = min_t(int, rblock->max_cq, - EHCA_MAX_NUM_QUEUES); - else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) { - ehca_gen_warn("The requested number of CQs is out of range " - "(1 - %i) specified by HW. Value is set to %i", - rblock->max_cq, rblock->max_cq); + if (ehca_max_cq == -1) + ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES); + else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) { + ehca_gen_err("Requested number of CQs is out of range (1 - %i) " + "specified by HW", rblock->max_cq); + ret = -EINVAL; + goto sense_attributes1; } /* query max MTU from first port -- it's the same for all ports */ @@ -736,13 +733,9 @@ static int __devinit ehca_probe(struct of_device *dev, ehca_gen_err("Cannot allocate shca memory."); return -ENOMEM; } - mutex_init(&shca->modify_mutex); atomic_set(&shca->num_cqs, 0); atomic_set(&shca->num_qps, 0); - shca->max_num_qps = ehca_max_qp; - shca->max_num_cqs = ehca_max_cq; - for (i = 0; i < ARRAY_SIZE(shca->sport); i++) spin_lock_init(&shca->sport[i].mod_sqp_lock); @@ -762,7 +755,7 @@ static int __devinit ehca_probe(struct of_device *dev, goto probe1; } - eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps; + eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp; /* create event queues */ ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size); if (ret) { @@ -971,41 +964,6 @@ void ehca_poll_eqs(unsigned long data) spin_unlock(&shca_list_lock); } -static int ehca_mem_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - static unsigned long ehca_dmem_warn_time; - - switch (action) { - case MEM_CANCEL_OFFLINE: - case MEM_CANCEL_ONLINE: - case MEM_ONLINE: - case MEM_OFFLINE: - return NOTIFY_OK; - case MEM_GOING_ONLINE: - case MEM_GOING_OFFLINE: - /* only ok if no hca is attached to the lpar */ - spin_lock(&shca_list_lock); - if (list_empty(&shca_list)) { - spin_unlock(&shca_list_lock); - return NOTIFY_OK; - } else { - spin_unlock(&shca_list_lock); - if (printk_timed_ratelimit(&ehca_dmem_warn_time, - 30 * 1000)) - ehca_gen_err("DMEM operations are not allowed" - "as long as an ehca adapter is" - "attached to the LPAR"); - return NOTIFY_BAD; - } - } - return NOTIFY_OK; -} - -static struct notifier_block ehca_mem_nb = { - .notifier_call = ehca_mem_notifier, -}; - static int __init ehca_module_init(void) { int ret; @@ -1033,12 +991,6 @@ static int __init ehca_module_init(void) goto module_init2; } - ret = register_memory_notifier(&ehca_mem_nb); - if (ret) { - ehca_gen_err("Failed registering memory add/remove notifier"); - goto module_init3; - } - if (ehca_poll_all_eqs != 1) { ehca_gen_err("WARNING!!!"); ehca_gen_err("It is possible to lose interrupts."); @@ -1051,9 +1003,6 @@ static int __init ehca_module_init(void) return 0; -module_init3: - ibmebus_unregister_driver(&ehca_driver); - module_init2: ehca_destroy_slab_caches(); @@ -1069,8 +1018,6 @@ static void __exit ehca_module_exit(void) ibmebus_unregister_driver(&ehca_driver); - unregister_memory_notifier(&ehca_mem_nb); - ehca_destroy_slab_caches(); ehca_destroy_comp_pool(); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c index 4d54b9f64567..4dbe2870e014 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c @@ -465,9 +465,9 @@ static struct ehca_qp *internal_create_qp( u32 swqe_size = 0, rwqe_size = 0, ib_qp_num; unsigned long flags; - if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) { + if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) { ehca_err(pd->device, "Unable to create QP, max number of %i " - "QPs reached.", shca->max_num_qps); + "QPs reached.", ehca_max_qp); ehca_err(pd->device, "To increase the maximum number of QPs " "use the number_of_qps module parameter.\n"); return ERR_PTR(-ENOSPC); @@ -502,12 +502,6 @@ static struct ehca_qp *internal_create_qp( if (init_attr->srq) { my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq); - if (qp_type == IB_QPT_UC) { - ehca_err(pd->device, "UC with SRQ not supported"); - atomic_dec(&shca->num_qps); - return ERR_PTR(-EINVAL); - } - has_srq = 1; parms.ext_type = EQPT_SRQBASE; parms.srq_qpn = my_srq->real_qp_num; diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c index 606f1e2ef284..cdca3a511e1c 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ b/trunk/drivers/infiniband/hw/mlx4/mad.c @@ -298,7 +298,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev) int p, q; int ret; - for (p = 0; p < dev->num_ports; ++p) + for (p = 0; p < dev->dev->caps.num_ports; ++p) for (q = 0; q <= 1; ++q) { agent = ib_register_mad_agent(&dev->ib_dev, p + 1, q ? IB_QPT_GSI : IB_QPT_SMI, @@ -314,7 +314,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev) return 0; err: - for (p = 0; p < dev->num_ports; ++p) + for (p = 0; p < dev->dev->caps.num_ports; ++p) for (q = 0; q <= 1; ++q) if (dev->send_agent[p][q]) ib_unregister_mad_agent(dev->send_agent[p][q]); @@ -327,7 +327,7 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev) struct ib_mad_agent *agent; int p, q; - for (p = 0; p < dev->num_ports; ++p) { + for (p = 0; p < dev->dev->caps.num_ports; ++p) { for (q = 0; q <= 1; ++q) { agent = dev->send_agent[p][q]; dev->send_agent[p][q] = NULL; diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index 2e80f8f47b02..a3c2851c0545 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -574,10 +574,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ibdev->ib_dev.owner = THIS_MODULE; ibdev->ib_dev.node_type = RDMA_NODE_IB_CA; ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey; - ibdev->num_ports = 0; - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) - ibdev->num_ports++; - ibdev->ib_dev.phys_port_cnt = ibdev->num_ports; + ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports; ibdev->ib_dev.num_comp_vectors = 1; ibdev->ib_dev.dma_device = &dev->pdev->dev; @@ -694,7 +691,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) struct mlx4_ib_dev *ibdev = ibdev_ptr; int p; - for (p = 1; p <= ibdev->num_ports; ++p) + for (p = 1; p <= dev->caps.num_ports; ++p) mlx4_CLOSE_PORT(dev, p); mlx4_ib_mad_cleanup(ibdev); @@ -709,10 +706,6 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, enum mlx4_dev_event event, int port) { struct ib_event ibev; - struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr); - - if (port > ibdev->num_ports) - return; switch (event) { case MLX4_DEV_EVENT_PORT_UP: diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h index 9974e886b8de..6e2b0dc21b61 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -162,7 +162,6 @@ struct mlx4_ib_ah { struct mlx4_ib_dev { struct ib_device ib_dev; struct mlx4_dev *dev; - int num_ports; void __iomem *uar_map; struct mlx4_uar priv_uar; diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index 39167a797f99..baa01deb2436 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -451,7 +451,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, struct ib_qp_init_attr *init_attr, struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp) { - int qpn; int err; mutex_init(&qp->mutex); @@ -546,17 +545,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, } } - if (sqpn) { - qpn = sqpn; - } else { - err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn); - if (err) - goto err_wrid; - } - - err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp); + err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp); if (err) - goto err_qpn; + goto err_wrid; /* * Hardware wants QPN written in big-endian order (after @@ -569,10 +560,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, return 0; -err_qpn: - if (!sqpn) - mlx4_qp_release_range(dev->dev, qpn, 1); - err_wrid: if (pd->uobject) { if (!init_attr->srq) @@ -668,10 +655,6 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, mlx4_ib_unlock_cqs(send_cq, recv_cq); mlx4_qp_free(dev->dev, &qp->mqp); - - if (!is_sqp(dev, qp)) - mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1); - mlx4_mtt_cleanup(dev->dev, &qp->mtt); if (is_user) { diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index e0c7dfabf2b4..68ba5c3482e4 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -507,7 +507,6 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev); void ipoib_drain_cq(struct net_device *dev); void ipoib_set_ethtool_ops(struct net_device *dev); -int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca); #ifdef CONFIG_INFINIBAND_IPOIB_CM diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c index e9795f60e5d6..66af5c1a76e5 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c @@ -42,13 +42,6 @@ static void ipoib_get_drvinfo(struct net_device *netdev, strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); } -static u32 ipoib_get_rx_csum(struct net_device *dev) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - return test_bit(IPOIB_FLAG_CSUM, &priv->flags) && - !test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); -} - static int ipoib_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) { @@ -136,7 +129,7 @@ static void ipoib_get_ethtool_stats(struct net_device *dev, static const struct ethtool_ops ipoib_ethtool_ops = { .get_drvinfo = ipoib_get_drvinfo, - .get_rx_csum = ipoib_get_rx_csum, + .get_tso = ethtool_op_get_tso, .get_coalesce = ipoib_get_coalesce, .set_coalesce = ipoib_set_coalesce, .get_flags = ethtool_op_get_flags, diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 28eb6f03c588..0e748aeeae99 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -685,6 +685,10 @@ int ipoib_ib_dev_open(struct net_device *dev) queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, round_jiffies_relative(HZ)); + init_timer(&priv->poll_timer); + priv->poll_timer.function = ipoib_ib_tx_timer_func; + priv->poll_timer.data = (unsigned long)dev; + set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); return 0; @@ -902,9 +906,6 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return -ENODEV; } - setup_timer(&priv->poll_timer, ipoib_ib_tx_timer_func, - (unsigned long) dev); - if (dev->flags & IFF_UP) { if (ipoib_ib_dev_open(dev)) { ipoib_transport_dev_cleanup(dev); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index fddded7900d1..c0ee514396df 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1173,48 +1173,11 @@ int ipoib_add_pkey_attr(struct net_device *dev) return device_create_file(&dev->dev, &dev_attr_pkey); } -int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) -{ - struct ib_device_attr *device_attr; - int result = -ENOMEM; - - device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); - if (!device_attr) { - printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", - hca->name, sizeof *device_attr); - return result; - } - - result = ib_query_device(hca, device_attr); - if (result) { - printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", - hca->name, result); - kfree(device_attr); - return result; - } - priv->hca_caps = device_attr->device_cap_flags; - - kfree(device_attr); - - if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { - set_bit(IPOIB_FLAG_CSUM, &priv->flags); - priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } - - if (lro) - priv->dev->features |= NETIF_F_LRO; - - if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) - priv->dev->features |= NETIF_F_TSO; - - return 0; -} - - static struct net_device *ipoib_add_port(const char *format, struct ib_device *hca, u8 port) { struct ipoib_dev_priv *priv; + struct ib_device_attr *device_attr; struct ib_port_attr attr; int result = -ENOMEM; @@ -1243,8 +1206,31 @@ static struct net_device *ipoib_add_port(const char *format, goto device_init_failed; } - if (ipoib_set_dev_features(priv, hca)) + device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); + if (!device_attr) { + printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", + hca->name, sizeof *device_attr); goto device_init_failed; + } + + result = ib_query_device(hca, device_attr); + if (result) { + printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", + hca->name, result); + kfree(device_attr); + goto device_init_failed; + } + priv->hca_caps = device_attr->device_cap_flags; + + kfree(device_attr); + + if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { + set_bit(IPOIB_FLAG_CSUM, &priv->flags); + priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } + + if (lro) + priv->dev->features |= NETIF_F_LRO; /* * Set the full membership bit, so that we join the right @@ -1280,6 +1266,9 @@ static struct net_device *ipoib_add_port(const char *format, goto event_failed; } + if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) + priv->dev->features |= NETIF_F_TSO; + result = register_netdev(priv->dev); if (result) { printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n", diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 2cf1a4088718..b08eb56196d3 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -93,10 +93,6 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu; set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags); - result = ipoib_set_dev_features(priv, ppriv->ca); - if (result) - goto device_init_failed; - priv->pkey = pkey; memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN); diff --git a/trunk/drivers/mfd/Makefile b/trunk/drivers/mfd/Makefile index 0acefe8aff87..68e237b830ad 100644 --- a/trunk/drivers/mfd/Makefile +++ b/trunk/drivers/mfd/Makefile @@ -17,7 +17,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o obj-$(CONFIG_MFD_WM8350) += wm8350.o obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o -obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o +obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o obj-$(CONFIG_MFD_CORE) += mfd-core.o diff --git a/trunk/drivers/mfd/sm501.c b/trunk/drivers/mfd/sm501.c index 170f9d47c2f9..220e4371266b 100644 --- a/trunk/drivers/mfd/sm501.c +++ b/trunk/drivers/mfd/sm501.c @@ -1374,31 +1374,31 @@ static int sm501_init_dev(struct sm501_devdata *sm) static int sm501_plat_probe(struct platform_device *dev) { struct sm501_devdata *sm; - int ret; + int err; sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL); if (sm == NULL) { dev_err(&dev->dev, "no memory for device data\n"); - ret = -ENOMEM; + err = -ENOMEM; goto err1; } sm->dev = &dev->dev; sm->pdev_id = dev->id; + sm->irq = platform_get_irq(dev, 0); + sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1); + sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); sm->platdata = dev->dev.platform_data; - ret = platform_get_irq(dev, 0); - if (ret < 0) { + if (sm->irq < 0) { dev_err(&dev->dev, "failed to get irq resource\n"); + err = sm->irq; goto err_res; } - sm->irq = ret; - sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1); - sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (sm->io_res == NULL || sm->mem_res == NULL) { dev_err(&dev->dev, "failed to get IO resource\n"); - ret = -ENOENT; + err = -ENOENT; goto err_res; } @@ -1407,7 +1407,7 @@ static int sm501_plat_probe(struct platform_device *dev) if (sm->regs_claim == NULL) { dev_err(&dev->dev, "cannot claim registers\n"); - ret = -EBUSY; + err= -EBUSY; goto err_res; } @@ -1418,7 +1418,7 @@ static int sm501_plat_probe(struct platform_device *dev) if (sm->regs == NULL) { dev_err(&dev->dev, "cannot remap registers\n"); - ret = -EIO; + err = -EIO; goto err_claim; } @@ -1430,7 +1430,7 @@ static int sm501_plat_probe(struct platform_device *dev) err_res: kfree(sm); err1: - return ret; + return err; } @@ -1625,7 +1625,8 @@ static int sm501_pci_probe(struct pci_dev *dev, goto err3; } - sm->regs = pci_ioremap_bar(dev, 1); + sm->regs = ioremap(pci_resource_start(dev, 1), + pci_resource_len(dev, 1)); if (sm->regs == NULL) { dev_err(&dev->dev, "cannot remap registers\n"); diff --git a/trunk/drivers/mfd/twl4030-core.c b/trunk/drivers/mfd/twl4030-core.c index dd843c4fbcc7..fd9a0160202c 100644 --- a/trunk/drivers/mfd/twl4030-core.c +++ b/trunk/drivers/mfd/twl4030-core.c @@ -27,11 +27,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include +#include +#include +#include +#include #include #include -#include #include #include @@ -89,6 +93,26 @@ #define twl_has_usb() false #endif +static inline void activate_irq(int irq) +{ +#ifdef CONFIG_ARM + /* ARM requires an extra step to clear IRQ_NOREQUEST, which it + * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. + */ + set_irq_flags(irq, IRQF_VALID); +#else + /* same effect on other architectures */ + set_irq_noprobe(irq); +#endif +} + +/* Primary Interrupt Handler on TWL4030 Registers */ + +/* Register Definitions */ + +#define REG_PIH_ISR_P1 (0x1) +#define REG_PIH_ISR_P2 (0x2) +#define REG_PIH_SIR (0x3) /* Triton Core internal information (BEGIN) */ @@ -151,6 +175,138 @@ /*----------------------------------------------------------------------*/ +/** + * struct twl4030_mod_iregs - TWL module IMR/ISR regs to mask/clear at init + * @mod_no: TWL4030 module number (e.g., TWL4030_MODULE_GPIO) + * @sih_ctrl: address of module SIH_CTRL register + * @reg_cnt: number of IMR/ISR regs + * @imrs: pointer to array of TWL module interrupt mask register indices + * @isrs: pointer to array of TWL module interrupt status register indices + * + * Ties together TWL4030 modules and lists of IMR/ISR registers to mask/clear + * during twl_init_irq(). + */ +struct twl4030_mod_iregs { + const u8 mod_no; + const u8 sih_ctrl; + const u8 reg_cnt; + const u8 *imrs; + const u8 *isrs; +}; + +/* TWL4030 INT module interrupt mask registers */ +static const u8 __initconst twl4030_int_imr_regs[] = { + TWL4030_INT_PWR_IMR1, + TWL4030_INT_PWR_IMR2, +}; + +/* TWL4030 INT module interrupt status registers */ +static const u8 __initconst twl4030_int_isr_regs[] = { + TWL4030_INT_PWR_ISR1, + TWL4030_INT_PWR_ISR2, +}; + +/* TWL4030 INTERRUPTS module interrupt mask registers */ +static const u8 __initconst twl4030_interrupts_imr_regs[] = { + TWL4030_INTERRUPTS_BCIIMR1A, + TWL4030_INTERRUPTS_BCIIMR1B, + TWL4030_INTERRUPTS_BCIIMR2A, + TWL4030_INTERRUPTS_BCIIMR2B, +}; + +/* TWL4030 INTERRUPTS module interrupt status registers */ +static const u8 __initconst twl4030_interrupts_isr_regs[] = { + TWL4030_INTERRUPTS_BCIISR1A, + TWL4030_INTERRUPTS_BCIISR1B, + TWL4030_INTERRUPTS_BCIISR2A, + TWL4030_INTERRUPTS_BCIISR2B, +}; + +/* TWL4030 MADC module interrupt mask registers */ +static const u8 __initconst twl4030_madc_imr_regs[] = { + TWL4030_MADC_IMR1, + TWL4030_MADC_IMR2, +}; + +/* TWL4030 MADC module interrupt status registers */ +static const u8 __initconst twl4030_madc_isr_regs[] = { + TWL4030_MADC_ISR1, + TWL4030_MADC_ISR2, +}; + +/* TWL4030 keypad module interrupt mask registers */ +static const u8 __initconst twl4030_keypad_imr_regs[] = { + TWL4030_KEYPAD_KEYP_IMR1, + TWL4030_KEYPAD_KEYP_IMR2, +}; + +/* TWL4030 keypad module interrupt status registers */ +static const u8 __initconst twl4030_keypad_isr_regs[] = { + TWL4030_KEYPAD_KEYP_ISR1, + TWL4030_KEYPAD_KEYP_ISR2, +}; + +/* TWL4030 GPIO module interrupt mask registers */ +static const u8 __initconst twl4030_gpio_imr_regs[] = { + REG_GPIO_IMR1A, + REG_GPIO_IMR1B, + REG_GPIO_IMR2A, + REG_GPIO_IMR2B, + REG_GPIO_IMR3A, + REG_GPIO_IMR3B, +}; + +/* TWL4030 GPIO module interrupt status registers */ +static const u8 __initconst twl4030_gpio_isr_regs[] = { + REG_GPIO_ISR1A, + REG_GPIO_ISR1B, + REG_GPIO_ISR2A, + REG_GPIO_ISR2B, + REG_GPIO_ISR3A, + REG_GPIO_ISR3B, +}; + +/* TWL4030 modules that have IMR/ISR registers that must be masked/cleared */ +static const struct twl4030_mod_iregs __initconst twl4030_mod_regs[] = { + { + .mod_no = TWL4030_MODULE_INT, + .sih_ctrl = TWL4030_INT_PWR_SIH_CTRL, + .reg_cnt = ARRAY_SIZE(twl4030_int_imr_regs), + .imrs = twl4030_int_imr_regs, + .isrs = twl4030_int_isr_regs, + }, + { + .mod_no = TWL4030_MODULE_INTERRUPTS, + .sih_ctrl = TWL4030_INTERRUPTS_BCISIHCTRL, + .reg_cnt = ARRAY_SIZE(twl4030_interrupts_imr_regs), + .imrs = twl4030_interrupts_imr_regs, + .isrs = twl4030_interrupts_isr_regs, + }, + { + .mod_no = TWL4030_MODULE_MADC, + .sih_ctrl = TWL4030_MADC_SIH_CTRL, + .reg_cnt = ARRAY_SIZE(twl4030_madc_imr_regs), + .imrs = twl4030_madc_imr_regs, + .isrs = twl4030_madc_isr_regs, + }, + { + .mod_no = TWL4030_MODULE_KEYPAD, + .sih_ctrl = TWL4030_KEYPAD_KEYP_SIH_CTRL, + .reg_cnt = ARRAY_SIZE(twl4030_keypad_imr_regs), + .imrs = twl4030_keypad_imr_regs, + .isrs = twl4030_keypad_isr_regs, + }, + { + .mod_no = TWL4030_MODULE_GPIO, + .sih_ctrl = REG_GPIO_SIH_CTRL, + .reg_cnt = ARRAY_SIZE(twl4030_gpio_imr_regs), + .imrs = twl4030_gpio_imr_regs, + .isrs = twl4030_gpio_isr_regs, + }, +}; + +/*----------------------------------------------------------------*/ + /* is driver active, bound to a chip? */ static bool inuse; @@ -211,6 +367,33 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { /*----------------------------------------------------------------------*/ +/* + * TWL4030 doesn't have PIH mask, hence dummy function for mask + * and unmask of the (eight) interrupts reported at that level ... + * masking is only available from SIH (secondary) modules. + */ + +static void twl4030_i2c_ackirq(unsigned int irq) +{ +} + +static void twl4030_i2c_disableint(unsigned int irq) +{ +} + +static void twl4030_i2c_enableint(unsigned int irq) +{ +} + +static struct irq_chip twl4030_irq_chip = { + .name = "twl4030", + .ack = twl4030_i2c_ackirq, + .mask = twl4030_i2c_disableint, + .unmask = twl4030_i2c_enableint, +}; + +/*----------------------------------------------------------------------*/ + /* Exported Functions */ /** @@ -352,11 +535,108 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8); /*----------------------------------------------------------------------*/ +static unsigned twl4030_irq_base; + +static struct completion irq_event; + +/* + * This thread processes interrupts reported by the Primary Interrupt Handler. + */ +static int twl4030_irq_thread(void *data) +{ + long irq = (long)data; + irq_desc_t *desc = irq_desc + irq; + static unsigned i2c_errors; + const static unsigned max_i2c_errors = 100; + + current->flags |= PF_NOFREEZE; + + while (!kthread_should_stop()) { + int ret; + int module_irq; + u8 pih_isr; + + /* Wait for IRQ, then read PIH irq status (also blocking) */ + wait_for_completion_interruptible(&irq_event); + + ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, + REG_PIH_ISR_P1); + if (ret) { + pr_warning("%s: I2C error %d reading PIH ISR\n", + DRIVER_NAME, ret); + if (++i2c_errors >= max_i2c_errors) { + printk(KERN_ERR "Maximum I2C error count" + " exceeded. Terminating %s.\n", + __func__); + break; + } + complete(&irq_event); + continue; + } + + /* these handlers deal with the relevant SIH irq status */ + local_irq_disable(); + for (module_irq = twl4030_irq_base; + pih_isr; + pih_isr >>= 1, module_irq++) { + if (pih_isr & 0x1) { + irq_desc_t *d = irq_desc + module_irq; + + d->handle_irq(module_irq, d); + } + } + local_irq_enable(); + + desc->chip->unmask(irq); + } + + return 0; +} + /* - * NOTE: We know the first 8 IRQs after pdata->base_irq are - * for the PIH, and the next are for the PWR_INT SIH, since - * that's how twl_init_irq() sets things up. + * do_twl4030_irq() is the desc->handle method for the twl4030 interrupt. + * This is a chained interrupt, so there is no desc->action method for it. + * Now we need to query the interrupt controller in the twl4030 to determine + * which module is generating the interrupt request. However, we can't do i2c + * transactions in interrupt context, so we must defer that work to a kernel + * thread. All we do here is acknowledge and mask the interrupt and wakeup + * the kernel thread. */ +static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc) +{ + const unsigned int cpu = smp_processor_id(); + + /* + * Earlier this was desc->triggered = 1; + */ + desc->status |= IRQ_LEVEL; + + /* + * Acknowledge, clear _AND_ disable the interrupt. + */ + desc->chip->ack(irq); + + if (!desc->depth) { + kstat_cpu(cpu).irqs[irq]++; + + complete(&irq_event); + } +} + +static struct task_struct * __init start_twl4030_irq_thread(long irq) +{ + struct task_struct *thread; + + init_completion(&irq_event); + thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq"); + if (!thread) + pr_err("%s: could not create twl4030 irq %ld thread!\n", + DRIVER_NAME, irq); + + return thread; +} + +/*----------------------------------------------------------------------*/ static int add_children(struct twl4030_platform_data *pdata) { @@ -388,7 +668,7 @@ static int add_children(struct twl4030_platform_data *pdata) if (status == 0) { struct resource r = { - .start = pdata->irq_base + 8 + 1, + .start = TWL4030_PWRIRQ_CHG_PRES, .flags = IORESOURCE_IRQ, }; @@ -537,7 +817,8 @@ static int add_children(struct twl4030_platform_data *pdata) /* RTC module IRQ */ if (status == 0) { struct resource r = { - .start = pdata->irq_base + 8 + 3, + /* REVISIT don't hard-wire this stuff */ + .start = TWL4030_PWRIRQ_RTC, .flags = IORESOURCE_IRQ, }; @@ -582,7 +863,7 @@ static int add_children(struct twl4030_platform_data *pdata) if (status == 0) { struct resource r = { - .start = pdata->irq_base + 8 + 2, + .start = TWL4030_PWRIRQ_USB_PRES, .flags = IORESOURCE_IRQ, }; @@ -684,17 +965,123 @@ static void __init clocks_init(void) /*----------------------------------------------------------------------*/ -int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); -int twl_exit_irq(void); +/** + * twl4030_i2c_clear_isr - clear TWL4030 SIH ISR regs via read + write + * @mod_no: TWL4030 module number + * @reg: register index to clear + * @cor: value of the _SIH_CTRL.COR bit (1 or 0) + * + * Either reads (cor == 1) or writes (cor == 0) to a TWL4030 interrupt + * status register to ensure that any prior interrupts are cleared. + * Returns the status from the I2C read operation. + */ +static int __init twl4030_i2c_clear_isr(u8 mod_no, u8 reg, u8 cor) +{ + u8 tmp; + + return (cor) ? twl4030_i2c_read_u8(mod_no, &tmp, reg) : + twl4030_i2c_write_u8(mod_no, 0xff, reg); +} + +/** + * twl4030_read_cor_bit - are TWL module ISRs cleared by reads or writes? + * @mod_no: TWL4030 module number + * @reg: register index to clear + * + * Returns 1 if the TWL4030 SIH interrupt status registers (ISRs) for + * the specified TWL module are cleared by reads, or 0 if cleared by + * writes. + */ +static int twl4030_read_cor_bit(u8 mod_no, u8 reg) +{ + u8 tmp = 0; + + WARN_ON(twl4030_i2c_read_u8(mod_no, &tmp, reg) < 0); + + tmp &= TWL4030_SIH_CTRL_COR_MASK; + tmp >>= __ffs(TWL4030_SIH_CTRL_COR_MASK); + + return tmp; +} + +/** + * twl4030_mask_clear_intrs - mask and clear all TWL4030 interrupts + * @t: pointer to twl4030_mod_iregs array + * @t_sz: ARRAY_SIZE(t) (starting at 1) + * + * Mask all TWL4030 interrupt mask registers (IMRs) and clear all + * interrupt status registers (ISRs). No return value, but will WARN if + * any I2C operations fail. + */ +static void __init twl4030_mask_clear_intrs(const struct twl4030_mod_iregs *t, + const u8 t_sz) +{ + int i, j; + + /* + * N.B. - further efficiency is possible here. Eight I2C + * operations on BCI and GPIO modules are avoidable if I2C + * burst read/write transactions were implemented. Would + * probably save about 1ms of boot time and a small amount of + * power. + */ + for (i = 0; i < t_sz; i++) { + const struct twl4030_mod_iregs tmr = t[i]; + int cor; + + /* Are ISRs cleared by reads or writes? */ + cor = twl4030_read_cor_bit(tmr.mod_no, tmr.sih_ctrl); + + for (j = 0; j < tmr.reg_cnt; j++) { + + /* Mask interrupts at the TWL4030 */ + WARN_ON(twl4030_i2c_write_u8(tmr.mod_no, 0xff, + tmr.imrs[j]) < 0); + + /* Clear TWL4030 ISRs */ + WARN_ON(twl4030_i2c_clear_isr(tmr.mod_no, + tmr.isrs[j], cor) < 0); + } + } +} + + +static void twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) +{ + int i; + + /* + * Mask and clear all TWL4030 interrupts since initially we do + * not have any TWL4030 module interrupt handlers present + */ + twl4030_mask_clear_intrs(twl4030_mod_regs, + ARRAY_SIZE(twl4030_mod_regs)); + + twl4030_irq_base = irq_base; + + /* install an irq handler for each of the PIH modules */ + for (i = irq_base; i < irq_end; i++) { + set_irq_chip_and_handler(i, &twl4030_irq_chip, + handle_simple_irq); + activate_irq(i); + } + + /* install an irq handler to demultiplex the TWL4030 interrupt */ + set_irq_data(irq_num, start_twl4030_irq_thread(irq_num)); + set_irq_chained_handler(irq_num, do_twl4030_irq); +} + +/*----------------------------------------------------------------------*/ static int twl4030_remove(struct i2c_client *client) { unsigned i; - int status; - status = twl_exit_irq(); - if (status < 0) - return status; + /* FIXME undo twl_init_irq() */ + if (twl4030_irq_base) { + dev_err(&client->dev, "can't yet clean up IRQs?\n"); + return -ENOSYS; + } for (i = 0; i < TWL4030_NUM_SLAVES; i++) { struct twl4030_client *twl = &twl4030_modules[i]; @@ -725,7 +1112,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) return -EIO; } - if (inuse) { + if (inuse || twl4030_irq_base) { dev_dbg(&client->dev, "driver is already in use\n"); return -EBUSY; } @@ -759,9 +1146,9 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) if (client->irq && pdata->irq_base && pdata->irq_end > pdata->irq_base) { - status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); - if (status < 0) - goto fail; + twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); + dev_info(&client->dev, "IRQ %d chains IRQs %d..%d\n", + client->irq, pdata->irq_base, pdata->irq_end - 1); } status = add_children(pdata); diff --git a/trunk/drivers/mfd/twl4030-irq.c b/trunk/drivers/mfd/twl4030-irq.c deleted file mode 100644 index fae868a8d499..000000000000 --- a/trunk/drivers/mfd/twl4030-irq.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * twl4030-irq.c - TWL4030/TPS659x0 irq support - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * Modifications to defer interrupt handling to a kernel thread: - * Copyright (C) 2006 MontaVista Software, Inc. - * - * Based on tlv320aic23.c: - * Copyright (c) by Kai Svahn - * - * Code cleanup and modifications to IRQ handler. - * by syed khasim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include - - -/* - * TWL4030 IRQ handling has two stages in hardware, and thus in software. - * The Primary Interrupt Handler (PIH) stage exposes status bits saying - * which Secondary Interrupt Handler (SIH) stage is raising an interrupt. - * SIH modules are more traditional IRQ components, which support per-IRQ - * enable/disable and trigger controls; they do most of the work. - * - * These chips are designed to support IRQ handling from two different - * I2C masters. Each has a dedicated IRQ line, and dedicated IRQ status - * and mask registers in the PIH and SIH modules. - * - * We set up IRQs starting at a platform-specified base, always starting - * with PIH and the SIH for PWR_INT and then usually adding GPIO: - * base + 0 .. base + 7 PIH - * base + 8 .. base + 15 SIH for PWR_INT - * base + 16 .. base + 33 SIH for GPIO - */ - -/* PIH register offsets */ -#define REG_PIH_ISR_P1 0x01 -#define REG_PIH_ISR_P2 0x02 -#define REG_PIH_SIR 0x03 /* for testing */ - - -/* Linux could (eventually) use either IRQ line */ -static int irq_line; - -struct sih { - char name[8]; - u8 module; /* module id */ - u8 control_offset; /* for SIH_CTRL */ - bool set_cor; - - u8 bits; /* valid in isr/imr */ - u8 bytes_ixr; /* bytelen of ISR/IMR/SIR */ - - u8 edr_offset; - u8 bytes_edr; /* bytelen of EDR */ - - /* SIR ignored -- set interrupt, for testing only */ - struct irq_data { - u8 isr_offset; - u8 imr_offset; - } mask[2]; - /* + 2 bytes padding */ -}; - -#define SIH_INITIALIZER(modname, nbits) \ - .module = TWL4030_MODULE_ ## modname, \ - .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \ - .bits = nbits, \ - .bytes_ixr = DIV_ROUND_UP(nbits, 8), \ - .edr_offset = TWL4030_ ## modname ## _EDR, \ - .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \ - .mask = { { \ - .isr_offset = TWL4030_ ## modname ## _ISR1, \ - .imr_offset = TWL4030_ ## modname ## _IMR1, \ - }, \ - { \ - .isr_offset = TWL4030_ ## modname ## _ISR2, \ - .imr_offset = TWL4030_ ## modname ## _IMR2, \ - }, }, - -/* register naming policies are inconsistent ... */ -#define TWL4030_INT_PWR_EDR TWL4030_INT_PWR_EDR1 -#define TWL4030_MODULE_KEYPAD_KEYP TWL4030_MODULE_KEYPAD -#define TWL4030_MODULE_INT_PWR TWL4030_MODULE_INT - - -/* Order in this table matches order in PIH_ISR. That is, - * BIT(n) in PIH_ISR is sih_modules[n]. - */ -static const struct sih sih_modules[6] = { - [0] = { - .name = "gpio", - .module = TWL4030_MODULE_GPIO, - .control_offset = REG_GPIO_SIH_CTRL, - .set_cor = true, - .bits = TWL4030_GPIO_MAX, - .bytes_ixr = 3, - /* Note: *all* of these IRQs default to no-trigger */ - .edr_offset = REG_GPIO_EDR1, - .bytes_edr = 5, - .mask = { { - .isr_offset = REG_GPIO_ISR1A, - .imr_offset = REG_GPIO_IMR1A, - }, { - .isr_offset = REG_GPIO_ISR1B, - .imr_offset = REG_GPIO_IMR1B, - }, }, - }, - [1] = { - .name = "keypad", - .set_cor = true, - SIH_INITIALIZER(KEYPAD_KEYP, 4) - }, - [2] = { - .name = "bci", - .module = TWL4030_MODULE_INTERRUPTS, - .control_offset = TWL4030_INTERRUPTS_BCISIHCTRL, - .bits = 12, - .bytes_ixr = 2, - .edr_offset = TWL4030_INTERRUPTS_BCIEDR1, - /* Note: most of these IRQs default to no-trigger */ - .bytes_edr = 3, - .mask = { { - .isr_offset = TWL4030_INTERRUPTS_BCIISR1A, - .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A, - }, { - .isr_offset = TWL4030_INTERRUPTS_BCIISR1B, - .imr_offset = TWL4030_INTERRUPTS_BCIIMR1B, - }, }, - }, - [3] = { - .name = "madc", - SIH_INITIALIZER(MADC, 4) - }, - [4] = { - /* USB doesn't use the same SIH organization */ - .name = "usb", - }, - [5] = { - .name = "power", - .set_cor = true, - SIH_INITIALIZER(INT_PWR, 8) - }, - /* there are no SIH modules #6 or #7 ... */ -}; - -#undef TWL4030_MODULE_KEYPAD_KEYP -#undef TWL4030_MODULE_INT_PWR -#undef TWL4030_INT_PWR_EDR - -/*----------------------------------------------------------------------*/ - -static unsigned twl4030_irq_base; - -static struct completion irq_event; - -/* - * This thread processes interrupts reported by the Primary Interrupt Handler. - */ -static int twl4030_irq_thread(void *data) -{ - long irq = (long)data; - irq_desc_t *desc = irq_desc + irq; - static unsigned i2c_errors; - const static unsigned max_i2c_errors = 100; - - current->flags |= PF_NOFREEZE; - - while (!kthread_should_stop()) { - int ret; - int module_irq; - u8 pih_isr; - - /* Wait for IRQ, then read PIH irq status (also blocking) */ - wait_for_completion_interruptible(&irq_event); - - ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, - REG_PIH_ISR_P1); - if (ret) { - pr_warning("twl4030: I2C error %d reading PIH ISR\n", - ret); - if (++i2c_errors >= max_i2c_errors) { - printk(KERN_ERR "Maximum I2C error count" - " exceeded. Terminating %s.\n", - __func__); - break; - } - complete(&irq_event); - continue; - } - - /* these handlers deal with the relevant SIH irq status */ - local_irq_disable(); - for (module_irq = twl4030_irq_base; - pih_isr; - pih_isr >>= 1, module_irq++) { - if (pih_isr & 0x1) { - irq_desc_t *d = irq_desc + module_irq; - - /* These can't be masked ... always warn - * if we get any surprises. - */ - if (d->status & IRQ_DISABLED) - note_interrupt(module_irq, d, - IRQ_NONE); - else - d->handle_irq(module_irq, d); - } - } - local_irq_enable(); - - desc->chip->unmask(irq); - } - - return 0; -} - -/* - * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. - * This is a chained interrupt, so there is no desc->action method for it. - * Now we need to query the interrupt controller in the twl4030 to determine - * which module is generating the interrupt request. However, we can't do i2c - * transactions in interrupt context, so we must defer that work to a kernel - * thread. All we do here is acknowledge and mask the interrupt and wakeup - * the kernel thread. - */ -static void handle_twl4030_pih(unsigned int irq, irq_desc_t *desc) -{ - /* Acknowledge, clear *AND* mask the interrupt... */ - desc->chip->ack(irq); - complete(&irq_event); -} - -static struct task_struct *start_twl4030_irq_thread(long irq) -{ - struct task_struct *thread; - - init_completion(&irq_event); - thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq"); - if (!thread) - pr_err("twl4030: could not create irq %ld thread!\n", irq); - - return thread; -} - -/*----------------------------------------------------------------------*/ - -/* - * twl4030_init_sih_modules() ... start from a known state where no - * IRQs will be coming in, and where we can quickly enable them then - * handle them as they arrive. Mask all IRQs: maybe init SIH_CTRL. - * - * NOTE: we don't touch EDR registers here; they stay with hardware - * defaults or whatever the last value was. Note that when both EDR - * bits for an IRQ are clear, that's as if its IMR bit is set... - */ -static int twl4030_init_sih_modules(unsigned line) -{ - const struct sih *sih; - u8 buf[4]; - int i; - int status; - - /* line 0 == int1_n signal; line 1 == int2_n signal */ - if (line > 1) - return -EINVAL; - - irq_line = line; - - /* disable all interrupts on our line */ - memset(buf, 0xff, sizeof buf); - sih = sih_modules; - for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { - - /* skip USB -- it's funky */ - if (!sih->bytes_ixr) - continue; - - status = twl4030_i2c_write(sih->module, buf, - sih->mask[line].imr_offset, sih->bytes_ixr); - if (status < 0) - pr_err("twl4030: err %d initializing %s %s\n", - status, sih->name, "IMR"); - - /* Maybe disable "exclusive" mode; buffer second pending irq; - * set Clear-On-Read (COR) bit. - * - * NOTE that sometimes COR polarity is documented as being - * inverted: for MADC and BCI, COR=1 means "clear on write". - * And for PWR_INT it's not documented... - */ - if (sih->set_cor) { - status = twl4030_i2c_write_u8(sih->module, - TWL4030_SIH_CTRL_COR_MASK, - sih->control_offset); - if (status < 0) - pr_err("twl4030: err %d initializing %s %s\n", - status, sih->name, "SIH_CTRL"); - } - } - - sih = sih_modules; - for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) { - u8 rxbuf[4]; - int j; - - /* skip USB */ - if (!sih->bytes_ixr) - continue; - - /* Clear pending interrupt status. Either the read was - * enough, or we need to write those bits. Repeat, in - * case an IRQ is pending (PENDDIS=0) ... that's not - * uncommon with PWR_INT.PWRON. - */ - for (j = 0; j < 2; j++) { - status = twl4030_i2c_read(sih->module, rxbuf, - sih->mask[line].isr_offset, sih->bytes_ixr); - if (status < 0) - pr_err("twl4030: err %d initializing %s %s\n", - status, sih->name, "ISR"); - - if (!sih->set_cor) - status = twl4030_i2c_write(sih->module, buf, - sih->mask[line].isr_offset, - sih->bytes_ixr); - /* else COR=1 means read sufficed. - * (for most SIH modules...) - */ - } - } - - return 0; -} - -static inline void activate_irq(int irq) -{ -#ifdef CONFIG_ARM - /* ARM requires an extra step to clear IRQ_NOREQUEST, which it - * sets on behalf of every irq_chip. Also sets IRQ_NOPROBE. - */ - set_irq_flags(irq, IRQF_VALID); -#else - /* same effect on other architectures */ - set_irq_noprobe(irq); -#endif -} - -/*----------------------------------------------------------------------*/ - -static DEFINE_SPINLOCK(sih_agent_lock); - -static struct workqueue_struct *wq; - -struct sih_agent { - int irq_base; - const struct sih *sih; - - u32 imr; - bool imr_change_pending; - struct work_struct mask_work; - - u32 edge_change; - struct work_struct edge_work; -}; - -static void twl4030_sih_do_mask(struct work_struct *work) -{ - struct sih_agent *agent; - const struct sih *sih; - union { - u8 bytes[4]; - u32 word; - } imr; - int status; - - agent = container_of(work, struct sih_agent, mask_work); - - /* see what work we have */ - spin_lock_irq(&sih_agent_lock); - if (agent->imr_change_pending) { - sih = agent->sih; - /* byte[0] gets overwritten as we write ... */ - imr.word = cpu_to_le32(agent->imr << 8); - agent->imr_change_pending = false; - } else - sih = NULL; - spin_unlock_irq(&sih_agent_lock); - if (!sih) - return; - - /* write the whole mask ... simpler than subsetting it */ - status = twl4030_i2c_write(sih->module, imr.bytes, - sih->mask[irq_line].imr_offset, sih->bytes_ixr); - if (status) - pr_err("twl4030: %s, %s --> %d\n", __func__, - "write", status); -} - -static void twl4030_sih_do_edge(struct work_struct *work) -{ - struct sih_agent *agent; - const struct sih *sih; - u8 bytes[6]; - u32 edge_change; - int status; - - agent = container_of(work, struct sih_agent, edge_work); - - /* see what work we have */ - spin_lock_irq(&sih_agent_lock); - edge_change = agent->edge_change; - agent->edge_change = 0;; - sih = edge_change ? agent->sih : NULL; - spin_unlock_irq(&sih_agent_lock); - if (!sih) - return; - - /* Read, reserving first byte for write scratch. Yes, this - * could be cached for some speedup ... but be careful about - * any processor on the other IRQ line, EDR registers are - * shared. - */ - status = twl4030_i2c_read(sih->module, bytes + 1, - sih->edr_offset, sih->bytes_edr); - if (status) { - pr_err("twl4030: %s, %s --> %d\n", __func__, - "read", status); - return; - } - - /* Modify only the bits we know must change */ - while (edge_change) { - int i = fls(edge_change) - 1; - struct irq_desc *d = irq_desc + i + agent->irq_base; - int byte = 1 + (i >> 2); - int off = (i & 0x3) * 2; - - bytes[byte] &= ~(0x03 << off); - - spin_lock_irq(&d->lock); - if (d->status & IRQ_TYPE_EDGE_RISING) - bytes[byte] |= BIT(off + 1); - if (d->status & IRQ_TYPE_EDGE_FALLING) - bytes[byte] |= BIT(off + 0); - spin_unlock_irq(&d->lock); - - edge_change &= ~BIT(i); - } - - /* Write */ - status = twl4030_i2c_write(sih->module, bytes, - sih->edr_offset, sih->bytes_edr); - if (status) - pr_err("twl4030: %s, %s --> %d\n", __func__, - "write", status); -} - -/*----------------------------------------------------------------------*/ - -/* - * All irq_chip methods get issued from code holding irq_desc[irq].lock, - * which can't perform the underlying I2C operations (because they sleep). - * So we must hand them off to a thread (workqueue) and cope with asynch - * completion, potentially including some re-ordering, of these requests. - */ - -static void twl4030_sih_mask(unsigned irq) -{ - struct sih_agent *sih = get_irq_chip_data(irq); - unsigned long flags; - - spin_lock_irqsave(&sih_agent_lock, flags); - sih->imr |= BIT(irq - sih->irq_base); - sih->imr_change_pending = true; - queue_work(wq, &sih->mask_work); - spin_unlock_irqrestore(&sih_agent_lock, flags); -} - -static void twl4030_sih_unmask(unsigned irq) -{ - struct sih_agent *sih = get_irq_chip_data(irq); - unsigned long flags; - - spin_lock_irqsave(&sih_agent_lock, flags); - sih->imr &= ~BIT(irq - sih->irq_base); - sih->imr_change_pending = true; - queue_work(wq, &sih->mask_work); - spin_unlock_irqrestore(&sih_agent_lock, flags); -} - -static int twl4030_sih_set_type(unsigned irq, unsigned trigger) -{ - struct sih_agent *sih = get_irq_chip_data(irq); - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - - if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - return -EINVAL; - - spin_lock_irqsave(&sih_agent_lock, flags); - if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) { - desc->status &= ~IRQ_TYPE_SENSE_MASK; - desc->status |= trigger; - sih->edge_change |= BIT(irq - sih->irq_base); - queue_work(wq, &sih->edge_work); - } - spin_unlock_irqrestore(&sih_agent_lock, flags); - return 0; -} - -static struct irq_chip twl4030_sih_irq_chip = { - .name = "twl4030", - .mask = twl4030_sih_mask, - .unmask = twl4030_sih_unmask, - .set_type = twl4030_sih_set_type, -}; - -/*----------------------------------------------------------------------*/ - -static inline int sih_read_isr(const struct sih *sih) -{ - int status; - union { - u8 bytes[4]; - u32 word; - } isr; - - /* FIXME need retry-on-error ... */ - - isr.word = 0; - status = twl4030_i2c_read(sih->module, isr.bytes, - sih->mask[irq_line].isr_offset, sih->bytes_ixr); - - return (status < 0) ? status : le32_to_cpu(isr.word); -} - -/* - * Generic handler for SIH interrupts ... we "know" this is called - * in task context, with IRQs enabled. - */ -static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) -{ - struct sih_agent *agent = get_irq_data(irq); - const struct sih *sih = agent->sih; - int isr; - - /* reading ISR acks the IRQs, using clear-on-read mode */ - local_irq_enable(); - isr = sih_read_isr(sih); - local_irq_disable(); - - if (isr < 0) { - pr_err("twl4030: %s SIH, read ISR error %d\n", - sih->name, isr); - /* REVISIT: recover; eventually mask it all, etc */ - return; - } - - while (isr) { - irq = fls(isr); - irq--; - isr &= ~BIT(irq); - - if (irq < sih->bits) - generic_handle_irq(agent->irq_base + irq); - else - pr_err("twl4030: %s SIH, invalid ISR bit %d\n", - sih->name, irq); - } -} - -static unsigned twl4030_irq_next; - -/* returns the first IRQ used by this SIH bank, - * or negative errno - */ -int twl4030_sih_setup(int module) -{ - int sih_mod; - const struct sih *sih = NULL; - struct sih_agent *agent; - int i, irq; - int status = -EINVAL; - unsigned irq_base = twl4030_irq_next; - - /* only support modules with standard clear-on-read for now */ - for (sih_mod = 0, sih = sih_modules; - sih_mod < ARRAY_SIZE(sih_modules); - sih_mod++, sih++) { - if (sih->module == module && sih->set_cor) { - if (!WARN((irq_base + sih->bits) > NR_IRQS, - "irq %d for %s too big\n", - irq_base + sih->bits, - sih->name)) - status = 0; - break; - } - } - if (status < 0) - return status; - - agent = kzalloc(sizeof *agent, GFP_KERNEL); - if (!agent) - return -ENOMEM; - - status = 0; - - agent->irq_base = irq_base; - agent->sih = sih; - agent->imr = ~0; - INIT_WORK(&agent->mask_work, twl4030_sih_do_mask); - INIT_WORK(&agent->edge_work, twl4030_sih_do_edge); - - for (i = 0; i < sih->bits; i++) { - irq = irq_base + i; - - set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip, - handle_edge_irq); - set_irq_chip_data(irq, agent); - activate_irq(irq); - } - - status = irq_base; - twl4030_irq_next += i; - - /* replace generic PIH handler (handle_simple_irq) */ - irq = sih_mod + twl4030_irq_base; - set_irq_data(irq, agent); - set_irq_chained_handler(irq, handle_twl4030_sih); - - pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, - irq, irq_base, twl4030_irq_next - 1); - - return status; -} - -/* FIXME need a call to reverse twl4030_sih_setup() ... */ - - -/*----------------------------------------------------------------------*/ - -/* FIXME pass in which interrupt line we'll use ... */ -#define twl_irq_line 0 - -int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) -{ - static struct irq_chip twl4030_irq_chip; - - int status; - int i; - struct task_struct *task; - - /* - * Mask and clear all TWL4030 interrupts since initially we do - * not have any TWL4030 module interrupt handlers present - */ - status = twl4030_init_sih_modules(twl_irq_line); - if (status < 0) - return status; - - wq = create_singlethread_workqueue("twl4030-irqchip"); - if (!wq) { - pr_err("twl4030: workqueue FAIL\n"); - return -ESRCH; - } - - twl4030_irq_base = irq_base; - - /* install an irq handler for each of the SIH modules; - * clone dummy irq_chip since PIH can't *do* anything - */ - twl4030_irq_chip = dummy_irq_chip; - twl4030_irq_chip.name = "twl4030"; - - twl4030_sih_irq_chip.ack = dummy_irq_chip.ack; - - for (i = irq_base; i < irq_end; i++) { - set_irq_chip_and_handler(i, &twl4030_irq_chip, - handle_simple_irq); - activate_irq(i); - } - twl4030_irq_next = i; - pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", - irq_num, irq_base, twl4030_irq_next - 1); - - /* ... and the PWR_INT module ... */ - status = twl4030_sih_setup(TWL4030_MODULE_INT); - if (status < 0) { - pr_err("twl4030: sih_setup PWR INT --> %d\n", status); - goto fail; - } - - /* install an irq handler to demultiplex the TWL4030 interrupt */ - task = start_twl4030_irq_thread(irq_num); - if (!task) { - pr_err("twl4030: irq thread FAIL\n"); - status = -ESRCH; - goto fail; - } - - set_irq_data(irq_num, task); - set_irq_chained_handler(irq_num, handle_twl4030_pih); - - return status; - -fail: - for (i = irq_base; i < irq_end; i++) - set_irq_chip_and_handler(i, NULL, NULL); - destroy_workqueue(wq); - wq = NULL; - return status; -} - -int twl_exit_irq(void) -{ - /* FIXME undo twl_init_irq() */ - if (twl4030_irq_base) { - pr_err("twl4030: can't yet clean up IRQs?\n"); - return -ENOSYS; - } - return 0; -} diff --git a/trunk/drivers/mfd/wm8350-core.c b/trunk/drivers/mfd/wm8350-core.c index 0d47fb9e4b3b..bf87f675e7fa 100644 --- a/trunk/drivers/mfd/wm8350-core.c +++ b/trunk/drivers/mfd/wm8350-core.c @@ -183,9 +183,6 @@ static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) | src[i - reg]; - /* Don't store volatile bits */ - wm8350->reg_cache[i] &= ~wm8350_reg_io_map[i].vol; - src[i - reg] = cpu_to_be16(src[i - reg]); } @@ -1123,7 +1120,6 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode) } value = be16_to_cpu(value); value &= wm8350_reg_io_map[i].readable; - value &= ~wm8350_reg_io_map[i].vol; wm8350->reg_cache[i] = value; } else wm8350->reg_cache[i] = reg_map[i]; @@ -1132,6 +1128,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode) out: return ret; } +EXPORT_SYMBOL_GPL(wm8350_create_cache); /* * Register a client device. This is non-fatal since there is no need to diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 0b71ebc074b6..ad301ace6085 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -464,12 +464,6 @@ config MIPS_JAZZ_SONIC This is the driver for the onboard card of MIPS Magnum 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM systems. -config XTENSA_XT2000_SONIC - tristate "Xtensa XT2000 onboard SONIC Ethernet support" - depends on XTENSA_PLATFORM_XT2000 - help - This is the driver for the onboard card of the Xtensa XT2000 board. - config MIPS_AU1X00_ENET bool "MIPS AU1000 Ethernet support" depends on SOC_AU1X00 @@ -2510,15 +2504,6 @@ config PASEMI_MAC This driver supports the on-chip 1/10Gbit Ethernet controller on PA Semi's PWRficient line of chips. -config MLX4_EN - tristate "Mellanox Technologies 10Gbit Ethernet support" - depends on PCI && INET - select MLX4_CORE - select INET_LRO - help - This driver supports Mellanox Technologies ConnectX Ethernet - devices. - config MLX4_CORE tristate depends on PCI diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index f19acf8b9220..fa2510b2e609 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -227,8 +227,6 @@ pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o obj-$(CONFIG_MLX4_CORE) += mlx4/ obj-$(CONFIG_ENC28J60) += enc28j60.o -obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o - obj-$(CONFIG_MACB) += macb.o obj-$(CONFIG_ARM) += arm/ diff --git a/trunk/drivers/net/fec_mpc52xx_phy.c b/trunk/drivers/net/fec_mpc52xx_phy.c index 45dd9bdc5d62..08e18bcb970f 100644 --- a/trunk/drivers/net/fec_mpc52xx_phy.c +++ b/trunk/drivers/net/fec_mpc52xx_phy.c @@ -2,7 +2,6 @@ * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver * * Copyright (C) 2007 Domen Puncer, Telargo, Inc. - * Copyright (C) 2008 Wolfram Sang, Pengutronix * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any @@ -22,45 +21,58 @@ struct mpc52xx_fec_mdio_priv { struct mpc52xx_fec __iomem *regs; }; -static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, - int reg, u32 value) +static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) { struct mpc52xx_fec_mdio_priv *priv = bus->priv; struct mpc52xx_fec __iomem *fec; int tries = 100; - - value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; - value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + u32 request = FEC_MII_READ_FRAME; fec = priv->regs; out_be32(&fec->ievent, FEC_IEVENT_MII); - out_be32(&priv->regs->mii_data, value); + + request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, request); /* wait for it to finish, this takes about 23 us on lite5200b */ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) udelay(5); - if (!tries) + if (tries == 0) return -ETIMEDOUT; - return value & FEC_MII_DATA_OP_RD ? - in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0; + return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK; } -static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) +static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) { - return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, FEC_MII_READ_FRAME); -} + struct mpc52xx_fec_mdio_priv *priv = bus->priv; + struct mpc52xx_fec __iomem *fec; + u32 value = data; + int tries = 100; -static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, - u16 data) -{ - return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, - data | FEC_MII_WRITE_FRAME); + fec = priv->regs; + out_be32(&fec->ievent, FEC_IEVENT_MII); + + value |= FEC_MII_WRITE_FRAME; + value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; + + out_be32(&priv->regs->mii_data, value); + + /* wait for request to finish */ + while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) + udelay(5); + + if (tries == 0) + return -ETIMEDOUT; + + return 0; } -static int mpc52xx_fec_mdio_probe(struct of_device *of, - const struct of_device_id *match) +static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match) { struct device *dev = &of->dev; struct device_node *np = of->node; @@ -119,8 +131,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, dev_set_drvdata(dev, bus); /* set MII speed */ - out_be32(&priv->regs->mii_speed, - ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); + out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); /* enable MII interrupt */ out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); diff --git a/trunk/drivers/net/ibm_newemac/core.c b/trunk/drivers/net/ibm_newemac/core.c index 2ee2622258f5..efcf21c9f5c7 100644 --- a/trunk/drivers/net/ibm_newemac/core.c +++ b/trunk/drivers/net/ibm_newemac/core.c @@ -2604,16 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-440ep") || of_device_is_compatible(np, "ibm,emac-440gr")) dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; - if (of_device_is_compatible(np, "ibm,emac-405ez")) { -#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CONTROL + if (of_device_is_compatible(np, "ibm,emac-405ez")) dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x; -#else - printk(KERN_ERR "%s: Flow control not disabled!\n", - np->full_name); - return -ENXIO; -#endif - } - } /* Fixup some feature bits based on the device tree */ diff --git a/trunk/drivers/net/ibm_newemac/mal.c b/trunk/drivers/net/ibm_newemac/mal.c index ecf9798987fa..1839d3f154a3 100644 --- a/trunk/drivers/net/ibm_newemac/mal.c +++ b/trunk/drivers/net/ibm_newemac/mal.c @@ -280,11 +280,9 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance) mal_schedule_poll(mal); set_mal_dcrn(mal, MAL_TXEOBISR, r); -#ifdef CONFIG_PPC_DCR_NATIVE if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) mtdcri(SDR0, DCRN_SDR_ICINTSTAT, (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX)); -#endif return IRQ_HANDLED; } @@ -300,11 +298,9 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance) mal_schedule_poll(mal); set_mal_dcrn(mal, MAL_RXEOBISR, r); -#ifdef CONFIG_PPC_DCR_NATIVE if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) mtdcri(SDR0, DCRN_SDR_ICINTSTAT, (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX)); -#endif return IRQ_HANDLED; } @@ -576,18 +572,9 @@ static int __devinit mal_probe(struct of_device *ofdev, goto fail; } - if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez")) { -#if defined(CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT) && \ - defined(CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR) + if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez")) mal->features |= (MAL_FTR_CLEAR_ICINTSTAT | MAL_FTR_COMMON_ERR_INT); -#else - printk(KERN_ERR "%s: Support for 405EZ not enabled!\n", - ofdev->node->full_name); - err = -ENODEV; - goto fail; -#endif - } mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0); mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1); diff --git a/trunk/drivers/net/mlx4/Makefile b/trunk/drivers/net/mlx4/Makefile index a7a97bf998f8..0952a6528f58 100644 --- a/trunk/drivers/net/mlx4/Makefile +++ b/trunk/drivers/net/mlx4/Makefile @@ -1,9 +1,4 @@ obj-$(CONFIG_MLX4_CORE) += mlx4_core.o mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ - mr.o pd.o port.o profile.o qp.o reset.o srq.o - -obj-$(CONFIG_MLX4_EN) += mlx4_en.o - -mlx4_en-y := en_main.o en_tx.o en_rx.o en_params.o en_port.o en_cq.o \ - en_resources.o en_netdev.o + mr.o pd.o profile.o qp.o reset.o srq.o diff --git a/trunk/drivers/net/mlx4/alloc.c b/trunk/drivers/net/mlx4/alloc.c index ad95d5f7b630..b411b79d72ad 100644 --- a/trunk/drivers/net/mlx4/alloc.c +++ b/trunk/drivers/net/mlx4/alloc.c @@ -48,16 +48,13 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); if (obj >= bitmap->max) { - bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) - & bitmap->mask; + bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; obj = find_first_zero_bit(bitmap->table, bitmap->max); } if (obj < bitmap->max) { set_bit(obj, bitmap->table); - bitmap->last = (obj + 1); - if (bitmap->last == bitmap->max) - bitmap->last = 0; + bitmap->last = (obj + 1) & (bitmap->max - 1); obj |= bitmap->top; } else obj = -1; @@ -69,90 +66,16 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) { - mlx4_bitmap_free_range(bitmap, obj, 1); -} - -static unsigned long find_aligned_range(unsigned long *bitmap, - u32 start, u32 nbits, - int len, int align) -{ - unsigned long end, i; - -again: - start = ALIGN(start, align); - - while ((start < nbits) && test_bit(start, bitmap)) - start += align; - - if (start >= nbits) - return -1; - - end = start+len; - if (end > nbits) - return -1; - - for (i = start + 1; i < end; i++) { - if (test_bit(i, bitmap)) { - start = i + 1; - goto again; - } - } - - return start; -} - -u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) -{ - u32 obj, i; - - if (likely(cnt == 1 && align == 1)) - return mlx4_bitmap_alloc(bitmap); - - spin_lock(&bitmap->lock); - - obj = find_aligned_range(bitmap->table, bitmap->last, - bitmap->max, cnt, align); - if (obj >= bitmap->max) { - bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) - & bitmap->mask; - obj = find_aligned_range(bitmap->table, 0, bitmap->max, - cnt, align); - } - - if (obj < bitmap->max) { - for (i = 0; i < cnt; i++) - set_bit(obj + i, bitmap->table); - if (obj == bitmap->last) { - bitmap->last = (obj + cnt); - if (bitmap->last >= bitmap->max) - bitmap->last = 0; - } - obj |= bitmap->top; - } else - obj = -1; - - spin_unlock(&bitmap->lock); - - return obj; -} - -void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) -{ - u32 i; - - obj &= bitmap->max + bitmap->reserved_top - 1; + obj &= bitmap->max - 1; spin_lock(&bitmap->lock); - for (i = 0; i < cnt; i++) - clear_bit(obj + i, bitmap->table); + clear_bit(obj, bitmap->table); bitmap->last = min(bitmap->last, obj); - bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) - & bitmap->mask; + bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; spin_unlock(&bitmap->lock); } -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, - u32 reserved_bot, u32 reserved_top) +int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved) { int i; @@ -162,16 +85,14 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, bitmap->last = 0; bitmap->top = 0; - bitmap->max = num - reserved_top; + bitmap->max = num; bitmap->mask = mask; - bitmap->reserved_top = reserved_top; spin_lock_init(&bitmap->lock); - bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * - sizeof (long), GFP_KERNEL); + bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL); if (!bitmap->table) return -ENOMEM; - for (i = 0; i < reserved_bot; ++i) + for (i = 0; i < reserved; ++i) set_bit(i, bitmap->table); return 0; diff --git a/trunk/drivers/net/mlx4/cq.c b/trunk/drivers/net/mlx4/cq.c index b7ad2829d67e..9bb50e3f8974 100644 --- a/trunk/drivers/net/mlx4/cq.c +++ b/trunk/drivers/net/mlx4/cq.c @@ -300,7 +300,7 @@ int mlx4_init_cq_table(struct mlx4_dev *dev) INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC); err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs, - dev->caps.num_cqs - 1, dev->caps.reserved_cqs, 0); + dev->caps.num_cqs - 1, dev->caps.reserved_cqs); if (err) return err; diff --git a/trunk/drivers/net/mlx4/en_cq.c b/trunk/drivers/net/mlx4/en_cq.c deleted file mode 100644 index 1368a8010af4..000000000000 --- a/trunk/drivers/net/mlx4/en_cq.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include - -#include "mlx4_en.h" - -static void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event) -{ - return; -} - - -int mlx4_en_create_cq(struct mlx4_en_priv *priv, - struct mlx4_en_cq *cq, - int entries, int ring, enum cq_type mode) -{ - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - cq->size = entries; - if (mode == RX) - cq->buf_size = cq->size * sizeof(struct mlx4_cqe); - else - cq->buf_size = sizeof(struct mlx4_cqe); - - cq->ring = ring; - cq->is_tx = mode; - spin_lock_init(&cq->lock); - - err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres, - cq->buf_size, 2 * PAGE_SIZE); - if (err) - return err; - - err = mlx4_en_map_buffer(&cq->wqres.buf); - if (err) - mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); - - return err; -} - -int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) -{ - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - cq->dev = mdev->pndev[priv->port]; - cq->mcq.set_ci_db = cq->wqres.db.db; - cq->mcq.arm_db = cq->wqres.db.db + 1; - *cq->mcq.set_ci_db = 0; - *cq->mcq.arm_db = 0; - cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf; - memset(cq->buf, 0, cq->buf_size); - - err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, - cq->wqres.db.dma, &cq->mcq, cq->is_tx); - if (err) - return err; - - cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq; - cq->mcq.event = mlx4_en_cq_event; - - if (cq->is_tx) { - init_timer(&cq->timer); - cq->timer.function = mlx4_en_poll_tx_cq; - cq->timer.data = (unsigned long) cq; - } else { - netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq, 64); - napi_enable(&cq->napi); - } - - return 0; -} - -void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - mlx4_en_unmap_buffer(&cq->wqres.buf); - mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); - cq->buf_size = 0; - cq->buf = NULL; -} - -void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - if (cq->is_tx) - del_timer(&cq->timer); - else - napi_disable(&cq->napi); - - mlx4_cq_free(mdev->dev, &cq->mcq); -} - -/* Set rx cq moderation parameters */ -int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) -{ - return mlx4_cq_modify(priv->mdev->dev, &cq->mcq, - cq->moder_cnt, cq->moder_time); -} - -int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) -{ - cq->armed = 1; - mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map, - &priv->mdev->uar_lock); - - return 0; -} - - diff --git a/trunk/drivers/net/mlx4/en_main.c b/trunk/drivers/net/mlx4/en_main.c deleted file mode 100644 index 1b0eebf84f76..000000000000 --- a/trunk/drivers/net/mlx4/en_main.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "mlx4_en.h" - -MODULE_AUTHOR("Liran Liss, Yevgeny Petrilin"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA Ethernet driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION " ("DRV_RELDATE")"); - -static const char mlx4_en_version[] = - DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; - -static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, - enum mlx4_dev_event event, int port) -{ - struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; - struct mlx4_en_priv *priv; - - if (!mdev->pndev[port]) - return; - - priv = netdev_priv(mdev->pndev[port]); - switch (event) { - case MLX4_DEV_EVENT_PORT_UP: - case MLX4_DEV_EVENT_PORT_DOWN: - /* To prevent races, we poll the link state in a separate - task rather than changing it here */ - priv->link_state = event; - queue_work(mdev->workqueue, &priv->linkstate_task); - break; - - case MLX4_DEV_EVENT_CATASTROPHIC_ERROR: - mlx4_err(mdev, "Internal error detected, restarting device\n"); - break; - - default: - mlx4_warn(mdev, "Unhandled event: %d\n", event); - } -} - -static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) -{ - struct mlx4_en_dev *mdev = endev_ptr; - int i; - - mutex_lock(&mdev->state_lock); - mdev->device_up = false; - mutex_unlock(&mdev->state_lock); - - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) - if (mdev->pndev[i]) - mlx4_en_destroy_netdev(mdev->pndev[i]); - - flush_workqueue(mdev->workqueue); - destroy_workqueue(mdev->workqueue); - mlx4_mr_free(dev, &mdev->mr); - mlx4_uar_free(dev, &mdev->priv_uar); - mlx4_pd_free(dev, mdev->priv_pdn); - kfree(mdev); -} - -static void *mlx4_en_add(struct mlx4_dev *dev) -{ - static int mlx4_en_version_printed; - struct mlx4_en_dev *mdev; - int i; - int err; - - if (!mlx4_en_version_printed) { - printk(KERN_INFO "%s", mlx4_en_version); - mlx4_en_version_printed++; - } - - mdev = kzalloc(sizeof *mdev, GFP_KERNEL); - if (!mdev) { - dev_err(&dev->pdev->dev, "Device struct alloc failed, " - "aborting.\n"); - err = -ENOMEM; - goto err_free_res; - } - - if (mlx4_pd_alloc(dev, &mdev->priv_pdn)) - goto err_free_dev; - - if (mlx4_uar_alloc(dev, &mdev->priv_uar)) - goto err_pd; - - mdev->uar_map = ioremap(mdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!mdev->uar_map) - goto err_uar; - spin_lock_init(&mdev->uar_lock); - - mdev->dev = dev; - mdev->dma_device = &(dev->pdev->dev); - mdev->pdev = dev->pdev; - mdev->device_up = false; - - mdev->LSO_support = !!(dev->caps.flags & (1 << 15)); - if (!mdev->LSO_support) - mlx4_warn(mdev, "LSO not supported, please upgrade to later " - "FW version to enable LSO\n"); - - if (mlx4_mr_alloc(mdev->dev, mdev->priv_pdn, 0, ~0ull, - MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ, - 0, 0, &mdev->mr)) { - mlx4_err(mdev, "Failed allocating memory region\n"); - goto err_uar; - } - if (mlx4_mr_enable(mdev->dev, &mdev->mr)) { - mlx4_err(mdev, "Failed enabling memory region\n"); - goto err_mr; - } - - /* Build device profile according to supplied module parameters */ - err = mlx4_en_get_profile(mdev); - if (err) { - mlx4_err(mdev, "Bad module parameters, aborting.\n"); - goto err_mr; - } - - /* Configure wich ports to start according to module parameters */ - mdev->port_cnt = 0; - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) - mdev->port_cnt++; - - /* If we did not receive an explicit number of Rx rings, default to - * the number of completion vectors populated by the mlx4_core */ - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { - mlx4_info(mdev, "Using %d tx rings for port:%d\n", - mdev->profile.prof[i].tx_ring_num, i); - if (!mdev->profile.prof[i].rx_ring_num) { - mdev->profile.prof[i].rx_ring_num = 1; - mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", - 1, i); - } else - mlx4_info(mdev, "Using %d rx rings for port:%d\n", - mdev->profile.prof[i].rx_ring_num, i); - } - - /* Create our own workqueue for reset/multicast tasks - * Note: we cannot use the shared workqueue because of deadlocks caused - * by the rtnl lock */ - mdev->workqueue = create_singlethread_workqueue("mlx4_en"); - if (!mdev->workqueue) { - err = -ENOMEM; - goto err_close_nic; - } - - /* At this stage all non-port specific tasks are complete: - * mark the card state as up */ - mutex_init(&mdev->state_lock); - mdev->device_up = true; - - /* Setup ports */ - - /* Create a netdev for each port */ - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { - mlx4_info(mdev, "Activating port:%d\n", i); - if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) { - mdev->pndev[i] = NULL; - goto err_free_netdev; - } - } - return mdev; - - -err_free_netdev: - mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { - if (mdev->pndev[i]) - mlx4_en_destroy_netdev(mdev->pndev[i]); - } - - mutex_lock(&mdev->state_lock); - mdev->device_up = false; - mutex_unlock(&mdev->state_lock); - flush_workqueue(mdev->workqueue); - - /* Stop event queue before we drop down to release shared SW state */ - -err_close_nic: - destroy_workqueue(mdev->workqueue); -err_mr: - mlx4_mr_free(dev, &mdev->mr); -err_uar: - mlx4_uar_free(dev, &mdev->priv_uar); -err_pd: - mlx4_pd_free(dev, mdev->priv_pdn); -err_free_dev: - kfree(mdev); -err_free_res: - return NULL; -} - -static struct mlx4_interface mlx4_en_interface = { - .add = mlx4_en_add, - .remove = mlx4_en_remove, - .event = mlx4_en_event, -}; - -static int __init mlx4_en_init(void) -{ - return mlx4_register_interface(&mlx4_en_interface); -} - -static void __exit mlx4_en_cleanup(void) -{ - mlx4_unregister_interface(&mlx4_en_interface); -} - -module_init(mlx4_en_init); -module_exit(mlx4_en_cleanup); - diff --git a/trunk/drivers/net/mlx4/en_netdev.c b/trunk/drivers/net/mlx4/en_netdev.c deleted file mode 100644 index a339afbeed38..000000000000 --- a/trunk/drivers/net/mlx4/en_netdev.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "mlx4_en.h" -#include "en_port.h" - - -static void mlx4_en_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - mlx4_dbg(HW, priv, "Registering VLAN group:%p\n", grp); - priv->vlgrp = grp; - - mutex_lock(&mdev->state_lock); - if (mdev->device_up && priv->port_up) { - err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp); - if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); - } - mutex_unlock(&mdev->state_lock); -} - -static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - if (!priv->vlgrp) - return; - - mlx4_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n", - vid, vlan_group_get_device(priv->vlgrp, vid)); - - /* Add VID to port VLAN filter */ - mutex_lock(&mdev->state_lock); - if (mdev->device_up && priv->port_up) { - err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); - if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); - } - mutex_unlock(&mdev->state_lock); -} - -static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - if (!priv->vlgrp) - return; - - mlx4_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp " - "entry:%p)\n", vid, priv->vlgrp, - vlan_group_get_device(priv->vlgrp, vid)); - vlan_group_set_device(priv->vlgrp, vid, NULL); - - /* Remove VID from port VLAN filter */ - mutex_lock(&mdev->state_lock); - if (mdev->device_up && priv->port_up) { - err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); - if (err) - mlx4_err(mdev, "Failed configuring VLAN filter\n"); - } - mutex_unlock(&mdev->state_lock); -} - -static u64 mlx4_en_mac_to_u64(u8 *addr) -{ - u64 mac = 0; - int i; - - for (i = 0; i < ETH_ALEN; i++) { - mac <<= 8; - mac |= addr[i]; - } - return mac; -} - -static int mlx4_en_set_mac(struct net_device *dev, void *addr) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - struct sockaddr *saddr = addr; - - if (!is_valid_ether_addr(saddr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); - priv->mac = mlx4_en_mac_to_u64(dev->dev_addr); - queue_work(mdev->workqueue, &priv->mac_task); - return 0; -} - -static void mlx4_en_do_set_mac(struct work_struct *work) -{ - struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, - mac_task); - struct mlx4_en_dev *mdev = priv->mdev; - int err = 0; - - mutex_lock(&mdev->state_lock); - if (priv->port_up) { - /* Remove old MAC and insert the new one */ - mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); - err = mlx4_register_mac(mdev->dev, priv->port, - priv->mac, &priv->mac_index); - if (err) - mlx4_err(mdev, "Failed changing HW MAC address\n"); - } else - mlx4_dbg(HW, priv, "Port is down, exiting...\n"); - - mutex_unlock(&mdev->state_lock); -} - -static void mlx4_en_clear_list(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct dev_mc_list *plist = priv->mc_list; - struct dev_mc_list *next; - - while (plist) { - next = plist->next; - kfree(plist); - plist = next; - } - priv->mc_list = NULL; -} - -static void mlx4_en_cache_mclist(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - struct dev_mc_list *mclist; - struct dev_mc_list *tmp; - struct dev_mc_list *plist = NULL; - - for (mclist = dev->mc_list; mclist; mclist = mclist->next) { - tmp = kmalloc(sizeof(struct dev_mc_list), GFP_ATOMIC); - if (!tmp) { - mlx4_err(mdev, "failed to allocate multicast list\n"); - mlx4_en_clear_list(dev); - return; - } - memcpy(tmp, mclist, sizeof(struct dev_mc_list)); - tmp->next = NULL; - if (plist) - plist->next = tmp; - else - priv->mc_list = tmp; - plist = tmp; - } -} - - -static void mlx4_en_set_multicast(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (!priv->port_up) - return; - - queue_work(priv->mdev->workqueue, &priv->mcast_task); -} - -static void mlx4_en_do_set_multicast(struct work_struct *work) -{ - struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, - mcast_task); - struct mlx4_en_dev *mdev = priv->mdev; - struct net_device *dev = priv->dev; - struct dev_mc_list *mclist; - u64 mcast_addr = 0; - int err; - - mutex_lock(&mdev->state_lock); - if (!mdev->device_up) { - mlx4_dbg(HW, priv, "Card is not up, ignoring " - "multicast change.\n"); - goto out; - } - if (!priv->port_up) { - mlx4_dbg(HW, priv, "Port is down, ignoring " - "multicast change.\n"); - goto out; - } - - /* - * Promsicuous mode: disable all filters - */ - - if (dev->flags & IFF_PROMISC) { - if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) { - if (netif_msg_rx_status(priv)) - mlx4_warn(mdev, "Port:%d entering promiscuous mode\n", - priv->port); - priv->flags |= MLX4_EN_FLAG_PROMISC; - - /* Enable promiscouos mode */ - err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, - priv->base_qpn, 1); - if (err) - mlx4_err(mdev, "Failed enabling " - "promiscous mode\n"); - - /* Disable port multicast filter (unconditionally) */ - err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, - 0, MLX4_MCAST_DISABLE); - if (err) - mlx4_err(mdev, "Failed disabling " - "multicast filter\n"); - - /* Disable port VLAN filter */ - err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL); - if (err) - mlx4_err(mdev, "Failed disabling " - "VLAN filter\n"); - } - goto out; - } - - /* - * Not in promiscous mode - */ - - if (priv->flags & MLX4_EN_FLAG_PROMISC) { - if (netif_msg_rx_status(priv)) - mlx4_warn(mdev, "Port:%d leaving promiscuous mode\n", - priv->port); - priv->flags &= ~MLX4_EN_FLAG_PROMISC; - - /* Disable promiscouos mode */ - err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, - priv->base_qpn, 0); - if (err) - mlx4_err(mdev, "Failed disabling promiscous mode\n"); - - /* Enable port VLAN filter */ - err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); - if (err) - mlx4_err(mdev, "Failed enabling VLAN filter\n"); - } - - /* Enable/disable the multicast filter according to IFF_ALLMULTI */ - if (dev->flags & IFF_ALLMULTI) { - err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, - 0, MLX4_MCAST_DISABLE); - if (err) - mlx4_err(mdev, "Failed disabling multicast filter\n"); - } else { - err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, - 0, MLX4_MCAST_DISABLE); - if (err) - mlx4_err(mdev, "Failed disabling multicast filter\n"); - - /* Flush mcast filter and init it with broadcast address */ - mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST, - 1, MLX4_MCAST_CONFIG); - - /* Update multicast list - we cache all addresses so they won't - * change while HW is updated holding the command semaphor */ - netif_tx_lock_bh(dev); - mlx4_en_cache_mclist(dev); - netif_tx_unlock_bh(dev); - for (mclist = priv->mc_list; mclist; mclist = mclist->next) { - mcast_addr = mlx4_en_mac_to_u64(mclist->dmi_addr); - mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, - mcast_addr, 0, MLX4_MCAST_CONFIG); - } - err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, - 0, MLX4_MCAST_ENABLE); - if (err) - mlx4_err(mdev, "Failed enabling multicast filter\n"); - - mlx4_en_clear_list(dev); - } -out: - mutex_unlock(&mdev->state_lock); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void mlx4_en_netpoll(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_cq *cq; - unsigned long flags; - int i; - - for (i = 0; i < priv->rx_ring_num; i++) { - cq = &priv->rx_cq[i]; - spin_lock_irqsave(&cq->lock, flags); - napi_synchronize(&cq->napi); - mlx4_en_process_rx_cq(dev, cq, 0); - spin_unlock_irqrestore(&cq->lock, flags); - } -} -#endif - -static void mlx4_en_tx_timeout(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - if (netif_msg_timer(priv)) - mlx4_warn(mdev, "Tx timeout called on port:%d\n", priv->port); - - if (netif_carrier_ok(dev)) { - priv->port_stats.tx_timeout++; - mlx4_dbg(DRV, priv, "Scheduling watchdog\n"); - queue_work(mdev->workqueue, &priv->watchdog_task); - } -} - - -static struct net_device_stats *mlx4_en_get_stats(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - spin_lock_bh(&priv->stats_lock); - memcpy(&priv->ret_stats, &priv->stats, sizeof(priv->stats)); - spin_unlock_bh(&priv->stats_lock); - - return &priv->ret_stats; -} - -static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_cq *cq; - int i; - - /* If we haven't received a specific coalescing setting - * (module param), we set the moderation paramters as follows: - * - moder_cnt is set to the number of mtu sized packets to - * satisfy our coelsing target. - * - moder_time is set to a fixed value. - */ - priv->rx_frames = (mdev->profile.rx_moder_cnt == - MLX4_EN_AUTO_CONF) ? - MLX4_EN_RX_COAL_TARGET / - priv->dev->mtu + 1 : - mdev->profile.rx_moder_cnt; - priv->rx_usecs = (mdev->profile.rx_moder_time == - MLX4_EN_AUTO_CONF) ? - MLX4_EN_RX_COAL_TIME : - mdev->profile.rx_moder_time; - mlx4_dbg(INTR, priv, "Default coalesing params for mtu:%d - " - "rx_frames:%d rx_usecs:%d\n", - priv->dev->mtu, priv->rx_frames, priv->rx_usecs); - - /* Setup cq moderation params */ - for (i = 0; i < priv->rx_ring_num; i++) { - cq = &priv->rx_cq[i]; - cq->moder_cnt = priv->rx_frames; - cq->moder_time = priv->rx_usecs; - } - - for (i = 0; i < priv->tx_ring_num; i++) { - cq = &priv->tx_cq[i]; - cq->moder_cnt = MLX4_EN_TX_COAL_PKTS; - cq->moder_time = MLX4_EN_TX_COAL_TIME; - } - - /* Reset auto-moderation params */ - priv->pkt_rate_low = MLX4_EN_RX_RATE_LOW; - priv->rx_usecs_low = MLX4_EN_RX_COAL_TIME_LOW; - priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH; - priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH; - priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL; - priv->adaptive_rx_coal = mdev->profile.auto_moder; - priv->last_moder_time = MLX4_EN_AUTO_CONF; - priv->last_moder_jiffies = 0; - priv->last_moder_packets = 0; - priv->last_moder_tx_packets = 0; - priv->last_moder_bytes = 0; -} - -static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv) -{ - unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies); - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_cq *cq; - unsigned long packets; - unsigned long rate; - unsigned long avg_pkt_size; - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long tx_packets; - unsigned long tx_pkt_diff; - unsigned long rx_pkt_diff; - int moder_time; - int i, err; - - if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ) - return; - - spin_lock_bh(&priv->stats_lock); - rx_packets = priv->stats.rx_packets; - rx_bytes = priv->stats.rx_bytes; - tx_packets = priv->stats.tx_packets; - spin_unlock_bh(&priv->stats_lock); - - if (!priv->last_moder_jiffies || !period) - goto out; - - tx_pkt_diff = ((unsigned long) (tx_packets - - priv->last_moder_tx_packets)); - rx_pkt_diff = ((unsigned long) (rx_packets - - priv->last_moder_packets)); - packets = max(tx_pkt_diff, rx_pkt_diff); - rate = packets * HZ / period; - avg_pkt_size = packets ? ((unsigned long) (rx_bytes - - priv->last_moder_bytes)) / packets : 0; - - /* Apply auto-moderation only when packet rate exceeds a rate that - * it matters */ - if (rate > MLX4_EN_RX_RATE_THRESH) { - /* If tx and rx packet rates are not balanced, assume that - * traffic is mainly BW bound and apply maximum moderation. - * Otherwise, moderate according to packet rate */ - if (2 * tx_pkt_diff > 3 * rx_pkt_diff || - 2 * rx_pkt_diff > 3 * tx_pkt_diff) { - moder_time = priv->rx_usecs_high; - } else { - if (rate < priv->pkt_rate_low) - moder_time = priv->rx_usecs_low; - else if (rate > priv->pkt_rate_high) - moder_time = priv->rx_usecs_high; - else - moder_time = (rate - priv->pkt_rate_low) * - (priv->rx_usecs_high - priv->rx_usecs_low) / - (priv->pkt_rate_high - priv->pkt_rate_low) + - priv->rx_usecs_low; - } - } else { - /* When packet rate is low, use default moderation rather than - * 0 to prevent interrupt storms if traffic suddenly increases */ - moder_time = priv->rx_usecs; - } - - mlx4_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n", - tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period); - - mlx4_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu " - "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n", - priv->last_moder_time, moder_time, period, packets, - avg_pkt_size, rate); - - if (moder_time != priv->last_moder_time) { - priv->last_moder_time = moder_time; - for (i = 0; i < priv->rx_ring_num; i++) { - cq = &priv->rx_cq[i]; - cq->moder_time = moder_time; - err = mlx4_en_set_cq_moder(priv, cq); - if (err) { - mlx4_err(mdev, "Failed modifying moderation for cq:%d " - "on port:%d\n", i, priv->port); - break; - } - } - } - -out: - priv->last_moder_packets = rx_packets; - priv->last_moder_tx_packets = tx_packets; - priv->last_moder_bytes = rx_bytes; - priv->last_moder_jiffies = jiffies; -} - -static void mlx4_en_do_get_stats(struct work_struct *work) -{ - struct delayed_work *delay = container_of(work, struct delayed_work, work); - struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv, - stats_task); - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0); - if (err) - mlx4_dbg(HW, priv, "Could not update stats for " - "port:%d\n", priv->port); - - mutex_lock(&mdev->state_lock); - if (mdev->device_up) { - if (priv->port_up) - mlx4_en_auto_moderation(priv); - - queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); - } - mutex_unlock(&mdev->state_lock); -} - -static void mlx4_en_linkstate(struct work_struct *work) -{ - struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, - linkstate_task); - struct mlx4_en_dev *mdev = priv->mdev; - int linkstate = priv->link_state; - - mutex_lock(&mdev->state_lock); - /* If observable port state changed set carrier state and - * report to system log */ - if (priv->last_link_state != linkstate) { - if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) { - if (netif_msg_link(priv)) - mlx4_info(mdev, "Port %d - link down\n", priv->port); - netif_carrier_off(priv->dev); - } else { - if (netif_msg_link(priv)) - mlx4_info(mdev, "Port %d - link up\n", priv->port); - netif_carrier_on(priv->dev); - } - } - priv->last_link_state = linkstate; - mutex_unlock(&mdev->state_lock); -} - - -static int mlx4_en_start_port(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_cq *cq; - struct mlx4_en_tx_ring *tx_ring; - struct mlx4_en_rx_ring *rx_ring; - int rx_index = 0; - int tx_index = 0; - u16 stride; - int err = 0; - int i; - int j; - - if (priv->port_up) { - mlx4_dbg(DRV, priv, "start port called while port already up\n"); - return 0; - } - - /* Calculate Rx buf size */ - dev->mtu = min(dev->mtu, priv->max_mtu); - mlx4_en_calc_rx_buf(dev); - mlx4_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size); - stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + - DS_SIZE * priv->num_frags); - /* Configure rx cq's and rings */ - for (i = 0; i < priv->rx_ring_num; i++) { - cq = &priv->rx_cq[i]; - rx_ring = &priv->rx_ring[i]; - - err = mlx4_en_activate_cq(priv, cq); - if (err) { - mlx4_err(mdev, "Failed activating Rx CQ\n"); - goto rx_err; - } - for (j = 0; j < cq->size; j++) - cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; - err = mlx4_en_set_cq_moder(priv, cq); - if (err) { - mlx4_err(mdev, "Failed setting cq moderation parameters"); - mlx4_en_deactivate_cq(priv, cq); - goto cq_err; - } - mlx4_en_arm_cq(priv, cq); - - ++rx_index; - } - - err = mlx4_en_activate_rx_rings(priv); - if (err) { - mlx4_err(mdev, "Failed to activate RX rings\n"); - goto cq_err; - } - - err = mlx4_en_config_rss_steer(priv); - if (err) { - mlx4_err(mdev, "Failed configuring rss steering\n"); - goto rx_err; - } - - /* Configure tx cq's and rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - /* Configure cq */ - cq = &priv->tx_cq[i]; - err = mlx4_en_activate_cq(priv, cq); - if (err) { - mlx4_err(mdev, "Failed allocating Tx CQ\n"); - goto tx_err; - } - err = mlx4_en_set_cq_moder(priv, cq); - if (err) { - mlx4_err(mdev, "Failed setting cq moderation parameters"); - mlx4_en_deactivate_cq(priv, cq); - goto tx_err; - } - mlx4_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i); - cq->buf->wqe_index = cpu_to_be16(0xffff); - - /* Configure ring */ - tx_ring = &priv->tx_ring[i]; - err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn, - priv->rx_ring[0].srq.srqn); - if (err) { - mlx4_err(mdev, "Failed allocating Tx ring\n"); - mlx4_en_deactivate_cq(priv, cq); - goto tx_err; - } - /* Set initial ownership of all Tx TXBBs to SW (1) */ - for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE) - *((u32 *) (tx_ring->buf + j)) = 0xffffffff; - ++tx_index; - } - - /* Configure port */ - err = mlx4_SET_PORT_general(mdev->dev, priv->port, - priv->rx_skb_size + ETH_FCS_LEN, - mdev->profile.tx_pause, - mdev->profile.tx_ppp, - mdev->profile.rx_pause, - mdev->profile.rx_ppp); - if (err) { - mlx4_err(mdev, "Failed setting port general configurations" - " for port %d, with error %d\n", priv->port, err); - goto tx_err; - } - /* Set default qp number */ - err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0); - if (err) { - mlx4_err(mdev, "Failed setting default qp numbers\n"); - goto tx_err; - } - /* Set port mac number */ - mlx4_dbg(DRV, priv, "Setting mac for port %d\n", priv->port); - err = mlx4_register_mac(mdev->dev, priv->port, - priv->mac, &priv->mac_index); - if (err) { - mlx4_err(mdev, "Failed setting port mac\n"); - goto tx_err; - } - - /* Init port */ - mlx4_dbg(HW, priv, "Initializing port\n"); - err = mlx4_INIT_PORT(mdev->dev, priv->port); - if (err) { - mlx4_err(mdev, "Failed Initializing port\n"); - goto mac_err; - } - - /* Schedule multicast task to populate multicast list */ - queue_work(mdev->workqueue, &priv->mcast_task); - - priv->port_up = true; - netif_start_queue(dev); - return 0; - -mac_err: - mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); -tx_err: - while (tx_index--) { - mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]); - mlx4_en_deactivate_cq(priv, &priv->tx_cq[tx_index]); - } - - mlx4_en_release_rss_steer(priv); -rx_err: - for (i = 0; i < priv->rx_ring_num; i++) - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[rx_index]); -cq_err: - while (rx_index--) - mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); - - return err; /* need to close devices */ -} - - -static void mlx4_en_stop_port(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int i; - - if (!priv->port_up) { - mlx4_dbg(DRV, priv, "stop port (%d) called while port already down\n", - priv->port); - return; - } - netif_stop_queue(dev); - - /* Synchronize with tx routine */ - netif_tx_lock_bh(dev); - priv->port_up = false; - netif_tx_unlock_bh(dev); - - /* close port*/ - mlx4_CLOSE_PORT(mdev->dev, priv->port); - - /* Unregister Mac address for the port */ - mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); - - /* Free TX Rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]); - mlx4_en_deactivate_cq(priv, &priv->tx_cq[i]); - } - msleep(10); - - for (i = 0; i < priv->tx_ring_num; i++) - mlx4_en_free_tx_buf(dev, &priv->tx_ring[i]); - - /* Free RSS qps */ - mlx4_en_release_rss_steer(priv); - - /* Free RX Rings */ - for (i = 0; i < priv->rx_ring_num; i++) { - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); - while (test_bit(NAPI_STATE_SCHED, &priv->rx_cq[i].napi.state)) - msleep(1); - mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]); - } -} - -static void mlx4_en_restart(struct work_struct *work) -{ - struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, - watchdog_task); - struct mlx4_en_dev *mdev = priv->mdev; - struct net_device *dev = priv->dev; - - mlx4_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port); - mlx4_en_stop_port(dev); - if (mlx4_en_start_port(dev)) - mlx4_err(mdev, "Failed restarting port %d\n", priv->port); -} - - -static int mlx4_en_open(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int i; - int err = 0; - - mutex_lock(&mdev->state_lock); - - if (!mdev->device_up) { - mlx4_err(mdev, "Cannot open - device down/disabled\n"); - err = -EBUSY; - goto out; - } - - /* Reset HW statistics and performance counters */ - if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1)) - mlx4_dbg(HW, priv, "Failed dumping statistics\n"); - - memset(&priv->stats, 0, sizeof(priv->stats)); - memset(&priv->pstats, 0, sizeof(priv->pstats)); - - for (i = 0; i < priv->tx_ring_num; i++) { - priv->tx_ring[i].bytes = 0; - priv->tx_ring[i].packets = 0; - } - for (i = 0; i < priv->rx_ring_num; i++) { - priv->rx_ring[i].bytes = 0; - priv->rx_ring[i].packets = 0; - } - - mlx4_en_set_default_moderation(priv); - err = mlx4_en_start_port(dev); - if (err) - mlx4_err(mdev, "Failed starting port:%d\n", priv->port); - -out: - mutex_unlock(&mdev->state_lock); - return err; -} - - -static int mlx4_en_close(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - if (netif_msg_ifdown(priv)) - mlx4_info(mdev, "Close called for port:%d\n", priv->port); - - mutex_lock(&mdev->state_lock); - - mlx4_en_stop_port(dev); - netif_carrier_off(dev); - - mutex_unlock(&mdev->state_lock); - return 0; -} - -static void mlx4_en_free_resources(struct mlx4_en_priv *priv) -{ - int i; - - for (i = 0; i < priv->tx_ring_num; i++) { - if (priv->tx_ring[i].tx_info) - mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]); - if (priv->tx_cq[i].buf) - mlx4_en_destroy_cq(priv, &priv->tx_cq[i]); - } - - for (i = 0; i < priv->rx_ring_num; i++) { - if (priv->rx_ring[i].rx_info) - mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]); - if (priv->rx_cq[i].buf) - mlx4_en_destroy_cq(priv, &priv->rx_cq[i]); - } -} - -static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_port_profile *prof = priv->prof; - int i; - - /* Create tx Rings */ - for (i = 0; i < priv->tx_ring_num; i++) { - if (mlx4_en_create_cq(priv, &priv->tx_cq[i], - prof->tx_ring_size, i, TX)) - goto err; - - if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], - prof->tx_ring_size, TXBB_SIZE)) - goto err; - } - - /* Create rx Rings */ - for (i = 0; i < priv->rx_ring_num; i++) { - if (mlx4_en_create_cq(priv, &priv->rx_cq[i], - prof->rx_ring_size, i, RX)) - goto err; - - if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i], - prof->rx_ring_size, priv->stride)) - goto err; - } - - return 0; - -err: - mlx4_err(mdev, "Failed to allocate NIC resources\n"); - return -ENOMEM; -} - - -void mlx4_en_destroy_netdev(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - mlx4_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); - - /* Unregister device - this will close the port if it was up */ - if (priv->registered) - unregister_netdev(dev); - - if (priv->allocated) - mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE); - - cancel_delayed_work(&priv->stats_task); - cancel_delayed_work(&priv->refill_task); - /* flush any pending task for this netdev */ - flush_workqueue(mdev->workqueue); - - /* Detach the netdev so tasks would not attempt to access it */ - mutex_lock(&mdev->state_lock); - mdev->pndev[priv->port] = NULL; - mutex_unlock(&mdev->state_lock); - - mlx4_en_free_resources(priv); - free_netdev(dev); -} - -static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int err = 0; - - mlx4_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n", - dev->mtu, new_mtu); - - if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) { - mlx4_err(mdev, "Bad MTU size:%d.\n", new_mtu); - return -EPERM; - } - dev->mtu = new_mtu; - - if (netif_running(dev)) { - mutex_lock(&mdev->state_lock); - if (!mdev->device_up) { - /* NIC is probably restarting - let watchdog task reset - * the port */ - mlx4_dbg(DRV, priv, "Change MTU called with card down!?\n"); - } else { - mlx4_en_stop_port(dev); - mlx4_en_set_default_moderation(priv); - err = mlx4_en_start_port(dev); - if (err) { - mlx4_err(mdev, "Failed restarting port:%d\n", - priv->port); - queue_work(mdev->workqueue, &priv->watchdog_task); - } - } - mutex_unlock(&mdev->state_lock); - } - return 0; -} - -int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, - struct mlx4_en_port_profile *prof) -{ - struct net_device *dev; - struct mlx4_en_priv *priv; - int i; - int err; - - dev = alloc_etherdev(sizeof(struct mlx4_en_priv)); - if (dev == NULL) { - mlx4_err(mdev, "Net device allocation failed\n"); - return -ENOMEM; - } - - SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev); - - /* - * Initialize driver private data - */ - - priv = netdev_priv(dev); - memset(priv, 0, sizeof(struct mlx4_en_priv)); - priv->dev = dev; - priv->mdev = mdev; - priv->prof = prof; - priv->port = port; - priv->port_up = false; - priv->rx_csum = 1; - priv->flags = prof->flags; - priv->tx_ring_num = prof->tx_ring_num; - priv->rx_ring_num = prof->rx_ring_num; - priv->mc_list = NULL; - priv->mac_index = -1; - priv->msg_enable = MLX4_EN_MSG_LEVEL; - spin_lock_init(&priv->stats_lock); - INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast); - INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac); - INIT_DELAYED_WORK(&priv->refill_task, mlx4_en_rx_refill); - INIT_WORK(&priv->watchdog_task, mlx4_en_restart); - INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); - INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); - - /* Query for default mac and max mtu */ - priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port]; - priv->mac = mdev->dev->caps.def_mac[priv->port]; - if (ILLEGAL_MAC(priv->mac)) { - mlx4_err(mdev, "Port: %d, invalid mac burned: 0x%llx, quiting\n", - priv->port, priv->mac); - err = -EINVAL; - goto out; - } - - priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + - DS_SIZE * MLX4_EN_MAX_RX_FRAGS); - err = mlx4_en_alloc_resources(priv); - if (err) - goto out; - - /* Populate Rx default RSS mappings */ - mlx4_en_set_default_rss_map(priv, &priv->rss_map, priv->rx_ring_num * - RSS_FACTOR, priv->rx_ring_num); - /* Allocate page for receive rings */ - err = mlx4_alloc_hwq_res(mdev->dev, &priv->res, - MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE); - if (err) { - mlx4_err(mdev, "Failed to allocate page for rx qps\n"); - goto out; - } - priv->allocated = 1; - - /* Populate Tx priority mappings */ - mlx4_en_set_prio_map(priv, priv->tx_prio_map, prof->tx_ring_num); - - /* - * Initialize netdev entry points - */ - - dev->open = &mlx4_en_open; - dev->stop = &mlx4_en_close; - dev->hard_start_xmit = &mlx4_en_xmit; - dev->get_stats = &mlx4_en_get_stats; - dev->set_multicast_list = &mlx4_en_set_multicast; - dev->set_mac_address = &mlx4_en_set_mac; - dev->change_mtu = &mlx4_en_change_mtu; - dev->tx_timeout = &mlx4_en_tx_timeout; - dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT; - dev->vlan_rx_register = mlx4_en_vlan_rx_register; - dev->vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = mlx4_en_netpoll; -#endif - SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops); - - /* Set defualt MAC */ - dev->addr_len = ETH_ALEN; - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[ETH_ALEN - 1 - i] = - (u8) (priv->mac >> (8 * i)); - - /* - * Set driver features - */ - dev->features |= NETIF_F_SG; - dev->features |= NETIF_F_HW_CSUM; - dev->features |= NETIF_F_HIGHDMA; - dev->features |= NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; - if (mdev->profile.num_lro) - dev->features |= NETIF_F_LRO; - if (mdev->LSO_support) { - dev->features |= NETIF_F_TSO; - dev->features |= NETIF_F_TSO6; - } - - mdev->pndev[port] = dev; - - netif_carrier_off(dev); - err = register_netdev(dev); - if (err) { - mlx4_err(mdev, "Netdev registration failed\n"); - goto out; - } - priv->registered = 1; - queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); - return 0; - -out: - mlx4_en_destroy_netdev(dev); - return err; -} - diff --git a/trunk/drivers/net/mlx4/en_params.c b/trunk/drivers/net/mlx4/en_params.c deleted file mode 100644 index c2e69b1bcd0a..000000000000 --- a/trunk/drivers/net/mlx4/en_params.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include - -#include "mlx4_en.h" -#include "en_port.h" - -#define MLX4_EN_PARM_INT(X, def_val, desc) \ - static unsigned int X = def_val;\ - module_param(X , uint, 0444); \ - MODULE_PARM_DESC(X, desc); - - -/* - * Device scope module parameters - */ - - -/* Use a XOR rathern than Toeplitz hash function for RSS */ -MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS"); - -/* RSS hash type mask - default to */ -MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask"); - -/* Number of LRO sessions per Rx ring (rounded up to a power of two) */ -MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS, - "Number of LRO sessions per ring or disabled (0)"); - -/* Priority pausing */ -MLX4_EN_PARM_INT(pptx, MLX4_EN_DEF_TX_PAUSE, - "Pause policy on TX: 0 never generate pause frames " - "1 generate pause frames according to RX buffer threshold"); -MLX4_EN_PARM_INT(pprx, MLX4_EN_DEF_RX_PAUSE, - "Pause policy on RX: 0 ignore received pause frames " - "1 respect received pause frames"); -MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." - " Per priority bit mask"); -MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]." - " Per priority bit mask"); - -/* Interrupt moderation tunning */ -MLX4_EN_PARM_INT(rx_moder_cnt, MLX4_EN_AUTO_CONF, - "Max coalesced descriptors for Rx interrupt moderation"); -MLX4_EN_PARM_INT(rx_moder_time, MLX4_EN_AUTO_CONF, - "Timeout following last packet for Rx interrupt moderation"); -MLX4_EN_PARM_INT(auto_moder, 1, "Enable dynamic interrupt moderation"); - -MLX4_EN_PARM_INT(rx_ring_num1, 0, "Number or Rx rings for port 1 (0 = #cores)"); -MLX4_EN_PARM_INT(rx_ring_num2, 0, "Number or Rx rings for port 2 (0 = #cores)"); - -MLX4_EN_PARM_INT(tx_ring_size1, MLX4_EN_AUTO_CONF, "Tx ring size for port 1"); -MLX4_EN_PARM_INT(tx_ring_size2, MLX4_EN_AUTO_CONF, "Tx ring size for port 2"); -MLX4_EN_PARM_INT(rx_ring_size1, MLX4_EN_AUTO_CONF, "Rx ring size for port 1"); -MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); - - -int mlx4_en_get_profile(struct mlx4_en_dev *mdev) -{ - struct mlx4_en_profile *params = &mdev->profile; - - params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); - params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); - params->auto_moder = auto_moder; - params->rss_xor = (rss_xor != 0); - params->rss_mask = rss_mask & 0x1f; - params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); - params->rx_pause = pprx; - params->rx_ppp = pfcrx; - params->tx_pause = pptx; - params->tx_ppp = pfctx; - if (params->rx_ppp || params->tx_ppp) { - params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; - params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; - } else { - params->prof[1].tx_ring_num = 1; - params->prof[2].tx_ring_num = 1; - } - params->prof[1].rx_ring_num = min_t(int, rx_ring_num1, MAX_RX_RINGS); - params->prof[2].rx_ring_num = min_t(int, rx_ring_num2, MAX_RX_RINGS); - - if (tx_ring_size1 == MLX4_EN_AUTO_CONF) - tx_ring_size1 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[1].tx_ring_size = - (tx_ring_size1 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size1); - - if (tx_ring_size2 == MLX4_EN_AUTO_CONF) - tx_ring_size2 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[2].tx_ring_size = - (tx_ring_size2 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size2); - - if (rx_ring_size1 == MLX4_EN_AUTO_CONF) - rx_ring_size1 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[1].rx_ring_size = - (rx_ring_size1 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size1); - - if (rx_ring_size2 == MLX4_EN_AUTO_CONF) - rx_ring_size2 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[2].rx_ring_size = - (rx_ring_size2 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size2); - return 0; -} - - -/* - * Ethtool support - */ - -static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv) -{ - int i; - - priv->port_stats.lro_aggregated = 0; - priv->port_stats.lro_flushed = 0; - priv->port_stats.lro_no_desc = 0; - - for (i = 0; i < priv->rx_ring_num; i++) { - priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated; - priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed; - priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc; - } -} - -static void -mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id); - strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32); - sprintf(drvinfo->fw_version, "%d.%d.%d", - (u16) (mdev->dev->caps.fw_ver >> 32), - (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff), - (u16) (mdev->dev->caps.fw_ver & 0xffff)); - strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32); - drvinfo->n_stats = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - -static u32 mlx4_en_get_tso(struct net_device *dev) -{ - return (dev->features & NETIF_F_TSO) != 0; -} - -static int mlx4_en_set_tso(struct net_device *dev, u32 data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (data) { - if (!priv->mdev->LSO_support) - return -EPERM; - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - } else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - return 0; -} - -static u32 mlx4_en_get_rx_csum(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - return priv->rx_csum; -} - -static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - priv->rx_csum = (data != 0); - return 0; -} - -static const char main_strings[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", - - /* port statistics */ - "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets", - "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed", - "rx_csum_good", "rx_csum_none", "tx_chksum_offload", - - /* packet statistics */ - "broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3", - "rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0", - "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5", - "tx_prio_6", "tx_prio_7", -}; -#define NUM_MAIN_STATS 21 -#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS) - -static u32 mlx4_en_get_msglevel(struct net_device *dev) -{ - return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable; -} - -static void mlx4_en_set_msglevel(struct net_device *dev, u32 val) -{ - ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val; -} - -static void mlx4_en_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - wol->supported = 0; - wol->wolopts = 0; - - return; -} - -static int mlx4_en_get_sset_count(struct net_device *dev, int sset) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - if (sset != ETH_SS_STATS) - return -EOPNOTSUPP; - - return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2; -} - -static void mlx4_en_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int index = 0; - int i; - - spin_lock_bh(&priv->stats_lock); - - mlx4_en_update_lro_stats(priv); - - for (i = 0; i < NUM_MAIN_STATS; i++) - data[index++] = ((unsigned long *) &priv->stats)[i]; - for (i = 0; i < NUM_PORT_STATS; i++) - data[index++] = ((unsigned long *) &priv->port_stats)[i]; - for (i = 0; i < priv->tx_ring_num; i++) { - data[index++] = priv->tx_ring[i].packets; - data[index++] = priv->tx_ring[i].bytes; - } - for (i = 0; i < priv->rx_ring_num; i++) { - data[index++] = priv->rx_ring[i].packets; - data[index++] = priv->rx_ring[i].bytes; - } - for (i = 0; i < NUM_PKT_STATS; i++) - data[index++] = ((unsigned long *) &priv->pkstats)[i]; - spin_unlock_bh(&priv->stats_lock); - -} - -static void mlx4_en_get_strings(struct net_device *dev, - uint32_t stringset, uint8_t *data) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int index = 0; - int i; - - if (stringset != ETH_SS_STATS) - return; - - /* Add main counters */ - for (i = 0; i < NUM_MAIN_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); - for (i = 0; i < NUM_PORT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, - main_strings[i + NUM_MAIN_STATS]); - for (i = 0; i < priv->tx_ring_num; i++) { - sprintf(data + (index++) * ETH_GSTRING_LEN, - "tx%d_packets", i); - sprintf(data + (index++) * ETH_GSTRING_LEN, - "tx%d_bytes", i); - } - for (i = 0; i < priv->rx_ring_num; i++) { - sprintf(data + (index++) * ETH_GSTRING_LEN, - "rx%d_packets", i); - sprintf(data + (index++) * ETH_GSTRING_LEN, - "rx%d_bytes", i); - } - for (i = 0; i < NUM_PKT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, - main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]); -} - -static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - cmd->autoneg = AUTONEG_DISABLE; - cmd->supported = SUPPORTED_10000baseT_Full; - cmd->advertising = SUPPORTED_10000baseT_Full; - if (netif_carrier_ok(dev)) { - cmd->speed = SPEED_10000; - cmd->duplex = DUPLEX_FULL; - } else { - cmd->speed = -1; - cmd->duplex = -1; - } - return 0; -} - -static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - if ((cmd->autoneg == AUTONEG_ENABLE) || - (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL)) - return -EINVAL; - - /* Nothing to change */ - return 0; -} - -static int mlx4_en_get_coalesce(struct net_device *dev, - struct ethtool_coalesce *coal) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - - coal->tx_coalesce_usecs = 0; - coal->tx_max_coalesced_frames = 0; - coal->rx_coalesce_usecs = priv->rx_usecs; - coal->rx_max_coalesced_frames = priv->rx_frames; - - coal->pkt_rate_low = priv->pkt_rate_low; - coal->rx_coalesce_usecs_low = priv->rx_usecs_low; - coal->pkt_rate_high = priv->pkt_rate_high; - coal->rx_coalesce_usecs_high = priv->rx_usecs_high; - coal->rate_sample_interval = priv->sample_interval; - coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal; - return 0; -} - -static int mlx4_en_set_coalesce(struct net_device *dev, - struct ethtool_coalesce *coal) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int err, i; - - priv->rx_frames = (coal->rx_max_coalesced_frames == - MLX4_EN_AUTO_CONF) ? - MLX4_EN_RX_COAL_TARGET / - priv->dev->mtu + 1 : - coal->rx_max_coalesced_frames; - priv->rx_usecs = (coal->rx_coalesce_usecs == - MLX4_EN_AUTO_CONF) ? - MLX4_EN_RX_COAL_TIME : - coal->rx_coalesce_usecs; - - /* Set adaptive coalescing params */ - priv->pkt_rate_low = coal->pkt_rate_low; - priv->rx_usecs_low = coal->rx_coalesce_usecs_low; - priv->pkt_rate_high = coal->pkt_rate_high; - priv->rx_usecs_high = coal->rx_coalesce_usecs_high; - priv->sample_interval = coal->rate_sample_interval; - priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce; - priv->last_moder_time = MLX4_EN_AUTO_CONF; - if (priv->adaptive_rx_coal) - return 0; - - for (i = 0; i < priv->rx_ring_num; i++) { - priv->rx_cq[i].moder_cnt = priv->rx_frames; - priv->rx_cq[i].moder_time = priv->rx_usecs; - err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); - if (err) - return err; - } - return 0; -} - -static int mlx4_en_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - mdev->profile.tx_pause = pause->tx_pause != 0; - mdev->profile.rx_pause = pause->rx_pause != 0; - err = mlx4_SET_PORT_general(mdev->dev, priv->port, - priv->rx_skb_size + ETH_FCS_LEN, - mdev->profile.tx_pause, - mdev->profile.tx_ppp, - mdev->profile.rx_pause, - mdev->profile.rx_ppp); - if (err) - mlx4_err(mdev, "Failed setting pause params to\n"); - - return err; -} - -static void mlx4_en_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - pause->tx_pause = mdev->profile.tx_pause; - pause->rx_pause = mdev->profile.rx_pause; -} - -static void mlx4_en_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *param) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - - memset(param, 0, sizeof(*param)); - param->rx_max_pending = mdev->dev->caps.max_rq_sg; - param->tx_max_pending = mdev->dev->caps.max_sq_sg; - param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size; - param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size; -} - -const struct ethtool_ops mlx4_en_ethtool_ops = { - .get_drvinfo = mlx4_en_get_drvinfo, - .get_settings = mlx4_en_get_settings, - .set_settings = mlx4_en_set_settings, -#ifdef NETIF_F_TSO - .get_tso = mlx4_en_get_tso, - .set_tso = mlx4_en_set_tso, -#endif - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_link = ethtool_op_get_link, - .get_rx_csum = mlx4_en_get_rx_csum, - .set_rx_csum = mlx4_en_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_ipv6_csum, - .get_strings = mlx4_en_get_strings, - .get_sset_count = mlx4_en_get_sset_count, - .get_ethtool_stats = mlx4_en_get_ethtool_stats, - .get_wol = mlx4_en_get_wol, - .get_msglevel = mlx4_en_get_msglevel, - .set_msglevel = mlx4_en_set_msglevel, - .get_coalesce = mlx4_en_get_coalesce, - .set_coalesce = mlx4_en_set_coalesce, - .get_pauseparam = mlx4_en_get_pauseparam, - .set_pauseparam = mlx4_en_set_pauseparam, - .get_ringparam = mlx4_en_get_ringparam, - .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, -}; - - - - - diff --git a/trunk/drivers/net/mlx4/en_port.c b/trunk/drivers/net/mlx4/en_port.c deleted file mode 100644 index c5a4c0389752..000000000000 --- a/trunk/drivers/net/mlx4/en_port.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - - -#include - -#include -#include - -#include "en_port.h" -#include "mlx4_en.h" - - -int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, - u64 mac, u64 clear, u8 mode) -{ - return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, - MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_set_vlan_fltr_mbox *filter; - int i; - int j; - int index = 0; - u32 entry; - int err = 0; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - filter = mailbox->buf; - if (grp) { - memset(filter, 0, sizeof *filter); - for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) { - entry = 0; - for (j = 0; j < 32; j++) - if (vlan_group_get_device(grp, index++)) - entry |= 1 << j; - filter->entry[i] = cpu_to_be32(entry); - } - } else { - /* When no vlans are configured we block all vlans */ - memset(filter, 0, sizeof(*filter)); - } - err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR, - MLX4_CMD_TIME_CLASS_B); - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - - -int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, - u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_set_port_general_context *context; - int err; - u32 in_mod; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - context = mailbox->buf; - memset(context, 0, sizeof *context); - - context->flags = SET_PORT_GEN_ALL_VALID; - context->mtu = cpu_to_be16(mtu); - context->pptx = (pptx * (!pfctx)) << 7; - context->pfctx = pfctx; - context->pprx = (pprx * (!pfcrx)) << 7; - context->pfcrx = pfcrx; - - in_mod = MLX4_SET_PORT_GENERAL << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, - u8 promisc) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_set_port_rqp_calc_context *context; - int err; - u32 in_mod; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - context = mailbox->buf; - memset(context, 0, sizeof *context); - - context->base_qpn = cpu_to_be32(base_qpn); - context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn); - context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn); - context->intra_no_vlan = 0; - context->no_vlan = MLX4_NO_VLAN_IDX; - context->intra_vlan_miss = 0; - context->vlan_miss = MLX4_VLAN_MISS_IDX; - - in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - - -int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) -{ - struct mlx4_en_stat_out_mbox *mlx4_en_stats; - struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); - struct net_device_stats *stats = &priv->stats; - struct mlx4_cmd_mailbox *mailbox; - u64 in_mod = reset << 8 | port; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - memset(mailbox->buf, 0, sizeof(*mlx4_en_stats)); - err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0, - MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B); - if (err) - goto out; - - mlx4_en_stats = mailbox->buf; - - spin_lock_bh(&priv->stats_lock); - - stats->rx_packets = be32_to_cpu(mlx4_en_stats->RTOTFRMS) - - be32_to_cpu(mlx4_en_stats->RDROP); - stats->tx_packets = be64_to_cpu(mlx4_en_stats->TTOT_prio_0) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_1) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_2) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_3) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_4) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_5) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_6) + - be64_to_cpu(mlx4_en_stats->TTOT_prio_7) + - be64_to_cpu(mlx4_en_stats->TTOT_novlan) + - be64_to_cpu(mlx4_en_stats->TTOT_loopbk); - stats->rx_bytes = be64_to_cpu(mlx4_en_stats->ROCT_prio_0) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_1) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_2) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_3) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_4) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_5) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_6) + - be64_to_cpu(mlx4_en_stats->ROCT_prio_7) + - be64_to_cpu(mlx4_en_stats->ROCT_novlan); - - stats->tx_bytes = be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_0) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_1) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_2) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_3) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_4) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_5) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_6) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_prio_7) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_novlan) + - be64_to_cpu(mlx4_en_stats->TTTLOCT_loopbk); - - stats->rx_errors = be64_to_cpu(mlx4_en_stats->PCS) + - be32_to_cpu(mlx4_en_stats->RdropLength) + - be32_to_cpu(mlx4_en_stats->RJBBR) + - be32_to_cpu(mlx4_en_stats->RCRC) + - be32_to_cpu(mlx4_en_stats->RRUNT); - stats->tx_errors = be32_to_cpu(mlx4_en_stats->TDROP); - stats->multicast = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_1) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_2) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_3) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_4) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_5) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_6) + - be64_to_cpu(mlx4_en_stats->MCAST_prio_7) + - be64_to_cpu(mlx4_en_stats->MCAST_novlan); - stats->collisions = 0; - stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength); - stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); - stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC); - stats->rx_frame_errors = 0; - stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); - stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); - stats->tx_aborted_errors = 0; - stats->tx_carrier_errors = 0; - stats->tx_fifo_errors = 0; - stats->tx_heartbeat_errors = 0; - stats->tx_window_errors = 0; - - priv->pkstats.broadcast = - be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) + - be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) + - be64_to_cpu(mlx4_en_stats->RBCAST_novlan); - priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0); - priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1); - priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2); - priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3); - priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4); - priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5); - priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6); - priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7); - priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0); - priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1); - priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2); - priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3); - priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4); - priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5); - priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6); - priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7); - spin_unlock_bh(&priv->stats_lock); - -out: - mlx4_free_cmd_mailbox(mdev->dev, mailbox); - return err; -} - diff --git a/trunk/drivers/net/mlx4/en_port.h b/trunk/drivers/net/mlx4/en_port.h deleted file mode 100644 index e6477f12beb5..000000000000 --- a/trunk/drivers/net/mlx4/en_port.h +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef _MLX4_EN_PORT_H_ -#define _MLX4_EN_PORT_H_ - - -#define SET_PORT_GEN_ALL_VALID 0x7 -#define SET_PORT_PROMISC_SHIFT 31 - -enum { - MLX4_CMD_SET_VLAN_FLTR = 0x47, - MLX4_CMD_SET_MCAST_FLTR = 0x48, - MLX4_CMD_DUMP_ETH_STATS = 0x49, -}; - -struct mlx4_set_port_general_context { - u8 reserved[3]; - u8 flags; - u16 reserved2; - __be16 mtu; - u8 pptx; - u8 pfctx; - u16 reserved3; - u8 pprx; - u8 pfcrx; - u16 reserved4; -}; - -struct mlx4_set_port_rqp_calc_context { - __be32 base_qpn; - __be32 flags; - u8 reserved[3]; - u8 mac_miss; - u8 intra_no_vlan; - u8 no_vlan; - u8 intra_vlan_miss; - u8 vlan_miss; - u8 reserved2[3]; - u8 no_vlan_prio; - __be32 promisc; - __be32 mcast; -}; - -#define VLAN_FLTR_SIZE 128 -struct mlx4_set_vlan_fltr_mbox { - __be32 entry[VLAN_FLTR_SIZE]; -}; - - -enum { - MLX4_MCAST_CONFIG = 0, - MLX4_MCAST_DISABLE = 1, - MLX4_MCAST_ENABLE = 2, -}; - - -struct mlx4_en_stat_out_mbox { - /* Received frames with a length of 64 octets */ - __be64 R64_prio_0; - __be64 R64_prio_1; - __be64 R64_prio_2; - __be64 R64_prio_3; - __be64 R64_prio_4; - __be64 R64_prio_5; - __be64 R64_prio_6; - __be64 R64_prio_7; - __be64 R64_novlan; - /* Received frames with a length of 127 octets */ - __be64 R127_prio_0; - __be64 R127_prio_1; - __be64 R127_prio_2; - __be64 R127_prio_3; - __be64 R127_prio_4; - __be64 R127_prio_5; - __be64 R127_prio_6; - __be64 R127_prio_7; - __be64 R127_novlan; - /* Received frames with a length of 255 octets */ - __be64 R255_prio_0; - __be64 R255_prio_1; - __be64 R255_prio_2; - __be64 R255_prio_3; - __be64 R255_prio_4; - __be64 R255_prio_5; - __be64 R255_prio_6; - __be64 R255_prio_7; - __be64 R255_novlan; - /* Received frames with a length of 511 octets */ - __be64 R511_prio_0; - __be64 R511_prio_1; - __be64 R511_prio_2; - __be64 R511_prio_3; - __be64 R511_prio_4; - __be64 R511_prio_5; - __be64 R511_prio_6; - __be64 R511_prio_7; - __be64 R511_novlan; - /* Received frames with a length of 1023 octets */ - __be64 R1023_prio_0; - __be64 R1023_prio_1; - __be64 R1023_prio_2; - __be64 R1023_prio_3; - __be64 R1023_prio_4; - __be64 R1023_prio_5; - __be64 R1023_prio_6; - __be64 R1023_prio_7; - __be64 R1023_novlan; - /* Received frames with a length of 1518 octets */ - __be64 R1518_prio_0; - __be64 R1518_prio_1; - __be64 R1518_prio_2; - __be64 R1518_prio_3; - __be64 R1518_prio_4; - __be64 R1518_prio_5; - __be64 R1518_prio_6; - __be64 R1518_prio_7; - __be64 R1518_novlan; - /* Received frames with a length of 1522 octets */ - __be64 R1522_prio_0; - __be64 R1522_prio_1; - __be64 R1522_prio_2; - __be64 R1522_prio_3; - __be64 R1522_prio_4; - __be64 R1522_prio_5; - __be64 R1522_prio_6; - __be64 R1522_prio_7; - __be64 R1522_novlan; - /* Received frames with a length of 1548 octets */ - __be64 R1548_prio_0; - __be64 R1548_prio_1; - __be64 R1548_prio_2; - __be64 R1548_prio_3; - __be64 R1548_prio_4; - __be64 R1548_prio_5; - __be64 R1548_prio_6; - __be64 R1548_prio_7; - __be64 R1548_novlan; - /* Received frames with a length of 1548 < octets < MTU */ - __be64 R2MTU_prio_0; - __be64 R2MTU_prio_1; - __be64 R2MTU_prio_2; - __be64 R2MTU_prio_3; - __be64 R2MTU_prio_4; - __be64 R2MTU_prio_5; - __be64 R2MTU_prio_6; - __be64 R2MTU_prio_7; - __be64 R2MTU_novlan; - /* Received frames with a length of MTU< octets and good CRC */ - __be64 RGIANT_prio_0; - __be64 RGIANT_prio_1; - __be64 RGIANT_prio_2; - __be64 RGIANT_prio_3; - __be64 RGIANT_prio_4; - __be64 RGIANT_prio_5; - __be64 RGIANT_prio_6; - __be64 RGIANT_prio_7; - __be64 RGIANT_novlan; - /* Received broadcast frames with good CRC */ - __be64 RBCAST_prio_0; - __be64 RBCAST_prio_1; - __be64 RBCAST_prio_2; - __be64 RBCAST_prio_3; - __be64 RBCAST_prio_4; - __be64 RBCAST_prio_5; - __be64 RBCAST_prio_6; - __be64 RBCAST_prio_7; - __be64 RBCAST_novlan; - /* Received multicast frames with good CRC */ - __be64 MCAST_prio_0; - __be64 MCAST_prio_1; - __be64 MCAST_prio_2; - __be64 MCAST_prio_3; - __be64 MCAST_prio_4; - __be64 MCAST_prio_5; - __be64 MCAST_prio_6; - __be64 MCAST_prio_7; - __be64 MCAST_novlan; - /* Received unicast not short or GIANT frames with good CRC */ - __be64 RTOTG_prio_0; - __be64 RTOTG_prio_1; - __be64 RTOTG_prio_2; - __be64 RTOTG_prio_3; - __be64 RTOTG_prio_4; - __be64 RTOTG_prio_5; - __be64 RTOTG_prio_6; - __be64 RTOTG_prio_7; - __be64 RTOTG_novlan; - - /* Count of total octets of received frames, includes framing characters */ - __be64 RTTLOCT_prio_0; - /* Count of total octets of received frames, not including framing - characters */ - __be64 RTTLOCT_NOFRM_prio_0; - /* Count of Total number of octets received - (only for frames without errors) */ - __be64 ROCT_prio_0; - - __be64 RTTLOCT_prio_1; - __be64 RTTLOCT_NOFRM_prio_1; - __be64 ROCT_prio_1; - - __be64 RTTLOCT_prio_2; - __be64 RTTLOCT_NOFRM_prio_2; - __be64 ROCT_prio_2; - - __be64 RTTLOCT_prio_3; - __be64 RTTLOCT_NOFRM_prio_3; - __be64 ROCT_prio_3; - - __be64 RTTLOCT_prio_4; - __be64 RTTLOCT_NOFRM_prio_4; - __be64 ROCT_prio_4; - - __be64 RTTLOCT_prio_5; - __be64 RTTLOCT_NOFRM_prio_5; - __be64 ROCT_prio_5; - - __be64 RTTLOCT_prio_6; - __be64 RTTLOCT_NOFRM_prio_6; - __be64 ROCT_prio_6; - - __be64 RTTLOCT_prio_7; - __be64 RTTLOCT_NOFRM_prio_7; - __be64 ROCT_prio_7; - - __be64 RTTLOCT_novlan; - __be64 RTTLOCT_NOFRM_novlan; - __be64 ROCT_novlan; - - /* Count of Total received frames including bad frames */ - __be64 RTOT_prio_0; - /* Count of Total number of received frames with 802.1Q encapsulation */ - __be64 R1Q_prio_0; - __be64 reserved1; - - __be64 RTOT_prio_1; - __be64 R1Q_prio_1; - __be64 reserved2; - - __be64 RTOT_prio_2; - __be64 R1Q_prio_2; - __be64 reserved3; - - __be64 RTOT_prio_3; - __be64 R1Q_prio_3; - __be64 reserved4; - - __be64 RTOT_prio_4; - __be64 R1Q_prio_4; - __be64 reserved5; - - __be64 RTOT_prio_5; - __be64 R1Q_prio_5; - __be64 reserved6; - - __be64 RTOT_prio_6; - __be64 R1Q_prio_6; - __be64 reserved7; - - __be64 RTOT_prio_7; - __be64 R1Q_prio_7; - __be64 reserved8; - - __be64 RTOT_novlan; - __be64 R1Q_novlan; - __be64 reserved9; - - /* Total number of Successfully Received Control Frames */ - __be64 RCNTL; - __be64 reserved10; - __be64 reserved11; - __be64 reserved12; - /* Count of received frames with a length/type field value between 46 - (42 for VLANtagged frames) and 1500 (also 1500 for VLAN-tagged frames), - inclusive */ - __be64 RInRangeLengthErr; - /* Count of received frames with length/type field between 1501 and 1535 - decimal, inclusive */ - __be64 ROutRangeLengthErr; - /* Count of received frames that are longer than max allowed size for - 802.3 frames (1518/1522) */ - __be64 RFrmTooLong; - /* Count frames received with PCS error */ - __be64 PCS; - - /* Transmit frames with a length of 64 octets */ - __be64 T64_prio_0; - __be64 T64_prio_1; - __be64 T64_prio_2; - __be64 T64_prio_3; - __be64 T64_prio_4; - __be64 T64_prio_5; - __be64 T64_prio_6; - __be64 T64_prio_7; - __be64 T64_novlan; - __be64 T64_loopbk; - /* Transmit frames with a length of 65 to 127 octets. */ - __be64 T127_prio_0; - __be64 T127_prio_1; - __be64 T127_prio_2; - __be64 T127_prio_3; - __be64 T127_prio_4; - __be64 T127_prio_5; - __be64 T127_prio_6; - __be64 T127_prio_7; - __be64 T127_novlan; - __be64 T127_loopbk; - /* Transmit frames with a length of 128 to 255 octets */ - __be64 T255_prio_0; - __be64 T255_prio_1; - __be64 T255_prio_2; - __be64 T255_prio_3; - __be64 T255_prio_4; - __be64 T255_prio_5; - __be64 T255_prio_6; - __be64 T255_prio_7; - __be64 T255_novlan; - __be64 T255_loopbk; - /* Transmit frames with a length of 256 to 511 octets */ - __be64 T511_prio_0; - __be64 T511_prio_1; - __be64 T511_prio_2; - __be64 T511_prio_3; - __be64 T511_prio_4; - __be64 T511_prio_5; - __be64 T511_prio_6; - __be64 T511_prio_7; - __be64 T511_novlan; - __be64 T511_loopbk; - /* Transmit frames with a length of 512 to 1023 octets */ - __be64 T1023_prio_0; - __be64 T1023_prio_1; - __be64 T1023_prio_2; - __be64 T1023_prio_3; - __be64 T1023_prio_4; - __be64 T1023_prio_5; - __be64 T1023_prio_6; - __be64 T1023_prio_7; - __be64 T1023_novlan; - __be64 T1023_loopbk; - /* Transmit frames with a length of 1024 to 1518 octets */ - __be64 T1518_prio_0; - __be64 T1518_prio_1; - __be64 T1518_prio_2; - __be64 T1518_prio_3; - __be64 T1518_prio_4; - __be64 T1518_prio_5; - __be64 T1518_prio_6; - __be64 T1518_prio_7; - __be64 T1518_novlan; - __be64 T1518_loopbk; - /* Counts transmit frames with a length of 1519 to 1522 bytes */ - __be64 T1522_prio_0; - __be64 T1522_prio_1; - __be64 T1522_prio_2; - __be64 T1522_prio_3; - __be64 T1522_prio_4; - __be64 T1522_prio_5; - __be64 T1522_prio_6; - __be64 T1522_prio_7; - __be64 T1522_novlan; - __be64 T1522_loopbk; - /* Transmit frames with a length of 1523 to 1548 octets */ - __be64 T1548_prio_0; - __be64 T1548_prio_1; - __be64 T1548_prio_2; - __be64 T1548_prio_3; - __be64 T1548_prio_4; - __be64 T1548_prio_5; - __be64 T1548_prio_6; - __be64 T1548_prio_7; - __be64 T1548_novlan; - __be64 T1548_loopbk; - /* Counts transmit frames with a length of 1549 to MTU bytes */ - __be64 T2MTU_prio_0; - __be64 T2MTU_prio_1; - __be64 T2MTU_prio_2; - __be64 T2MTU_prio_3; - __be64 T2MTU_prio_4; - __be64 T2MTU_prio_5; - __be64 T2MTU_prio_6; - __be64 T2MTU_prio_7; - __be64 T2MTU_novlan; - __be64 T2MTU_loopbk; - /* Transmit frames with a length greater than MTU octets and a good CRC. */ - __be64 TGIANT_prio_0; - __be64 TGIANT_prio_1; - __be64 TGIANT_prio_2; - __be64 TGIANT_prio_3; - __be64 TGIANT_prio_4; - __be64 TGIANT_prio_5; - __be64 TGIANT_prio_6; - __be64 TGIANT_prio_7; - __be64 TGIANT_novlan; - __be64 TGIANT_loopbk; - /* Transmit broadcast frames with a good CRC */ - __be64 TBCAST_prio_0; - __be64 TBCAST_prio_1; - __be64 TBCAST_prio_2; - __be64 TBCAST_prio_3; - __be64 TBCAST_prio_4; - __be64 TBCAST_prio_5; - __be64 TBCAST_prio_6; - __be64 TBCAST_prio_7; - __be64 TBCAST_novlan; - __be64 TBCAST_loopbk; - /* Transmit multicast frames with a good CRC */ - __be64 TMCAST_prio_0; - __be64 TMCAST_prio_1; - __be64 TMCAST_prio_2; - __be64 TMCAST_prio_3; - __be64 TMCAST_prio_4; - __be64 TMCAST_prio_5; - __be64 TMCAST_prio_6; - __be64 TMCAST_prio_7; - __be64 TMCAST_novlan; - __be64 TMCAST_loopbk; - /* Transmit good frames that are neither broadcast nor multicast */ - __be64 TTOTG_prio_0; - __be64 TTOTG_prio_1; - __be64 TTOTG_prio_2; - __be64 TTOTG_prio_3; - __be64 TTOTG_prio_4; - __be64 TTOTG_prio_5; - __be64 TTOTG_prio_6; - __be64 TTOTG_prio_7; - __be64 TTOTG_novlan; - __be64 TTOTG_loopbk; - - /* total octets of transmitted frames, including framing characters */ - __be64 TTTLOCT_prio_0; - /* total octets of transmitted frames, not including framing characters */ - __be64 TTTLOCT_NOFRM_prio_0; - /* ifOutOctets */ - __be64 TOCT_prio_0; - - __be64 TTTLOCT_prio_1; - __be64 TTTLOCT_NOFRM_prio_1; - __be64 TOCT_prio_1; - - __be64 TTTLOCT_prio_2; - __be64 TTTLOCT_NOFRM_prio_2; - __be64 TOCT_prio_2; - - __be64 TTTLOCT_prio_3; - __be64 TTTLOCT_NOFRM_prio_3; - __be64 TOCT_prio_3; - - __be64 TTTLOCT_prio_4; - __be64 TTTLOCT_NOFRM_prio_4; - __be64 TOCT_prio_4; - - __be64 TTTLOCT_prio_5; - __be64 TTTLOCT_NOFRM_prio_5; - __be64 TOCT_prio_5; - - __be64 TTTLOCT_prio_6; - __be64 TTTLOCT_NOFRM_prio_6; - __be64 TOCT_prio_6; - - __be64 TTTLOCT_prio_7; - __be64 TTTLOCT_NOFRM_prio_7; - __be64 TOCT_prio_7; - - __be64 TTTLOCT_novlan; - __be64 TTTLOCT_NOFRM_novlan; - __be64 TOCT_novlan; - - __be64 TTTLOCT_loopbk; - __be64 TTTLOCT_NOFRM_loopbk; - __be64 TOCT_loopbk; - - /* Total frames transmitted with a good CRC that are not aborted */ - __be64 TTOT_prio_0; - /* Total number of frames transmitted with 802.1Q encapsulation */ - __be64 T1Q_prio_0; - __be64 reserved13; - - __be64 TTOT_prio_1; - __be64 T1Q_prio_1; - __be64 reserved14; - - __be64 TTOT_prio_2; - __be64 T1Q_prio_2; - __be64 reserved15; - - __be64 TTOT_prio_3; - __be64 T1Q_prio_3; - __be64 reserved16; - - __be64 TTOT_prio_4; - __be64 T1Q_prio_4; - __be64 reserved17; - - __be64 TTOT_prio_5; - __be64 T1Q_prio_5; - __be64 reserved18; - - __be64 TTOT_prio_6; - __be64 T1Q_prio_6; - __be64 reserved19; - - __be64 TTOT_prio_7; - __be64 T1Q_prio_7; - __be64 reserved20; - - __be64 TTOT_novlan; - __be64 T1Q_novlan; - __be64 reserved21; - - __be64 TTOT_loopbk; - __be64 T1Q_loopbk; - __be64 reserved22; - - /* Received frames with a length greater than MTU octets and a bad CRC */ - __be32 RJBBR; - /* Received frames with a bad CRC that are not runts, jabbers, - or alignment errors */ - __be32 RCRC; - /* Received frames with SFD with a length of less than 64 octets and a - bad CRC */ - __be32 RRUNT; - /* Received frames with a length less than 64 octets and a good CRC */ - __be32 RSHORT; - /* Total Number of Received Packets Dropped */ - __be32 RDROP; - /* Drop due to overflow */ - __be32 RdropOvflw; - /* Drop due to overflow */ - __be32 RdropLength; - /* Total of good frames. Does not include frames received with - frame-too-long, FCS, or length errors */ - __be32 RTOTFRMS; - /* Total dropped Xmited packets */ - __be32 TDROP; -}; - - -#endif diff --git a/trunk/drivers/net/mlx4/en_resources.c b/trunk/drivers/net/mlx4/en_resources.c deleted file mode 100644 index a0545209e507..000000000000 --- a/trunk/drivers/net/mlx4/en_resources.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include - -#include "mlx4_en.h" - -void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, - int is_tx, int rss, int qpn, int cqn, int srqn, - struct mlx4_qp_context *context) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - memset(context, 0, sizeof *context); - context->flags = cpu_to_be32(7 << 16 | rss << 13); - context->pd = cpu_to_be32(mdev->priv_pdn); - context->mtu_msgmax = 0xff; - context->rq_size_stride = 0; - if (is_tx) - context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4); - else - context->sq_size_stride = 1; - context->usr_page = cpu_to_be32(mdev->priv_uar.index); - context->local_qpn = cpu_to_be32(qpn); - context->pri_path.ackto = 1 & 0x07; - context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6; - context->pri_path.counter_index = 0xff; - context->cqn_send = cpu_to_be32(cqn); - context->cqn_recv = cpu_to_be32(cqn); - context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2); - if (!rss) - context->srqn = cpu_to_be32(MLX4_EN_USE_SRQ | srqn); -} - - -int mlx4_en_map_buffer(struct mlx4_buf *buf) -{ - struct page **pages; - int i; - - if (BITS_PER_LONG == 64 || buf->nbufs == 1) - return 0; - - pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL); - if (!pages) - return -ENOMEM; - - for (i = 0; i < buf->nbufs; ++i) - pages[i] = virt_to_page(buf->page_list[i].buf); - - buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL); - kfree(pages); - if (!buf->direct.buf) - return -ENOMEM; - - return 0; -} - -void mlx4_en_unmap_buffer(struct mlx4_buf *buf) -{ - if (BITS_PER_LONG == 64 || buf->nbufs == 1) - return; - - vunmap(buf->direct.buf); -} diff --git a/trunk/drivers/net/mlx4/en_rx.c b/trunk/drivers/net/mlx4/en_rx.c deleted file mode 100644 index 6232227f56c3..000000000000 --- a/trunk/drivers/net/mlx4/en_rx.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "mlx4_en.h" - -static void *get_wqe(struct mlx4_en_rx_ring *ring, int n) -{ - int offset = n << ring->srq.wqe_shift; - return ring->buf + offset; -} - -static void mlx4_en_srq_event(struct mlx4_srq *srq, enum mlx4_event type) -{ - return; -} - -static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - *mac_hdr = page_address(frags->page) + frags->page_offset; - *ip_hdr = *mac_hdr + ETH_HLEN; - *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr)); - *hdr_flags = LRO_IPV4 | LRO_TCP; - - return 0; -} - -static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, - struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, - struct mlx4_en_rx_alloc *ring_alloc, - int i) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; - struct mlx4_en_rx_alloc *page_alloc = &ring_alloc[i]; - struct page *page; - dma_addr_t dma; - - if (page_alloc->offset == frag_info->last_offset) { - /* Allocate new page */ - page = alloc_pages(GFP_ATOMIC | __GFP_COMP, MLX4_EN_ALLOC_ORDER); - if (!page) - return -ENOMEM; - - skb_frags[i].page = page_alloc->page; - skb_frags[i].page_offset = page_alloc->offset; - page_alloc->page = page; - page_alloc->offset = frag_info->frag_align; - } else { - page = page_alloc->page; - get_page(page); - - skb_frags[i].page = page; - skb_frags[i].page_offset = page_alloc->offset; - page_alloc->offset += frag_info->frag_stride; - } - dma = pci_map_single(mdev->pdev, page_address(skb_frags[i].page) + - skb_frags[i].page_offset, frag_info->frag_size, - PCI_DMA_FROMDEVICE); - rx_desc->data[i].addr = cpu_to_be64(dma); - return 0; -} - -static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_rx_alloc *page_alloc; - int i; - - for (i = 0; i < priv->num_frags; i++) { - page_alloc = &ring->page_alloc[i]; - page_alloc->page = alloc_pages(GFP_ATOMIC | __GFP_COMP, - MLX4_EN_ALLOC_ORDER); - if (!page_alloc->page) - goto out; - - page_alloc->offset = priv->frag_info[i].frag_align; - mlx4_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n", - i, page_alloc->page); - } - return 0; - -out: - while (i--) { - page_alloc = &ring->page_alloc[i]; - put_page(page_alloc->page); - page_alloc->page = NULL; - } - return -ENOMEM; -} - -static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_rx_alloc *page_alloc; - int i; - - for (i = 0; i < priv->num_frags; i++) { - page_alloc = &ring->page_alloc[i]; - mlx4_dbg(DRV, priv, "Freeing allocator:%d count:%d\n", - i, page_count(page_alloc->page)); - - put_page(page_alloc->page); - page_alloc->page = NULL; - } -} - - -static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, int index) -{ - struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index; - struct skb_frag_struct *skb_frags = ring->rx_info + - (index << priv->log_rx_info); - int possible_frags; - int i; - - /* Pre-link descriptor */ - rx_desc->next.next_wqe_index = cpu_to_be16((index + 1) & ring->size_mask); - - /* Set size and memtype fields */ - for (i = 0; i < priv->num_frags; i++) { - skb_frags[i].size = priv->frag_info[i].frag_size; - rx_desc->data[i].byte_count = - cpu_to_be32(priv->frag_info[i].frag_size); - rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key); - } - - /* If the number of used fragments does not fill up the ring stride, - * remaining (unused) fragments must be padded with null address/size - * and a special memory key */ - possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE; - for (i = priv->num_frags; i < possible_frags; i++) { - rx_desc->data[i].byte_count = 0; - rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD); - rx_desc->data[i].addr = 0; - } -} - - -static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, int index) -{ - struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride); - struct skb_frag_struct *skb_frags = ring->rx_info + - (index << priv->log_rx_info); - int i; - - for (i = 0; i < priv->num_frags; i++) - if (mlx4_en_alloc_frag(priv, rx_desc, skb_frags, ring->page_alloc, i)) - goto err; - - return 0; - -err: - while (i--) - put_page(skb_frags[i].page); - return -ENOMEM; -} - -static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring) -{ - *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff); -} - -static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_rx_ring *ring; - int ring_ind; - int buf_ind; - - for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) { - for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { - ring = &priv->rx_ring[ring_ind]; - - if (mlx4_en_prepare_rx_desc(priv, ring, - ring->actual_size)) { - if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) { - mlx4_err(mdev, "Failed to allocate " - "enough rx buffers\n"); - return -ENOMEM; - } else { - if (netif_msg_rx_err(priv)) - mlx4_warn(mdev, - "Only %d buffers allocated\n", - ring->actual_size); - goto out; - } - } - ring->actual_size++; - ring->prod++; - } - } -out: - return 0; -} - -static int mlx4_en_fill_rx_buf(struct net_device *dev, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int num = 0; - int err; - - while ((u32) (ring->prod - ring->cons) < ring->actual_size) { - err = mlx4_en_prepare_rx_desc(priv, ring, ring->prod & - ring->size_mask); - if (err) { - if (netif_msg_rx_err(priv)) - mlx4_warn(priv->mdev, - "Failed preparing rx descriptor\n"); - priv->port_stats.rx_alloc_failed++; - break; - } - ++num; - ++ring->prod; - } - if ((u32) (ring->prod - ring->cons) == ring->size) - ring->full = 1; - - return num; -} - -static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct skb_frag_struct *skb_frags; - struct mlx4_en_rx_desc *rx_desc; - dma_addr_t dma; - int index; - int nr; - - mlx4_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n", - ring->cons, ring->prod); - - /* Unmap and free Rx buffers */ - BUG_ON((u32) (ring->prod - ring->cons) > ring->size); - while (ring->cons != ring->prod) { - index = ring->cons & ring->size_mask; - rx_desc = ring->buf + (index << ring->log_stride); - skb_frags = ring->rx_info + (index << priv->log_rx_info); - mlx4_dbg(DRV, priv, "Processing descriptor:%d\n", index); - - for (nr = 0; nr < priv->num_frags; nr++) { - mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr); - dma = be64_to_cpu(rx_desc->data[nr].addr); - - mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma); - pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, - PCI_DMA_FROMDEVICE); - put_page(skb_frags[nr].page); - } - ++ring->cons; - } -} - - -void mlx4_en_rx_refill(struct work_struct *work) -{ - struct delayed_work *delay = container_of(work, struct delayed_work, work); - struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv, - refill_task); - struct mlx4_en_dev *mdev = priv->mdev; - struct net_device *dev = priv->dev; - struct mlx4_en_rx_ring *ring; - int need_refill = 0; - int i; - - mutex_lock(&mdev->state_lock); - if (!mdev->device_up || !priv->port_up) - goto out; - - /* We only get here if there are no receive buffers, so we can't race - * with Rx interrupts while filling buffers */ - for (i = 0; i < priv->rx_ring_num; i++) { - ring = &priv->rx_ring[i]; - if (ring->need_refill) { - if (mlx4_en_fill_rx_buf(dev, ring)) { - ring->need_refill = 0; - mlx4_en_update_rx_prod_db(ring); - } else - need_refill = 1; - } - } - if (need_refill) - queue_delayed_work(mdev->workqueue, &priv->refill_task, HZ); - -out: - mutex_unlock(&mdev->state_lock); -} - - -int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, u32 size, u16 stride) -{ - struct mlx4_en_dev *mdev = priv->mdev; - int err; - int tmp; - - /* Sanity check SRQ size before proceeding */ - if (size >= mdev->dev->caps.max_srq_wqes) - return -EINVAL; - - ring->prod = 0; - ring->cons = 0; - ring->size = size; - ring->size_mask = size - 1; - ring->stride = stride; - ring->log_stride = ffs(ring->stride) - 1; - ring->buf_size = ring->size * ring->stride; - - tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS * - sizeof(struct skb_frag_struct)); - ring->rx_info = vmalloc(tmp); - if (!ring->rx_info) { - mlx4_err(mdev, "Failed allocating rx_info ring\n"); - return -ENOMEM; - } - mlx4_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n", - ring->rx_info, tmp); - - err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, - ring->buf_size, 2 * PAGE_SIZE); - if (err) - goto err_ring; - - err = mlx4_en_map_buffer(&ring->wqres.buf); - if (err) { - mlx4_err(mdev, "Failed to map RX buffer\n"); - goto err_hwq; - } - ring->buf = ring->wqres.buf.direct.buf; - - /* Configure lro mngr */ - memset(&ring->lro, 0, sizeof(struct net_lro_mgr)); - ring->lro.dev = priv->dev; - ring->lro.features = LRO_F_NAPI; - ring->lro.frag_align_pad = NET_IP_ALIGN; - ring->lro.ip_summed = CHECKSUM_UNNECESSARY; - ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY; - ring->lro.max_desc = mdev->profile.num_lro; - ring->lro.max_aggr = MAX_SKB_FRAGS; - ring->lro.lro_arr = kzalloc(mdev->profile.num_lro * - sizeof(struct net_lro_desc), - GFP_KERNEL); - if (!ring->lro.lro_arr) { - mlx4_err(mdev, "Failed to allocate lro array\n"); - goto err_map; - } - ring->lro.get_frag_header = mlx4_en_get_frag_header; - - return 0; - -err_map: - mlx4_en_unmap_buffer(&ring->wqres.buf); -err_hwq: - mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); -err_ring: - vfree(ring->rx_info); - ring->rx_info = NULL; - return err; -} - -int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_wqe_srq_next_seg *next; - struct mlx4_en_rx_ring *ring; - int i; - int ring_ind; - int err; - int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + - DS_SIZE * priv->num_frags); - int max_gs = (stride - sizeof(struct mlx4_wqe_srq_next_seg)) / DS_SIZE; - - for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { - ring = &priv->rx_ring[ring_ind]; - - ring->prod = 0; - ring->cons = 0; - ring->actual_size = 0; - ring->cqn = priv->rx_cq[ring_ind].mcq.cqn; - - ring->stride = stride; - ring->log_stride = ffs(ring->stride) - 1; - ring->buf_size = ring->size * ring->stride; - - memset(ring->buf, 0, ring->buf_size); - mlx4_en_update_rx_prod_db(ring); - - /* Initailize all descriptors */ - for (i = 0; i < ring->size; i++) - mlx4_en_init_rx_desc(priv, ring, i); - - /* Initialize page allocators */ - err = mlx4_en_init_allocator(priv, ring); - if (err) { - mlx4_err(mdev, "Failed initializing ring allocator\n"); - goto err_allocator; - } - - /* Fill Rx buffers */ - ring->full = 0; - } - if (mlx4_en_fill_rx_buffers(priv)) - goto err_buffers; - - for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { - ring = &priv->rx_ring[ring_ind]; - - mlx4_en_update_rx_prod_db(ring); - - /* Configure SRQ representing the ring */ - ring->srq.max = ring->size; - ring->srq.max_gs = max_gs; - ring->srq.wqe_shift = ilog2(ring->stride); - - for (i = 0; i < ring->srq.max; ++i) { - next = get_wqe(ring, i); - next->next_wqe_index = - cpu_to_be16((i + 1) & (ring->srq.max - 1)); - } - - err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt, - ring->wqres.db.dma, &ring->srq); - if (err){ - mlx4_err(mdev, "Failed to allocate srq\n"); - goto err_srq; - } - ring->srq.event = mlx4_en_srq_event; - } - - return 0; - -err_srq: - while (ring_ind >= 0) { - ring = &priv->rx_ring[ring_ind]; - mlx4_srq_free(mdev->dev, &ring->srq); - ring_ind--; - } - -err_buffers: - for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) - mlx4_en_free_rx_buf(priv, &priv->rx_ring[ring_ind]); - - ring_ind = priv->rx_ring_num - 1; -err_allocator: - while (ring_ind >= 0) { - mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]); - ring_ind--; - } - return err; -} - -void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - kfree(ring->lro.lro_arr); - mlx4_en_unmap_buffer(&ring->wqres.buf); - mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); - vfree(ring->rx_info); - ring->rx_info = NULL; -} - -void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - mlx4_srq_free(mdev->dev, &ring->srq); - mlx4_en_free_rx_buf(priv, ring); - mlx4_en_destroy_allocator(priv, ring); -} - - -/* Unmap a completed descriptor and free unused pages */ -static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, - struct skb_frag_struct *skb_frags_rx, - struct mlx4_en_rx_alloc *page_alloc, - int length) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_frag_info *frag_info; - int nr; - dma_addr_t dma; - - /* Collect used fragments while replacing them in the HW descirptors */ - for (nr = 0; nr < priv->num_frags; nr++) { - frag_info = &priv->frag_info[nr]; - if (length <= frag_info->frag_prefix_size) - break; - - /* Save page reference in skb */ - skb_frags_rx[nr].page = skb_frags[nr].page; - skb_frags_rx[nr].size = skb_frags[nr].size; - skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset; - dma = be64_to_cpu(rx_desc->data[nr].addr); - - /* Allocate a replacement page */ - if (mlx4_en_alloc_frag(priv, rx_desc, skb_frags, page_alloc, nr)) - goto fail; - - /* Unmap buffer */ - pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, - PCI_DMA_FROMDEVICE); - } - /* Adjust size of last fragment to match actual length */ - skb_frags_rx[nr - 1].size = length - - priv->frag_info[nr - 1].frag_prefix_size; - return nr; - -fail: - /* Drop all accumulated fragments (which have already been replaced in - * the descriptor) of this packet; remaining fragments are reused... */ - while (nr > 0) { - nr--; - put_page(skb_frags_rx[nr].page); - } - return 0; -} - - -static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, - struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, - struct mlx4_en_rx_alloc *page_alloc, - unsigned int length) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct sk_buff *skb; - void *va; - int used_frags; - dma_addr_t dma; - - skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN); - if (!skb) { - mlx4_dbg(RX_ERR, priv, "Failed allocating skb\n"); - return NULL; - } - skb->dev = priv->dev; - skb_reserve(skb, NET_IP_ALIGN); - skb->len = length; - skb->truesize = length + sizeof(struct sk_buff); - - /* Get pointer to first fragment so we could copy the headers into the - * (linear part of the) skb */ - va = page_address(skb_frags[0].page) + skb_frags[0].page_offset; - - if (length <= SMALL_PACKET_SIZE) { - /* We are copying all relevant data to the skb - temporarily - * synch buffers for the copy */ - dma = be64_to_cpu(rx_desc->data[0].addr); - dma_sync_single_range_for_cpu(&mdev->pdev->dev, dma, 0, - length, DMA_FROM_DEVICE); - skb_copy_to_linear_data(skb, va, length); - dma_sync_single_range_for_device(&mdev->pdev->dev, dma, 0, - length, DMA_FROM_DEVICE); - skb->tail += length; - } else { - - /* Move relevant fragments to skb */ - used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, - skb_shinfo(skb)->frags, - page_alloc, length); - skb_shinfo(skb)->nr_frags = used_frags; - - /* Copy headers into the skb linear buffer */ - memcpy(skb->data, va, HEADER_COPY_SIZE); - skb->tail += HEADER_COPY_SIZE; - - /* Skip headers in first fragment */ - skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE; - - /* Adjust size of first fragment */ - skb_shinfo(skb)->frags[0].size -= HEADER_COPY_SIZE; - skb->data_len = length - HEADER_COPY_SIZE; - } - return skb; -} - -static void mlx4_en_copy_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, - int from, int to, int num) -{ - struct skb_frag_struct *skb_frags_from; - struct skb_frag_struct *skb_frags_to; - struct mlx4_en_rx_desc *rx_desc_from; - struct mlx4_en_rx_desc *rx_desc_to; - int from_index, to_index; - int nr, i; - - for (i = 0; i < num; i++) { - from_index = (from + i) & ring->size_mask; - to_index = (to + i) & ring->size_mask; - skb_frags_from = ring->rx_info + (from_index << priv->log_rx_info); - skb_frags_to = ring->rx_info + (to_index << priv->log_rx_info); - rx_desc_from = ring->buf + (from_index << ring->log_stride); - rx_desc_to = ring->buf + (to_index << ring->log_stride); - - for (nr = 0; nr < priv->num_frags; nr++) { - skb_frags_to[nr].page = skb_frags_from[nr].page; - skb_frags_to[nr].page_offset = skb_frags_from[nr].page_offset; - rx_desc_to->data[nr].addr = rx_desc_from->data[nr].addr; - } - } -} - - -int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_cqe *cqe; - struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; - struct skb_frag_struct *skb_frags; - struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS]; - struct mlx4_en_rx_desc *rx_desc; - struct sk_buff *skb; - int index; - int nr; - unsigned int length; - int polled = 0; - int ip_summed; - - if (!priv->port_up) - return 0; - - /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx - * descriptor offset can be deduced from the CQE index instead of - * reading 'cqe->index' */ - index = cq->mcq.cons_index & ring->size_mask; - cqe = &cq->buf[index]; - - /* Process all completed CQEs */ - while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, - cq->mcq.cons_index & cq->size)) { - - skb_frags = ring->rx_info + (index << priv->log_rx_info); - rx_desc = ring->buf + (index << ring->log_stride); - - /* - * make sure we read the CQE after we read the ownership bit - */ - rmb(); - - /* Drop packet on bad receive or bad checksum */ - if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == - MLX4_CQE_OPCODE_ERROR)) { - mlx4_err(mdev, "CQE completed in error - vendor " - "syndrom:%d syndrom:%d\n", - ((struct mlx4_err_cqe *) cqe)->vendor_err_syndrome, - ((struct mlx4_err_cqe *) cqe)->syndrome); - goto next; - } - if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) { - mlx4_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n"); - goto next; - } - - /* - * Packet is OK - process it. - */ - length = be32_to_cpu(cqe->byte_cnt); - ring->bytes += length; - ring->packets++; - - if (likely(priv->rx_csum)) { - if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && - (cqe->checksum == cpu_to_be16(0xffff))) { - priv->port_stats.rx_chksum_good++; - /* This packet is eligible for LRO if it is: - * - DIX Ethernet (type interpretation) - * - TCP/IP (v4) - * - without IP options - * - not an IP fragment */ - if (mlx4_en_can_lro(cqe->status) && - dev->features & NETIF_F_LRO) { - - nr = mlx4_en_complete_rx_desc( - priv, rx_desc, - skb_frags, lro_frags, - ring->page_alloc, length); - if (!nr) - goto next; - - if (priv->vlgrp && (cqe->vlan_my_qpn & - cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) { - lro_vlan_hwaccel_receive_frags( - &ring->lro, lro_frags, - length, length, - priv->vlgrp, - be16_to_cpu(cqe->sl_vid), - NULL, 0); - } else - lro_receive_frags(&ring->lro, - lro_frags, - length, - length, - NULL, 0); - - goto next; - } - - /* LRO not possible, complete processing here */ - ip_summed = CHECKSUM_UNNECESSARY; - INC_PERF_COUNTER(priv->pstats.lro_misses); - } else { - ip_summed = CHECKSUM_NONE; - priv->port_stats.rx_chksum_none++; - } - } else { - ip_summed = CHECKSUM_NONE; - priv->port_stats.rx_chksum_none++; - } - - skb = mlx4_en_rx_skb(priv, rx_desc, skb_frags, - ring->page_alloc, length); - if (!skb) { - priv->stats.rx_dropped++; - goto next; - } - - skb->ip_summed = ip_summed; - skb->protocol = eth_type_trans(skb, dev); - - /* Push it up the stack */ - if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) & - MLX4_CQE_VLAN_PRESENT_MASK)) { - vlan_hwaccel_receive_skb(skb, priv->vlgrp, - be16_to_cpu(cqe->sl_vid)); - } else - netif_receive_skb(skb); - - dev->last_rx = jiffies; - -next: - ++cq->mcq.cons_index; - index = (cq->mcq.cons_index) & ring->size_mask; - cqe = &cq->buf[index]; - if (++polled == budget) { - /* We are here because we reached the NAPI budget - - * flush only pending LRO sessions */ - lro_flush_all(&ring->lro); - goto out; - } - } - - /* If CQ is empty flush all LRO sessions unconditionally */ - lro_flush_all(&ring->lro); - -out: - AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled); - mlx4_cq_set_ci(&cq->mcq); - wmb(); /* ensure HW sees CQ consumer before we post new buffers */ - ring->cons = cq->mcq.cons_index; - ring->prod += polled; /* Polled descriptors were realocated in place */ - if (unlikely(!ring->full)) { - mlx4_en_copy_desc(priv, ring, ring->cons - polled, - ring->prod - polled, polled); - mlx4_en_fill_rx_buf(dev, ring); - } - mlx4_en_update_rx_prod_db(ring); - return polled; -} - - -void mlx4_en_rx_irq(struct mlx4_cq *mcq) -{ - struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); - struct mlx4_en_priv *priv = netdev_priv(cq->dev); - - if (priv->port_up) - netif_rx_schedule(cq->dev, &cq->napi); - else - mlx4_en_arm_cq(priv, cq); -} - -/* Rx CQ polling - called by NAPI */ -int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) -{ - struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi); - struct net_device *dev = cq->dev; - struct mlx4_en_priv *priv = netdev_priv(dev); - int done; - - done = mlx4_en_process_rx_cq(dev, cq, budget); - - /* If we used up all the quota - we're probably not done yet... */ - if (done == budget) - INC_PERF_COUNTER(priv->pstats.napi_quota); - else { - /* Done for now */ - netif_rx_complete(dev, napi); - mlx4_en_arm_cq(priv, cq); - } - return done; -} - - -/* Calculate the last offset position that accomodates a full fragment - * (assuming fagment size = stride-align) */ -static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align) -{ - u16 res = MLX4_EN_ALLOC_SIZE % stride; - u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align; - - mlx4_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d " - "res:%d offset:%d\n", stride, align, res, offset); - return offset; -} - - -static int frag_sizes[] = { - FRAG_SZ0, - FRAG_SZ1, - FRAG_SZ2, - FRAG_SZ3 -}; - -void mlx4_en_calc_rx_buf(struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN + ETH_LLC_SNAP_SIZE; - int buf_size = 0; - int i = 0; - - while (buf_size < eff_mtu) { - priv->frag_info[i].frag_size = - (eff_mtu > buf_size + frag_sizes[i]) ? - frag_sizes[i] : eff_mtu - buf_size; - priv->frag_info[i].frag_prefix_size = buf_size; - if (!i) { - priv->frag_info[i].frag_align = NET_IP_ALIGN; - priv->frag_info[i].frag_stride = - ALIGN(frag_sizes[i] + NET_IP_ALIGN, SMP_CACHE_BYTES); - } else { - priv->frag_info[i].frag_align = 0; - priv->frag_info[i].frag_stride = - ALIGN(frag_sizes[i], SMP_CACHE_BYTES); - } - priv->frag_info[i].last_offset = mlx4_en_last_alloc_offset( - priv, priv->frag_info[i].frag_stride, - priv->frag_info[i].frag_align); - buf_size += priv->frag_info[i].frag_size; - i++; - } - - priv->num_frags = i; - priv->rx_skb_size = eff_mtu; - priv->log_rx_info = ROUNDUP_LOG2(i * sizeof(struct skb_frag_struct)); - - mlx4_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d " - "num_frags:%d):\n", eff_mtu, priv->num_frags); - for (i = 0; i < priv->num_frags; i++) { - mlx4_dbg(DRV, priv, " frag:%d - size:%d prefix:%d align:%d " - "stride:%d last_offset:%d\n", i, - priv->frag_info[i].frag_size, - priv->frag_info[i].frag_prefix_size, - priv->frag_info[i].frag_align, - priv->frag_info[i].frag_stride, - priv->frag_info[i].last_offset); - } -} - -/* RSS related functions */ - -/* Calculate rss size and map each entry in rss table to rx ring */ -void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv, - struct mlx4_en_rss_map *rss_map, - int num_entries, int num_rings) -{ - int i; - - rss_map->size = roundup_pow_of_two(num_entries); - mlx4_dbg(DRV, priv, "Setting default RSS map of %d entires\n", - rss_map->size); - - for (i = 0; i < rss_map->size; i++) { - rss_map->map[i] = i % num_rings; - mlx4_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]); - } -} - -static void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event) -{ - return; -} - - -static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, - int qpn, int srqn, int cqn, - enum mlx4_qp_state *state, - struct mlx4_qp *qp) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_qp_context *context; - int err = 0; - - context = kmalloc(sizeof *context , GFP_KERNEL); - if (!context) { - mlx4_err(mdev, "Failed to allocate qp context\n"); - return -ENOMEM; - } - - err = mlx4_qp_alloc(mdev->dev, qpn, qp); - if (err) { - mlx4_err(mdev, "Failed to allocate qp #%d\n", qpn); - goto out; - return err; - } - qp->event = mlx4_en_sqp_event; - - memset(context, 0, sizeof *context); - mlx4_en_fill_qp_context(priv, 0, 0, 0, 0, qpn, cqn, srqn, context); - - err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, context, qp, state); - if (err) { - mlx4_qp_remove(mdev->dev, qp); - mlx4_qp_free(mdev->dev, qp); - } -out: - kfree(context); - return err; -} - -/* Allocate rx qp's and configure them according to rss map */ -int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_rss_map *rss_map = &priv->rss_map; - struct mlx4_qp_context context; - struct mlx4_en_rss_context *rss_context; - void *ptr; - int rss_xor = mdev->profile.rss_xor; - u8 rss_mask = mdev->profile.rss_mask; - int i, srqn, qpn, cqn; - int err = 0; - int good_qps = 0; - - mlx4_dbg(DRV, priv, "Configuring rss steering for port %u\n", priv->port); - err = mlx4_qp_reserve_range(mdev->dev, rss_map->size, - rss_map->size, &rss_map->base_qpn); - if (err) { - mlx4_err(mdev, "Failed reserving %d qps for port %u\n", - rss_map->size, priv->port); - return err; - } - - for (i = 0; i < rss_map->size; i++) { - cqn = priv->rx_ring[rss_map->map[i]].cqn; - srqn = priv->rx_ring[rss_map->map[i]].srq.srqn; - qpn = rss_map->base_qpn + i; - err = mlx4_en_config_rss_qp(priv, qpn, srqn, cqn, - &rss_map->state[i], - &rss_map->qps[i]); - if (err) - goto rss_err; - - ++good_qps; - } - - /* Configure RSS indirection qp */ - err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn); - if (err) { - mlx4_err(mdev, "Failed to reserve range for RSS " - "indirection qp\n"); - goto rss_err; - } - err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp); - if (err) { - mlx4_err(mdev, "Failed to allocate RSS indirection QP\n"); - goto reserve_err; - } - rss_map->indir_qp.event = mlx4_en_sqp_event; - mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, - priv->rx_ring[0].cqn, 0, &context); - - ptr = ((void *) &context) + 0x3c; - rss_context = (struct mlx4_en_rss_context *) ptr; - rss_context->base_qpn = cpu_to_be32(ilog2(rss_map->size) << 24 | - (rss_map->base_qpn)); - rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); - rss_context->hash_fn = rss_xor & 0x3; - rss_context->flags = rss_mask << 2; - - err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context, - &rss_map->indir_qp, &rss_map->indir_state); - if (err) - goto indir_err; - - return 0; - -indir_err: - mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state, - MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); - mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); - mlx4_qp_free(mdev->dev, &rss_map->indir_qp); -reserve_err: - mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1); -rss_err: - for (i = 0; i < good_qps; i++) { - mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], - MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]); - mlx4_qp_remove(mdev->dev, &rss_map->qps[i]); - mlx4_qp_free(mdev->dev, &rss_map->qps[i]); - } - mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size); - return err; -} - -void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_rss_map *rss_map = &priv->rss_map; - int i; - - mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state, - MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); - mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); - mlx4_qp_free(mdev->dev, &rss_map->indir_qp); - mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1); - - for (i = 0; i < rss_map->size; i++) { - mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], - MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]); - mlx4_qp_remove(mdev->dev, &rss_map->qps[i]); - mlx4_qp_free(mdev->dev, &rss_map->qps[i]); - } - mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size); -} - - - - - diff --git a/trunk/drivers/net/mlx4/en_tx.c b/trunk/drivers/net/mlx4/en_tx.c deleted file mode 100644 index 8592f8fb8475..000000000000 --- a/trunk/drivers/net/mlx4/en_tx.c +++ /dev/null @@ -1,820 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "mlx4_en.h" - -enum { - MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */ -}; - -static int inline_thold __read_mostly = MAX_INLINE; - -module_param_named(inline_thold, inline_thold, int, 0444); -MODULE_PARM_DESC(inline_thold, "treshold for using inline data"); - -int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring, u32 size, - u16 stride) -{ - struct mlx4_en_dev *mdev = priv->mdev; - int tmp; - int err; - - ring->size = size; - ring->size_mask = size - 1; - ring->stride = stride; - - inline_thold = min(inline_thold, MAX_INLINE); - - spin_lock_init(&ring->comp_lock); - - tmp = size * sizeof(struct mlx4_en_tx_info); - ring->tx_info = vmalloc(tmp); - if (!ring->tx_info) { - mlx4_err(mdev, "Failed allocating tx_info ring\n"); - return -ENOMEM; - } - mlx4_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n", - ring->tx_info, tmp); - - ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL); - if (!ring->bounce_buf) { - mlx4_err(mdev, "Failed allocating bounce buffer\n"); - err = -ENOMEM; - goto err_tx; - } - ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE); - - err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size, - 2 * PAGE_SIZE); - if (err) { - mlx4_err(mdev, "Failed allocating hwq resources\n"); - goto err_bounce; - } - - err = mlx4_en_map_buffer(&ring->wqres.buf); - if (err) { - mlx4_err(mdev, "Failed to map TX buffer\n"); - goto err_hwq_res; - } - - ring->buf = ring->wqres.buf.direct.buf; - - mlx4_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d " - "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size, - ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map); - - err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn); - if (err) { - mlx4_err(mdev, "Failed reserving qp for tx ring.\n"); - goto err_map; - } - - err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp); - if (err) { - mlx4_err(mdev, "Failed allocating qp %d\n", ring->qpn); - goto err_reserve; - } - - return 0; - -err_reserve: - mlx4_qp_release_range(mdev->dev, ring->qpn, 1); -err_map: - mlx4_en_unmap_buffer(&ring->wqres.buf); -err_hwq_res: - mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); -err_bounce: - kfree(ring->bounce_buf); - ring->bounce_buf = NULL; -err_tx: - vfree(ring->tx_info); - ring->tx_info = NULL; - return err; -} - -void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring) -{ - struct mlx4_en_dev *mdev = priv->mdev; - mlx4_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn); - - mlx4_qp_remove(mdev->dev, &ring->qp); - mlx4_qp_free(mdev->dev, &ring->qp); - mlx4_qp_release_range(mdev->dev, ring->qpn, 1); - mlx4_en_unmap_buffer(&ring->wqres.buf); - mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); - kfree(ring->bounce_buf); - ring->bounce_buf = NULL; - vfree(ring->tx_info); - ring->tx_info = NULL; -} - -int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring, - int cq, int srqn) -{ - struct mlx4_en_dev *mdev = priv->mdev; - int err; - - ring->cqn = cq; - ring->prod = 0; - ring->cons = 0xffffffff; - ring->last_nr_txbb = 1; - ring->poll_cnt = 0; - ring->blocked = 0; - memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info)); - memset(ring->buf, 0, ring->buf_size); - - ring->qp_state = MLX4_QP_STATE_RST; - ring->doorbell_qpn = swab32(ring->qp.qpn << 8); - - mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, - ring->cqn, srqn, &ring->context); - - err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context, - &ring->qp, &ring->qp_state); - - return err; -} - -void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring) -{ - struct mlx4_en_dev *mdev = priv->mdev; - - mlx4_qp_modify(mdev->dev, NULL, ring->qp_state, - MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp); -} - - -static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring, - int index, u8 owner) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_tx_info *tx_info = &ring->tx_info[index]; - struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE; - struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset; - struct sk_buff *skb = tx_info->skb; - struct skb_frag_struct *frag; - void *end = ring->buf + ring->buf_size; - int frags = skb_shinfo(skb)->nr_frags; - int i; - __be32 *ptr = (__be32 *)tx_desc; - __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT)); - - /* Optimize the common case when there are no wraparounds */ - if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { - if (tx_info->linear) { - pci_unmap_single(mdev->pdev, - (dma_addr_t) be64_to_cpu(data->addr), - be32_to_cpu(data->byte_count), - PCI_DMA_TODEVICE); - ++data; - } - - for (i = 0; i < frags; i++) { - frag = &skb_shinfo(skb)->frags[i]; - pci_unmap_page(mdev->pdev, - (dma_addr_t) be64_to_cpu(data[i].addr), - frag->size, PCI_DMA_TODEVICE); - } - /* Stamp the freed descriptor */ - for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) { - *ptr = stamp; - ptr += STAMP_DWORDS; - } - - } else { - if ((void *) data >= end) { - data = (struct mlx4_wqe_data_seg *) - (ring->buf + ((void *) data - end)); - } - - if (tx_info->linear) { - pci_unmap_single(mdev->pdev, - (dma_addr_t) be64_to_cpu(data->addr), - be32_to_cpu(data->byte_count), - PCI_DMA_TODEVICE); - ++data; - } - - for (i = 0; i < frags; i++) { - /* Check for wraparound before unmapping */ - if ((void *) data >= end) - data = (struct mlx4_wqe_data_seg *) ring->buf; - frag = &skb_shinfo(skb)->frags[i]; - pci_unmap_page(mdev->pdev, - (dma_addr_t) be64_to_cpu(data->addr), - frag->size, PCI_DMA_TODEVICE); - } - /* Stamp the freed descriptor */ - for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) { - *ptr = stamp; - ptr += STAMP_DWORDS; - if ((void *) ptr >= end) { - ptr = ring->buf; - stamp ^= cpu_to_be32(0x80000000); - } - } - - } - dev_kfree_skb_any(skb); - return tx_info->nr_txbb; -} - - -int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - int cnt = 0; - - /* Skip last polled descriptor */ - ring->cons += ring->last_nr_txbb; - mlx4_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n", - ring->cons, ring->prod); - - if ((u32) (ring->prod - ring->cons) > ring->size) { - if (netif_msg_tx_err(priv)) - mlx4_warn(priv->mdev, "Tx consumer passed producer!\n"); - return 0; - } - - while (ring->cons != ring->prod) { - ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring, - ring->cons & ring->size_mask, - !!(ring->cons & ring->size)); - ring->cons += ring->last_nr_txbb; - cnt++; - } - - if (cnt) - mlx4_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt); - - return cnt; -} - -void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num) -{ - int block = 8 / ring_num; - int extra = 8 - (block * ring_num); - int num = 0; - u16 ring = 1; - int prio; - - if (ring_num == 1) { - for (prio = 0; prio < 8; prio++) - prio_map[prio] = 0; - return; - } - - for (prio = 0; prio < 8; prio++) { - if (extra && (num == block + 1)) { - ring++; - num = 0; - extra--; - } else if (!extra && (num == block)) { - ring++; - num = 0; - } - prio_map[prio] = ring; - mlx4_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring); - num++; - } -} - -static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_cq *mcq = &cq->mcq; - struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring]; - struct mlx4_cqe *cqe = cq->buf; - u16 index; - u16 new_index; - u32 txbbs_skipped = 0; - u32 cq_last_sav; - - /* index always points to the first TXBB of the last polled descriptor */ - index = ring->cons & ring->size_mask; - new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask; - if (index == new_index) - return; - - if (!priv->port_up) - return; - - /* - * We use a two-stage loop: - * - the first samples the HW-updated CQE - * - the second frees TXBBs until the last sample - * This lets us amortize CQE cache misses, while still polling the CQ - * until is quiescent. - */ - cq_last_sav = mcq->cons_index; - do { - do { - /* Skip over last polled CQE */ - index = (index + ring->last_nr_txbb) & ring->size_mask; - txbbs_skipped += ring->last_nr_txbb; - - /* Poll next CQE */ - ring->last_nr_txbb = mlx4_en_free_tx_desc( - priv, ring, index, - !!((ring->cons + txbbs_skipped) & - ring->size)); - ++mcq->cons_index; - - } while (index != new_index); - - new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask; - } while (index != new_index); - AVG_PERF_COUNTER(priv->pstats.tx_coal_avg, - (u32) (mcq->cons_index - cq_last_sav)); - - /* - * To prevent CQ overflow we first update CQ consumer and only then - * the ring consumer. - */ - mlx4_cq_set_ci(mcq); - wmb(); - ring->cons += txbbs_skipped; - - /* Wakeup Tx queue if this ring stopped it */ - if (unlikely(ring->blocked)) { - if (((u32) (ring->prod - ring->cons) <= - ring->size - HEADROOM - MAX_DESC_TXBBS) && !cq->armed) { - - /* TODO: support multiqueue netdevs. Currently, we block - * when *any* ring is full. Note that: - * - 2 Tx rings can unblock at the same time and call - * netif_wake_queue(), which is OK since this - * operation is idempotent. - * - We might wake the queue just after another ring - * stopped it. This is no big deal because the next - * transmission on that ring would stop the queue. - */ - ring->blocked = 0; - netif_wake_queue(dev); - priv->port_stats.wake_queue++; - } - } -} - -void mlx4_en_tx_irq(struct mlx4_cq *mcq) -{ - struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); - struct mlx4_en_priv *priv = netdev_priv(cq->dev); - struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring]; - - spin_lock_irq(&ring->comp_lock); - cq->armed = 0; - mlx4_en_process_tx_cq(cq->dev, cq); - if (ring->blocked) - mlx4_en_arm_cq(priv, cq); - else - mod_timer(&cq->timer, jiffies + 1); - spin_unlock_irq(&ring->comp_lock); -} - - -void mlx4_en_poll_tx_cq(unsigned long data) -{ - struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data; - struct mlx4_en_priv *priv = netdev_priv(cq->dev); - struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring]; - u32 inflight; - - INC_PERF_COUNTER(priv->pstats.tx_poll); - - netif_tx_lock(priv->dev); - spin_lock_irq(&ring->comp_lock); - mlx4_en_process_tx_cq(cq->dev, cq); - inflight = (u32) (ring->prod - ring->cons - ring->last_nr_txbb); - - /* If there are still packets in flight and the timer has not already - * been scheduled by the Tx routine then schedule it here to guarantee - * completion processing of these packets */ - if (inflight && priv->port_up) - mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); - - spin_unlock_irq(&ring->comp_lock); - netif_tx_unlock(priv->dev); -} - -static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring, - u32 index, - unsigned int desc_size) -{ - u32 copy = (ring->size - index) * TXBB_SIZE; - int i; - - for (i = desc_size - copy - 4; i >= 0; i -= 4) { - if ((i & (TXBB_SIZE - 1)) == 0) - wmb(); - - *((u32 *) (ring->buf + i)) = - *((u32 *) (ring->bounce_buf + copy + i)); - } - - for (i = copy - 4; i >= 4 ; i -= 4) { - if ((i & (TXBB_SIZE - 1)) == 0) - wmb(); - - *((u32 *) (ring->buf + index * TXBB_SIZE + i)) = - *((u32 *) (ring->bounce_buf + i)); - } - - /* Return real descriptor location */ - return ring->buf + index * TXBB_SIZE; -} - -static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) -{ - struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind]; - struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind]; - - /* If we don't have a pending timer, set one up to catch our recent - post in case the interface becomes idle */ - if (!timer_pending(&cq->timer)) - mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); - - /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */ - if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0) - mlx4_en_process_tx_cq(priv->dev, cq); -} - -static void *get_frag_ptr(struct sk_buff *skb) -{ - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; - struct page *page = frag->page; - void *ptr; - - ptr = page_address(page); - if (unlikely(!ptr)) - return NULL; - - return ptr + frag->page_offset; -} - -static int is_inline(struct sk_buff *skb, void **pfrag) -{ - void *ptr; - - if (inline_thold && !skb_is_gso(skb) && skb->len <= inline_thold) { - if (skb_shinfo(skb)->nr_frags == 1) { - ptr = get_frag_ptr(skb); - if (unlikely(!ptr)) - return 0; - - if (pfrag) - *pfrag = ptr; - - return 1; - } else if (unlikely(skb_shinfo(skb)->nr_frags)) - return 0; - else - return 1; - } - - return 0; -} - -static int inline_size(struct sk_buff *skb) -{ - if (skb->len + CTRL_SIZE + sizeof(struct mlx4_wqe_inline_seg) - <= MLX4_INLINE_ALIGN) - return ALIGN(skb->len + CTRL_SIZE + - sizeof(struct mlx4_wqe_inline_seg), 16); - else - return ALIGN(skb->len + CTRL_SIZE + 2 * - sizeof(struct mlx4_wqe_inline_seg), 16); -} - -static int get_real_size(struct sk_buff *skb, struct net_device *dev, - int *lso_header_size) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int real_size; - - if (skb_is_gso(skb)) { - *lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb); - real_size = CTRL_SIZE + skb_shinfo(skb)->nr_frags * DS_SIZE + - ALIGN(*lso_header_size + 4, DS_SIZE); - if (unlikely(*lso_header_size != skb_headlen(skb))) { - /* We add a segment for the skb linear buffer only if - * it contains data */ - if (*lso_header_size < skb_headlen(skb)) - real_size += DS_SIZE; - else { - if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "Non-linear headers\n"); - dev_kfree_skb_any(skb); - return 0; - } - } - if (unlikely(*lso_header_size > MAX_LSO_HDR_SIZE)) { - if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "LSO header size too big\n"); - dev_kfree_skb_any(skb); - return 0; - } - } else { - *lso_header_size = 0; - if (!is_inline(skb, NULL)) - real_size = CTRL_SIZE + (skb_shinfo(skb)->nr_frags + 1) * DS_SIZE; - else - real_size = inline_size(skb); - } - - return real_size; -} - -static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *skb, - int real_size, u16 *vlan_tag, int tx_ind, void *fragptr) -{ - struct mlx4_wqe_inline_seg *inl = &tx_desc->inl; - int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof *inl; - - if (skb->len <= spc) { - inl->byte_count = cpu_to_be32(1 << 31 | skb->len); - skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb)); - if (skb_shinfo(skb)->nr_frags) - memcpy(((void *)(inl + 1)) + skb_headlen(skb), fragptr, - skb_shinfo(skb)->frags[0].size); - - } else { - inl->byte_count = cpu_to_be32(1 << 31 | spc); - if (skb_headlen(skb) <= spc) { - skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb)); - if (skb_headlen(skb) < spc) { - memcpy(((void *)(inl + 1)) + skb_headlen(skb), - fragptr, spc - skb_headlen(skb)); - fragptr += spc - skb_headlen(skb); - } - inl = (void *) (inl + 1) + spc; - memcpy(((void *)(inl + 1)), fragptr, skb->len - spc); - } else { - skb_copy_from_linear_data(skb, inl + 1, spc); - inl = (void *) (inl + 1) + spc; - skb_copy_from_linear_data_offset(skb, spc, inl + 1, - skb_headlen(skb) - spc); - if (skb_shinfo(skb)->nr_frags) - memcpy(((void *)(inl + 1)) + skb_headlen(skb) - spc, - fragptr, skb_shinfo(skb)->frags[0].size); - } - - wmb(); - inl->byte_count = cpu_to_be32(1 << 31 | (skb->len - spc)); - } - tx_desc->ctrl.vlan_tag = cpu_to_be16(*vlan_tag); - tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!(*vlan_tag); - tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; -} - -static int get_vlan_info(struct mlx4_en_priv *priv, struct sk_buff *skb, - u16 *vlan_tag) -{ - int tx_ind; - - /* Obtain VLAN information if present */ - if (priv->vlgrp && vlan_tx_tag_present(skb)) { - *vlan_tag = vlan_tx_tag_get(skb); - /* Set the Tx ring to use according to vlan priority */ - tx_ind = priv->tx_prio_map[*vlan_tag >> 13]; - } else { - *vlan_tag = 0; - tx_ind = 0; - } - return tx_ind; -} - -int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - struct mlx4_en_tx_ring *ring; - struct mlx4_en_cq *cq; - struct mlx4_en_tx_desc *tx_desc; - struct mlx4_wqe_data_seg *data; - struct skb_frag_struct *frag; - struct mlx4_en_tx_info *tx_info; - int tx_ind = 0; - int nr_txbb; - int desc_size; - int real_size; - dma_addr_t dma; - u32 index; - __be32 op_own; - u16 vlan_tag; - int i; - int lso_header_size; - void *fragptr; - - if (unlikely(!skb->len)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - real_size = get_real_size(skb, dev, &lso_header_size); - if (unlikely(!real_size)) - return NETDEV_TX_OK; - - /* Allign descriptor to TXBB size */ - desc_size = ALIGN(real_size, TXBB_SIZE); - nr_txbb = desc_size / TXBB_SIZE; - if (unlikely(nr_txbb > MAX_DESC_TXBBS)) { - if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "Oversized header or SG list\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - tx_ind = get_vlan_info(priv, skb, &vlan_tag); - ring = &priv->tx_ring[tx_ind]; - - /* Check available TXBBs And 2K spare for prefetch */ - if (unlikely(((int)(ring->prod - ring->cons)) > - ring->size - HEADROOM - MAX_DESC_TXBBS)) { - /* every full Tx ring stops queue. - * TODO: implement multi-queue support (per-queue stop) */ - netif_stop_queue(dev); - ring->blocked = 1; - priv->port_stats.queue_stopped++; - - /* Use interrupts to find out when queue opened */ - cq = &priv->tx_cq[tx_ind]; - mlx4_en_arm_cq(priv, cq); - return NETDEV_TX_BUSY; - } - - /* Now that we know what Tx ring to use */ - if (unlikely(!priv->port_up)) { - if (netif_msg_tx_err(priv)) - mlx4_warn(mdev, "xmit: port down!\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* Track current inflight packets for performance analysis */ - AVG_PERF_COUNTER(priv->pstats.inflight_avg, - (u32) (ring->prod - ring->cons - 1)); - - /* Packet is good - grab an index and transmit it */ - index = ring->prod & ring->size_mask; - - /* See if we have enough space for whole descriptor TXBB for setting - * SW ownership on next descriptor; if not, use a bounce buffer. */ - if (likely(index + nr_txbb <= ring->size)) - tx_desc = ring->buf + index * TXBB_SIZE; - else - tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf; - - /* Save skb in tx_info ring */ - tx_info = &ring->tx_info[index]; - tx_info->skb = skb; - tx_info->nr_txbb = nr_txbb; - - /* Prepare ctrl segement apart opcode+ownership, which depends on - * whether LSO is used */ - tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag); - tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!vlan_tag; - tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; - tx_desc->ctrl.srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE | - MLX4_WQE_CTRL_SOLICITED); - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | - MLX4_WQE_CTRL_TCP_UDP_CSUM); - priv->port_stats.tx_chksum_offload++; - } - - /* Handle LSO (TSO) packets */ - if (lso_header_size) { - /* Mark opcode as LSO */ - op_own = cpu_to_be32(MLX4_OPCODE_LSO | (1 << 6)) | - ((ring->prod & ring->size) ? - cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0); - - /* Fill in the LSO prefix */ - tx_desc->lso.mss_hdr_size = cpu_to_be32( - skb_shinfo(skb)->gso_size << 16 | lso_header_size); - - /* Copy headers; - * note that we already verified that it is linear */ - memcpy(tx_desc->lso.header, skb->data, lso_header_size); - data = ((void *) &tx_desc->lso + - ALIGN(lso_header_size + 4, DS_SIZE)); - - priv->port_stats.tso_packets++; - i = ((skb->len - lso_header_size) / skb_shinfo(skb)->gso_size) + - !!((skb->len - lso_header_size) % skb_shinfo(skb)->gso_size); - ring->bytes += skb->len + (i - 1) * lso_header_size; - ring->packets += i; - } else { - /* Normal (Non LSO) packet */ - op_own = cpu_to_be32(MLX4_OPCODE_SEND) | - ((ring->prod & ring->size) ? - cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0); - data = &tx_desc->data; - ring->bytes += max(skb->len, (unsigned int) ETH_ZLEN); - ring->packets++; - - } - AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, skb->len); - - - /* valid only for none inline segments */ - tx_info->data_offset = (void *) data - (void *) tx_desc; - - tx_info->linear = (lso_header_size < skb_headlen(skb) && !is_inline(skb, NULL)) ? 1 : 0; - data += skb_shinfo(skb)->nr_frags + tx_info->linear - 1; - - if (!is_inline(skb, &fragptr)) { - /* Map fragments */ - for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) { - frag = &skb_shinfo(skb)->frags[i]; - dma = pci_map_page(mdev->dev->pdev, frag->page, frag->page_offset, - frag->size, PCI_DMA_TODEVICE); - data->addr = cpu_to_be64(dma); - data->lkey = cpu_to_be32(mdev->mr.key); - wmb(); - data->byte_count = cpu_to_be32(frag->size); - --data; - } - - /* Map linear part */ - if (tx_info->linear) { - dma = pci_map_single(mdev->dev->pdev, skb->data + lso_header_size, - skb_headlen(skb) - lso_header_size, PCI_DMA_TODEVICE); - data->addr = cpu_to_be64(dma); - data->lkey = cpu_to_be32(mdev->mr.key); - wmb(); - data->byte_count = cpu_to_be32(skb_headlen(skb) - lso_header_size); - } - } else - build_inline_wqe(tx_desc, skb, real_size, &vlan_tag, tx_ind, fragptr); - - ring->prod += nr_txbb; - - /* If we used a bounce buffer then copy descriptor back into place */ - if (tx_desc == (struct mlx4_en_tx_desc *) ring->bounce_buf) - tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); - - /* Run destructor before passing skb to HW */ - if (likely(!skb_shared(skb))) - skb_orphan(skb); - - /* Ensure new descirptor hits memory - * before setting ownership of this descriptor to HW */ - wmb(); - tx_desc->ctrl.owner_opcode = op_own; - - /* Ring doorbell! */ - wmb(); - writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL); - dev->trans_start = jiffies; - - /* Poll CQ here */ - mlx4_en_xmit_poll(priv, tx_ind); - - return 0; -} - diff --git a/trunk/drivers/net/mlx4/eq.c b/trunk/drivers/net/mlx4/eq.c index de169338cd90..8a8b56135a58 100644 --- a/trunk/drivers/net/mlx4/eq.c +++ b/trunk/drivers/net/mlx4/eq.c @@ -558,7 +558,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) int i; err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs, - dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0); + dev->caps.num_eqs - 1, dev->caps.reserved_eqs); if (err) return err; diff --git a/trunk/drivers/net/mlx4/fw.c b/trunk/drivers/net/mlx4/fw.c index be09fdb79cb8..7e32955da982 100644 --- a/trunk/drivers/net/mlx4/fw.c +++ b/trunk/drivers/net/mlx4/fw.c @@ -88,7 +88,6 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags) [ 8] = "P_Key violation counter", [ 9] = "Q_Key violation counter", [10] = "VMM", - [12] = "DPDP", [16] = "MW support", [17] = "APM support", [18] = "Atomic ops support", @@ -347,7 +346,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); dev_cap->max_vl[i] = field >> 4; MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); - dev_cap->ib_mtu[i] = field >> 4; + dev_cap->max_mtu[i] = field >> 4; dev_cap->max_port_width[i] = field & 0xf; MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); dev_cap->max_gids[i] = 1 << (field & 0xf); @@ -355,13 +354,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_pkeys[i] = 1 << (field & 0xf); } } else { -#define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00 #define QUERY_PORT_MTU_OFFSET 0x01 -#define QUERY_PORT_ETH_MTU_OFFSET 0x02 #define QUERY_PORT_WIDTH_OFFSET 0x06 #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 -#define QUERY_PORT_MAC_OFFSET 0x08 -#define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a #define QUERY_PORT_MAX_VL_OFFSET 0x0b for (i = 1; i <= dev_cap->num_ports; ++i) { @@ -370,10 +365,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) if (err) goto out; - MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET); - dev_cap->supported_port_types[i] = field & 3; MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); - dev_cap->ib_mtu[i] = field & 0xf; + dev_cap->max_mtu[i] = field & 0xf; MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); dev_cap->max_port_width[i] = field & 0xf; MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); @@ -381,11 +374,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_pkeys[i] = 1 << (field & 0xf); MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); dev_cap->max_vl[i] = field & 0xf; - MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET); - dev_cap->log_max_macs[i] = field & 0xf; - dev_cap->log_max_vlans[i] = field >> 4; - MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET); - MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET); } } @@ -419,7 +407,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", - dev_cap->local_ca_ack_delay, 128 << dev_cap->ib_mtu[1], + dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1], dev_cap->max_port_width[1]); mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); @@ -831,7 +819,7 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); - field = 128 << dev->caps.ib_mtu_cap[port]; + field = 128 << dev->caps.mtu_cap[port]; MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET); field = dev->caps.gid_table_len[port]; MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET); diff --git a/trunk/drivers/net/mlx4/fw.h b/trunk/drivers/net/mlx4/fw.h index 526d7f30c041..decbb5c2ad41 100644 --- a/trunk/drivers/net/mlx4/fw.h +++ b/trunk/drivers/net/mlx4/fw.h @@ -66,13 +66,11 @@ struct mlx4_dev_cap { int local_ca_ack_delay; int num_ports; u32 max_msg_sz; - int ib_mtu[MLX4_MAX_PORTS + 1]; + int max_mtu[MLX4_MAX_PORTS + 1]; int max_port_width[MLX4_MAX_PORTS + 1]; int max_vl[MLX4_MAX_PORTS + 1]; int max_gids[MLX4_MAX_PORTS + 1]; int max_pkeys[MLX4_MAX_PORTS + 1]; - u64 def_mac[MLX4_MAX_PORTS + 1]; - u16 eth_mtu[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; u32 flags; int reserved_uars; @@ -104,9 +102,6 @@ struct mlx4_dev_cap { u32 reserved_lkey; u64 max_icm_sz; int max_gso_sz; - u8 supported_port_types[MLX4_MAX_PORTS + 1]; - u8 log_max_macs[MLX4_MAX_PORTS + 1]; - u8 log_max_vlans[MLX4_MAX_PORTS + 1]; }; struct mlx4_adapter { diff --git a/trunk/drivers/net/mlx4/main.c b/trunk/drivers/net/mlx4/main.c index 468921b8f4b6..1252a919de2e 100644 --- a/trunk/drivers/net/mlx4/main.c +++ b/trunk/drivers/net/mlx4/main.c @@ -85,57 +85,6 @@ static struct mlx4_profile default_profile = { .num_mtt = 1 << 20, }; -static int log_num_mac = 2; -module_param_named(log_num_mac, log_num_mac, int, 0444); -MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)"); - -static int log_num_vlan; -module_param_named(log_num_vlan, log_num_vlan, int, 0444); -MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)"); - -static int use_prio; -module_param_named(use_prio, use_prio, bool, 0444); -MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " - "(0/1, default 0)"); - -static int mlx4_check_port_params(struct mlx4_dev *dev, - enum mlx4_port_type *port_type) -{ - int i; - - for (i = 0; i < dev->caps.num_ports - 1; i++) { - if (port_type[i] != port_type[i+1] && - !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { - mlx4_err(dev, "Only same port types supported " - "on this HCA, aborting.\n"); - return -EINVAL; - } - } - if ((port_type[0] == MLX4_PORT_TYPE_ETH) && - (port_type[1] == MLX4_PORT_TYPE_IB)) { - mlx4_err(dev, "eth-ib configuration is not supported.\n"); - return -EINVAL; - } - - for (i = 0; i < dev->caps.num_ports; i++) { - if (!(port_type[i] & dev->caps.supported_type[i+1])) { - mlx4_err(dev, "Requested port type for port %d is not " - "supported on this HCA\n", i + 1); - return -EINVAL; - } - } - return 0; -} - -static void mlx4_set_port_mask(struct mlx4_dev *dev) -{ - int i; - - dev->caps.port_mask = 0; - for (i = 1; i <= dev->caps.num_ports; ++i) - if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB) - dev->caps.port_mask |= 1 << (i - 1); -} static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) { int err; @@ -171,13 +120,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.num_ports = dev_cap->num_ports; for (i = 1; i <= dev->caps.num_ports; ++i) { dev->caps.vl_cap[i] = dev_cap->max_vl[i]; - dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; + dev->caps.mtu_cap[i] = dev_cap->max_mtu[i]; dev->caps.gid_table_len[i] = dev_cap->max_gids[i]; dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i]; dev->caps.port_width_cap[i] = dev_cap->max_port_width[i]; - dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i]; - dev->caps.def_mac[i] = dev_cap->def_mac[i]; - dev->caps.supported_type[i] = dev_cap->supported_port_types[i]; } dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; @@ -188,6 +134,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_rq_sg = dev_cap->max_rq_sg; dev->caps.max_wqes = dev_cap->max_qp_sz; dev->caps.max_qp_init_rdma = dev_cap->max_requester_per_qp; + dev->caps.reserved_qps = dev_cap->reserved_qps; dev->caps.max_srq_wqes = dev_cap->max_srq_sz; dev->caps.max_srq_sge = dev_cap->max_rq_sg - 1; dev->caps.reserved_srqs = dev_cap->reserved_srqs; @@ -216,138 +163,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.stat_rate_support = dev_cap->stat_rate_support; dev->caps.max_gso_sz = dev_cap->max_gso_sz; - dev->caps.log_num_macs = log_num_mac; - dev->caps.log_num_vlans = log_num_vlan; - dev->caps.log_num_prios = use_prio ? 3 : 0; - - for (i = 1; i <= dev->caps.num_ports; ++i) { - if (dev->caps.supported_type[i] != MLX4_PORT_TYPE_ETH) - dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; - else - dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; - - if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) { - dev->caps.log_num_macs = dev_cap->log_max_macs[i]; - mlx4_warn(dev, "Requested number of MACs is too much " - "for port %d, reducing to %d.\n", - i, 1 << dev->caps.log_num_macs); - } - if (dev->caps.log_num_vlans > dev_cap->log_max_vlans[i]) { - dev->caps.log_num_vlans = dev_cap->log_max_vlans[i]; - mlx4_warn(dev, "Requested number of VLANs is too much " - "for port %d, reducing to %d.\n", - i, 1 << dev->caps.log_num_vlans); - } - } - - mlx4_set_port_mask(dev); - - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps; - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] = - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] = - (1 << dev->caps.log_num_macs) * - (1 << dev->caps.log_num_vlans) * - (1 << dev->caps.log_num_prios) * - dev->caps.num_ports; - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH; - - dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] + - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] + - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] + - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH]; - return 0; } -/* - * Change the port configuration of the device. - * Every user of this function must hold the port mutex. - */ -static int mlx4_change_port_types(struct mlx4_dev *dev, - enum mlx4_port_type *port_types) -{ - int err = 0; - int change = 0; - int port; - - for (port = 0; port < dev->caps.num_ports; port++) { - if (port_types[port] != dev->caps.port_type[port + 1]) { - change = 1; - dev->caps.port_type[port + 1] = port_types[port]; - } - } - if (change) { - mlx4_unregister_device(dev); - for (port = 1; port <= dev->caps.num_ports; port++) { - mlx4_CLOSE_PORT(dev, port); - err = mlx4_SET_PORT(dev, port); - if (err) { - mlx4_err(dev, "Failed to set port %d, " - "aborting\n", port); - goto out; - } - } - mlx4_set_port_mask(dev); - err = mlx4_register_device(dev); - } - -out: - return err; -} - -static ssize_t show_port_type(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info, - port_attr); - struct mlx4_dev *mdev = info->dev; - - return sprintf(buf, "%s\n", - mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB ? - "ib" : "eth"); -} - -static ssize_t set_port_type(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info, - port_attr); - struct mlx4_dev *mdev = info->dev; - struct mlx4_priv *priv = mlx4_priv(mdev); - enum mlx4_port_type types[MLX4_MAX_PORTS]; - int i; - int err = 0; - - if (!strcmp(buf, "ib\n")) - info->tmp_type = MLX4_PORT_TYPE_IB; - else if (!strcmp(buf, "eth\n")) - info->tmp_type = MLX4_PORT_TYPE_ETH; - else { - mlx4_err(mdev, "%s is not supported port type\n", buf); - return -EINVAL; - } - - mutex_lock(&priv->port_mutex); - for (i = 0; i < mdev->caps.num_ports; i++) - types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type : - mdev->caps.port_type[i+1]; - - err = mlx4_check_port_params(mdev, types); - if (err) - goto out; - - for (i = 1; i <= mdev->caps.num_ports; i++) - priv->port[i].tmp_type = 0; - - err = mlx4_change_port_types(mdev, types); - -out: - mutex_unlock(&priv->port_mutex); - return err ? err : count; -} - static int mlx4_load_fw(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -393,8 +211,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, ((u64) (MLX4_CMPT_TYPE_QP * cmpt_entry_sz) << MLX4_CMPT_SHIFT), cmpt_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], - 0, 0); + dev->caps.reserved_qps, 0, 0); if (err) goto err; @@ -519,8 +336,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, init_hca->qpc_base, dev_cap->qpc_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], - 0, 0); + dev->caps.reserved_qps, 0, 0); if (err) { mlx4_err(dev, "Failed to map QP context memory, aborting.\n"); goto err_unmap_dmpt; @@ -530,8 +346,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, init_hca->auxc_base, dev_cap->aux_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], - 0, 0); + dev->caps.reserved_qps, 0, 0); if (err) { mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n"); goto err_unmap_qp; @@ -541,8 +356,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, init_hca->altc_base, dev_cap->altc_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], - 0, 0); + dev->caps.reserved_qps, 0, 0); if (err) { mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n"); goto err_unmap_auxc; @@ -552,8 +366,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, init_hca->rdmarc_base, dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift, dev->caps.num_qps, - dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], - 0, 0); + dev->caps.reserved_qps, 0, 0); if (err) { mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n"); goto err_unmap_altc; @@ -752,7 +565,6 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); int err; - int port; err = mlx4_init_uar_table(dev); if (err) { @@ -851,20 +663,8 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) goto err_qp_table_free; } - for (port = 1; port <= dev->caps.num_ports; port++) { - err = mlx4_SET_PORT(dev, port); - if (err) { - mlx4_err(dev, "Failed to set port %d, aborting\n", - port); - goto err_mcg_table_free; - } - } - return 0; -err_mcg_table_free: - mlx4_cleanup_mcg_table(dev); - err_qp_table_free: mlx4_cleanup_qp_table(dev); @@ -928,45 +728,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) priv->eq_table.eq[i].irq = dev->pdev->irq; } -static int mlx4_init_port_info(struct mlx4_dev *dev, int port) -{ - struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; - int err = 0; - - info->dev = dev; - info->port = port; - mlx4_init_mac_table(dev, &info->mac_table); - mlx4_init_vlan_table(dev, &info->vlan_table); - - sprintf(info->dev_name, "mlx4_port%d", port); - info->port_attr.attr.name = info->dev_name; - info->port_attr.attr.mode = S_IRUGO | S_IWUSR; - info->port_attr.show = show_port_type; - info->port_attr.store = set_port_type; - - err = device_create_file(&dev->pdev->dev, &info->port_attr); - if (err) { - mlx4_err(dev, "Failed to create file for port %d\n", port); - info->port = -1; - } - - return err; -} - -static void mlx4_cleanup_port_info(struct mlx4_port_info *info) -{ - if (info->port < 0) - return; - - device_remove_file(&info->dev->pdev->dev, &info->port_attr); -} - static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { struct mlx4_priv *priv; struct mlx4_dev *dev; int err; - int port; printk(KERN_INFO PFX "Initializing %s\n", pci_name(pdev)); @@ -1041,8 +807,6 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); - mutex_init(&priv->port_mutex); - INIT_LIST_HEAD(&priv->pgdir_list); mutex_init(&priv->pgdir_mutex); @@ -1078,24 +842,15 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (err) goto err_close; - for (port = 1; port <= dev->caps.num_ports; port++) { - err = mlx4_init_port_info(dev, port); - if (err) - goto err_port; - } - err = mlx4_register_device(dev); if (err) - goto err_port; + goto err_cleanup; pci_set_drvdata(pdev, dev); return 0; -err_port: - for (port = 1; port <= dev->caps.num_ports; port++) - mlx4_cleanup_port_info(&priv->port[port]); - +err_cleanup: mlx4_cleanup_mcg_table(dev); mlx4_cleanup_qp_table(dev); mlx4_cleanup_srq_table(dev); @@ -1152,10 +907,8 @@ static void mlx4_remove_one(struct pci_dev *pdev) if (dev) { mlx4_unregister_device(dev); - for (p = 1; p <= dev->caps.num_ports; p++) { - mlx4_cleanup_port_info(&priv->port[p]); + for (p = 1; p <= dev->caps.num_ports; ++p) mlx4_CLOSE_PORT(dev, p); - } mlx4_cleanup_mcg_table(dev); mlx4_cleanup_qp_table(dev); @@ -1195,8 +948,6 @@ static struct pci_device_id mlx4_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */ { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */ - { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ { 0, } }; @@ -1209,28 +960,10 @@ static struct pci_driver mlx4_driver = { .remove = __devexit_p(mlx4_remove_one) }; -static int __init mlx4_verify_params(void) -{ - if ((log_num_mac < 0) || (log_num_mac > 7)) { - printk(KERN_WARNING "mlx4_core: bad num_mac: %d\n", log_num_mac); - return -1; - } - - if ((log_num_vlan < 0) || (log_num_vlan > 7)) { - printk(KERN_WARNING "mlx4_core: bad num_vlan: %d\n", log_num_vlan); - return -1; - } - - return 0; -} - static int __init mlx4_init(void) { int ret; - if (mlx4_verify_params()) - return -EINVAL; - ret = mlx4_catas_init(); if (ret) return ret; diff --git a/trunk/drivers/net/mlx4/mcg.c b/trunk/drivers/net/mlx4/mcg.c index 592c01ae2c5d..c83f88ce0736 100644 --- a/trunk/drivers/net/mlx4/mcg.c +++ b/trunk/drivers/net/mlx4/mcg.c @@ -368,8 +368,8 @@ int mlx4_init_mcg_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int err; - err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms, - dev->caps.num_amgms - 1, 0, 0); + err = mlx4_bitmap_init(&priv->mcg_table.bitmap, + dev->caps.num_amgms, dev->caps.num_amgms - 1, 0); if (err) return err; diff --git a/trunk/drivers/net/mlx4/mlx4.h b/trunk/drivers/net/mlx4/mlx4.h index fa431fad0eec..5337e3ac3e78 100644 --- a/trunk/drivers/net/mlx4/mlx4.h +++ b/trunk/drivers/net/mlx4/mlx4.h @@ -111,7 +111,6 @@ struct mlx4_bitmap { u32 last; u32 top; u32 max; - u32 reserved_top; u32 mask; spinlock_t lock; unsigned long *table; @@ -252,38 +251,6 @@ struct mlx4_catas_err { struct list_head list; }; -#define MLX4_MAX_MAC_NUM 128 -#define MLX4_MAC_TABLE_SIZE (MLX4_MAX_MAC_NUM << 3) - -struct mlx4_mac_table { - __be64 entries[MLX4_MAX_MAC_NUM]; - int refs[MLX4_MAX_MAC_NUM]; - struct mutex mutex; - int total; - int max; -}; - -#define MLX4_MAX_VLAN_NUM 128 -#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2) - -struct mlx4_vlan_table { - __be32 entries[MLX4_MAX_VLAN_NUM]; - int refs[MLX4_MAX_VLAN_NUM]; - struct mutex mutex; - int total; - int max; -}; - -struct mlx4_port_info { - struct mlx4_dev *dev; - int port; - char dev_name[16]; - struct device_attribute port_attr; - enum mlx4_port_type tmp_type; - struct mlx4_mac_table mac_table; - struct mlx4_vlan_table vlan_table; -}; - struct mlx4_priv { struct mlx4_dev dev; @@ -312,8 +279,6 @@ struct mlx4_priv { struct mlx4_uar driver_uar; void __iomem *kar; - struct mlx4_port_info port[MLX4_MAX_PORTS + 1]; - struct mutex port_mutex; }; static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) @@ -323,10 +288,7 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); -u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align); -void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt); -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, - u32 reserved_bot, u32 resetrved_top); +int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved); void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap); int mlx4_reset(struct mlx4_dev *dev); @@ -384,9 +346,4 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); void mlx4_handle_catas_err(struct mlx4_dev *dev); -void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); -void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); - -int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); - #endif /* MLX4_H */ diff --git a/trunk/drivers/net/mlx4/mlx4_en.h b/trunk/drivers/net/mlx4/mlx4_en.h deleted file mode 100644 index 11fb17c6e97b..000000000000 --- a/trunk/drivers/net/mlx4/mlx4_en.h +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef _MLX4_EN_H_ -#define _MLX4_EN_H_ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "en_port.h" - -#define DRV_NAME "mlx4_en" -#define DRV_VERSION "1.4.0" -#define DRV_RELDATE "Sep 2008" - - -#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) - -#define mlx4_dbg(mlevel, priv, format, arg...) \ - if (NETIF_MSG_##mlevel & priv->msg_enable) \ - printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\ - (&priv->mdev->pdev->dev)->bus_id , ## arg) - -#define mlx4_err(mdev, format, arg...) \ - printk(KERN_ERR "%s %s: " format , DRV_NAME ,\ - (&mdev->pdev->dev)->bus_id , ## arg) -#define mlx4_info(mdev, format, arg...) \ - printk(KERN_INFO "%s %s: " format , DRV_NAME ,\ - (&mdev->pdev->dev)->bus_id , ## arg) -#define mlx4_warn(mdev, format, arg...) \ - printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\ - (&mdev->pdev->dev)->bus_id , ## arg) - -/* - * Device constants - */ - - -#define MLX4_EN_PAGE_SHIFT 12 -#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) -#define MAX_TX_RINGS 16 -#define MAX_RX_RINGS 16 -#define MAX_RSS_MAP_SIZE 64 -#define RSS_FACTOR 2 -#define TXBB_SIZE 64 -#define HEADROOM (2048 / TXBB_SIZE + 1) -#define MAX_LSO_HDR_SIZE 92 -#define STAMP_STRIDE 64 -#define STAMP_DWORDS (STAMP_STRIDE / 4) -#define STAMP_SHIFT 31 -#define STAMP_VAL 0x7fffffff -#define STATS_DELAY (HZ / 4) - -/* Typical TSO descriptor with 16 gather entries is 352 bytes... */ -#define MAX_DESC_SIZE 512 -#define MAX_DESC_TXBBS (MAX_DESC_SIZE / TXBB_SIZE) - -/* - * OS related constants and tunables - */ - -#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ) - -#define MLX4_EN_ALLOC_ORDER 2 -#define MLX4_EN_ALLOC_SIZE (PAGE_SIZE << MLX4_EN_ALLOC_ORDER) - -#define MLX4_EN_MAX_LRO_DESCRIPTORS 32 - -/* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU - * and 4K allocations) */ -enum { - FRAG_SZ0 = 512 - NET_IP_ALIGN, - FRAG_SZ1 = 1024, - FRAG_SZ2 = 4096, - FRAG_SZ3 = MLX4_EN_ALLOC_SIZE -}; -#define MLX4_EN_MAX_RX_FRAGS 4 - -/* Minimum ring size for our page-allocation sceme to work */ -#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES) -#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) - -#define MLX4_EN_TX_RING_NUM 9 -#define MLX4_EN_DEF_TX_RING_SIZE 1024 -#define MLX4_EN_DEF_RX_RING_SIZE 1024 - -/* Target number of bytes to coalesce with interrupt moderation */ -#define MLX4_EN_RX_COAL_TARGET 0x20000 -#define MLX4_EN_RX_COAL_TIME 0x10 - -#define MLX4_EN_TX_COAL_PKTS 5 -#define MLX4_EN_TX_COAL_TIME 0x80 - -#define MLX4_EN_RX_RATE_LOW 400000 -#define MLX4_EN_RX_COAL_TIME_LOW 0 -#define MLX4_EN_RX_RATE_HIGH 450000 -#define MLX4_EN_RX_COAL_TIME_HIGH 128 -#define MLX4_EN_RX_SIZE_THRESH 1024 -#define MLX4_EN_RX_RATE_THRESH (1000000 / MLX4_EN_RX_COAL_TIME_HIGH) -#define MLX4_EN_SAMPLE_INTERVAL 0 - -#define MLX4_EN_AUTO_CONF 0xffff - -#define MLX4_EN_DEF_RX_PAUSE 1 -#define MLX4_EN_DEF_TX_PAUSE 1 - -/* Interval between sucessive polls in the Tx routine when polling is used - instead of interrupts (in per-core Tx rings) - should be power of 2 */ -#define MLX4_EN_TX_POLL_MODER 16 -#define MLX4_EN_TX_POLL_TIMEOUT (HZ / 4) - -#define ETH_LLC_SNAP_SIZE 8 - -#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN) -#define HEADER_COPY_SIZE (128 - NET_IP_ALIGN) - -#define MLX4_EN_MIN_MTU 46 -#define ETH_BCAST 0xffffffffffffULL - -#ifdef MLX4_EN_PERF_STAT -/* Number of samples to 'average' */ -#define AVG_SIZE 128 -#define AVG_FACTOR 1024 -#define NUM_PERF_STATS NUM_PERF_COUNTERS - -#define INC_PERF_COUNTER(cnt) (++(cnt)) -#define ADD_PERF_COUNTER(cnt, add) ((cnt) += (add)) -#define AVG_PERF_COUNTER(cnt, sample) \ - ((cnt) = ((cnt) * (AVG_SIZE - 1) + (sample) * AVG_FACTOR) / AVG_SIZE) -#define GET_PERF_COUNTER(cnt) (cnt) -#define GET_AVG_PERF_COUNTER(cnt) ((cnt) / AVG_FACTOR) - -#else - -#define NUM_PERF_STATS 0 -#define INC_PERF_COUNTER(cnt) do {} while (0) -#define ADD_PERF_COUNTER(cnt, add) do {} while (0) -#define AVG_PERF_COUNTER(cnt, sample) do {} while (0) -#define GET_PERF_COUNTER(cnt) (0) -#define GET_AVG_PERF_COUNTER(cnt) (0) -#endif /* MLX4_EN_PERF_STAT */ - -/* - * Configurables - */ - -enum cq_type { - RX = 0, - TX = 1, -}; - - -/* - * Useful macros - */ -#define ROUNDUP_LOG2(x) ilog2(roundup_pow_of_two(x)) -#define XNOR(x, y) (!(x) == !(y)) -#define ILLEGAL_MAC(addr) (addr == 0xffffffffffffULL || addr == 0x0) - - -struct mlx4_en_tx_info { - struct sk_buff *skb; - u32 nr_txbb; - u8 linear; - u8 data_offset; -}; - - -#define MLX4_EN_BIT_DESC_OWN 0x80000000 -#define CTRL_SIZE sizeof(struct mlx4_wqe_ctrl_seg) -#define MLX4_EN_MEMTYPE_PAD 0x100 -#define DS_SIZE sizeof(struct mlx4_wqe_data_seg) - - -struct mlx4_en_tx_desc { - struct mlx4_wqe_ctrl_seg ctrl; - union { - struct mlx4_wqe_data_seg data; /* at least one data segment */ - struct mlx4_wqe_lso_seg lso; - struct mlx4_wqe_inline_seg inl; - }; -}; - -#define MLX4_EN_USE_SRQ 0x01000000 - -struct mlx4_en_rx_alloc { - struct page *page; - u16 offset; -}; - -struct mlx4_en_tx_ring { - struct mlx4_hwq_resources wqres; - u32 size ; /* number of TXBBs */ - u32 size_mask; - u16 stride; - u16 cqn; /* index of port CQ associated with this ring */ - u32 prod; - u32 cons; - u32 buf_size; - u32 doorbell_qpn; - void *buf; - u16 poll_cnt; - int blocked; - struct mlx4_en_tx_info *tx_info; - u8 *bounce_buf; - u32 last_nr_txbb; - struct mlx4_qp qp; - struct mlx4_qp_context context; - int qpn; - enum mlx4_qp_state qp_state; - struct mlx4_srq dummy; - unsigned long bytes; - unsigned long packets; - spinlock_t comp_lock; -}; - -struct mlx4_en_rx_desc { - struct mlx4_wqe_srq_next_seg next; - /* actual number of entries depends on rx ring stride */ - struct mlx4_wqe_data_seg data[0]; -}; - -struct mlx4_en_rx_ring { - struct mlx4_srq srq; - struct mlx4_hwq_resources wqres; - struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS]; - struct net_lro_mgr lro; - u32 size ; /* number of Rx descs*/ - u32 actual_size; - u32 size_mask; - u16 stride; - u16 log_stride; - u16 cqn; /* index of port CQ associated with this ring */ - u32 prod; - u32 cons; - u32 buf_size; - int need_refill; - int full; - void *buf; - void *rx_info; - unsigned long bytes; - unsigned long packets; -}; - - -static inline int mlx4_en_can_lro(__be16 status) -{ - return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 | - MLX4_CQE_STATUS_IPV4F | - MLX4_CQE_STATUS_IPV6 | - MLX4_CQE_STATUS_IPV4OPT | - MLX4_CQE_STATUS_TCP | - MLX4_CQE_STATUS_UDP | - MLX4_CQE_STATUS_IPOK)) == - cpu_to_be16(MLX4_CQE_STATUS_IPV4 | - MLX4_CQE_STATUS_IPOK | - MLX4_CQE_STATUS_TCP); -} - -struct mlx4_en_cq { - struct mlx4_cq mcq; - struct mlx4_hwq_resources wqres; - int ring; - spinlock_t lock; - struct net_device *dev; - struct napi_struct napi; - /* Per-core Tx cq processing support */ - struct timer_list timer; - int size; - int buf_size; - unsigned vector; - enum cq_type is_tx; - u16 moder_time; - u16 moder_cnt; - int armed; - struct mlx4_cqe *buf; -#define MLX4_EN_OPCODE_ERROR 0x1e -}; - -struct mlx4_en_port_profile { - u32 flags; - u32 tx_ring_num; - u32 rx_ring_num; - u32 tx_ring_size; - u32 rx_ring_size; -}; - -struct mlx4_en_profile { - int rss_xor; - int num_lro; - u8 rss_mask; - u32 active_ports; - u32 small_pkt_int; - int rx_moder_cnt; - int rx_moder_time; - int auto_moder; - u8 rx_pause; - u8 rx_ppp; - u8 tx_pause; - u8 tx_ppp; - u8 no_reset; - struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; -}; - -struct mlx4_en_dev { - struct mlx4_dev *dev; - struct pci_dev *pdev; - struct mutex state_lock; - struct net_device *pndev[MLX4_MAX_PORTS + 1]; - u32 port_cnt; - bool device_up; - struct mlx4_en_profile profile; - u32 LSO_support; - struct workqueue_struct *workqueue; - struct device *dma_device; - void __iomem *uar_map; - struct mlx4_uar priv_uar; - struct mlx4_mr mr; - u32 priv_pdn; - spinlock_t uar_lock; -}; - - -struct mlx4_en_rss_map { - int size; - int base_qpn; - u16 map[MAX_RSS_MAP_SIZE]; - struct mlx4_qp qps[MAX_RSS_MAP_SIZE]; - enum mlx4_qp_state state[MAX_RSS_MAP_SIZE]; - struct mlx4_qp indir_qp; - enum mlx4_qp_state indir_state; -}; - -struct mlx4_en_rss_context { - __be32 base_qpn; - __be32 default_qpn; - u16 reserved; - u8 hash_fn; - u8 flags; - __be32 rss_key[10]; -}; - -struct mlx4_en_pkt_stats { - unsigned long broadcast; - unsigned long rx_prio[8]; - unsigned long tx_prio[8]; -#define NUM_PKT_STATS 17 -}; - -struct mlx4_en_port_stats { - unsigned long lro_aggregated; - unsigned long lro_flushed; - unsigned long lro_no_desc; - unsigned long tso_packets; - unsigned long queue_stopped; - unsigned long wake_queue; - unsigned long tx_timeout; - unsigned long rx_alloc_failed; - unsigned long rx_chksum_good; - unsigned long rx_chksum_none; - unsigned long tx_chksum_offload; -#define NUM_PORT_STATS 11 -}; - -struct mlx4_en_perf_stats { - u32 tx_poll; - u64 tx_pktsz_avg; - u32 inflight_avg; - u16 tx_coal_avg; - u16 rx_coal_avg; - u32 napi_quota; -#define NUM_PERF_COUNTERS 6 -}; - -struct mlx4_en_frag_info { - u16 frag_size; - u16 frag_prefix_size; - u16 frag_stride; - u16 frag_align; - u16 last_offset; - -}; - -struct mlx4_en_priv { - struct mlx4_en_dev *mdev; - struct mlx4_en_port_profile *prof; - struct net_device *dev; - struct vlan_group *vlgrp; - struct net_device_stats stats; - struct net_device_stats ret_stats; - spinlock_t stats_lock; - - unsigned long last_moder_packets; - unsigned long last_moder_tx_packets; - unsigned long last_moder_bytes; - unsigned long last_moder_jiffies; - int last_moder_time; - u16 rx_usecs; - u16 rx_frames; - u16 tx_usecs; - u16 tx_frames; - u32 pkt_rate_low; - u16 rx_usecs_low; - u32 pkt_rate_high; - u16 rx_usecs_high; - u16 sample_interval; - u16 adaptive_rx_coal; - u32 msg_enable; - - struct mlx4_hwq_resources res; - int link_state; - int last_link_state; - bool port_up; - int port; - int registered; - int allocated; - int stride; - int rx_csum; - u64 mac; - int mac_index; - unsigned max_mtu; - int base_qpn; - - struct mlx4_en_rss_map rss_map; - u16 tx_prio_map[8]; - u32 flags; -#define MLX4_EN_FLAG_PROMISC 0x1 - u32 tx_ring_num; - u32 rx_ring_num; - u32 rx_skb_size; - struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS]; - u16 num_frags; - u16 log_rx_info; - - struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS]; - struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS]; - struct mlx4_en_cq tx_cq[MAX_TX_RINGS]; - struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; - struct work_struct mcast_task; - struct work_struct mac_task; - struct delayed_work refill_task; - struct work_struct watchdog_task; - struct work_struct linkstate_task; - struct delayed_work stats_task; - struct mlx4_en_perf_stats pstats; - struct mlx4_en_pkt_stats pkstats; - struct mlx4_en_port_stats port_stats; - struct dev_mc_list *mc_list; - struct mlx4_en_stat_out_mbox hw_stats; -}; - - -void mlx4_en_destroy_netdev(struct net_device *dev); -int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, - struct mlx4_en_port_profile *prof); - -int mlx4_en_get_profile(struct mlx4_en_dev *mdev); - -int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, - int entries, int ring, enum cq_type mode); -void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); -int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); -void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); -int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); -int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); - -void mlx4_en_poll_tx_cq(unsigned long data); -void mlx4_en_tx_irq(struct mlx4_cq *mcq); -int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); - -int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring, - u32 size, u16 stride); -void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring); -int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring, - int cq, int srqn); -void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_tx_ring *ring); - -int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, - u32 size, u16 stride); -void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring); -int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv); -void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring); -int mlx4_en_process_rx_cq(struct net_device *dev, - struct mlx4_en_cq *cq, - int budget); -int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget); -void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, - int is_tx, int rss, int qpn, int cqn, int srqn, - struct mlx4_qp_context *context); -int mlx4_en_map_buffer(struct mlx4_buf *buf); -void mlx4_en_unmap_buffer(struct mlx4_buf *buf); - -void mlx4_en_calc_rx_buf(struct net_device *dev); -void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv, - struct mlx4_en_rss_map *rss_map, - int num_entries, int num_rings); -void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num); -int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); -void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); -int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring); -void mlx4_en_rx_refill(struct work_struct *work); -void mlx4_en_rx_irq(struct mlx4_cq *mcq); - -int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode); -int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp); -int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, - u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx); -int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, - u8 promisc); - -int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset); - -/* - * Globals - */ -extern const struct ethtool_ops mlx4_en_ethtool_ops; -#endif diff --git a/trunk/drivers/net/mlx4/mr.c b/trunk/drivers/net/mlx4/mr.c index 0caf74cae8bc..d1dd5b48dbd1 100644 --- a/trunk/drivers/net/mlx4/mr.c +++ b/trunk/drivers/net/mlx4/mr.c @@ -461,7 +461,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) int err; err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, - ~0, dev->caps.reserved_mrws, 0); + ~0, dev->caps.reserved_mrws); if (err) return err; diff --git a/trunk/drivers/net/mlx4/pd.c b/trunk/drivers/net/mlx4/pd.c index 26d1a7a9e375..aa616892d09c 100644 --- a/trunk/drivers/net/mlx4/pd.c +++ b/trunk/drivers/net/mlx4/pd.c @@ -62,7 +62,7 @@ int mlx4_init_pd_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds, - (1 << 24) - 1, dev->caps.reserved_pds, 0); + (1 << 24) - 1, dev->caps.reserved_pds); } void mlx4_cleanup_pd_table(struct mlx4_dev *dev) @@ -100,7 +100,7 @@ int mlx4_init_uar_table(struct mlx4_dev *dev) return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap, dev->caps.num_uars, dev->caps.num_uars - 1, - max(128, dev->caps.reserved_uars), 0); + max(128, dev->caps.reserved_uars)); } void mlx4_cleanup_uar_table(struct mlx4_dev *dev) diff --git a/trunk/drivers/net/mlx4/port.c b/trunk/drivers/net/mlx4/port.c deleted file mode 100644 index e2fdab42c4ce..000000000000 --- a/trunk/drivers/net/mlx4/port.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2007 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" - -#define MLX4_MAC_VALID (1ull << 63) -#define MLX4_MAC_MASK 0xffffffffffffULL - -#define MLX4_VLAN_VALID (1u << 31) -#define MLX4_VLAN_MASK 0xfff - -void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table) -{ - int i; - - mutex_init(&table->mutex); - for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { - table->entries[i] = 0; - table->refs[i] = 0; - } - table->max = 1 << dev->caps.log_num_macs; - table->total = 0; -} - -void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) -{ - int i; - - mutex_init(&table->mutex); - for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) { - table->entries[i] = 0; - table->refs[i] = 0; - } - table->max = 1 << dev->caps.log_num_vlans; - table->total = 0; -} - -static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, - __be64 *entries) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 in_mod; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); - - in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index) -{ - struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; - int i, err = 0; - int free = -1; - - mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); - mutex_lock(&table->mutex); - for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) { - if (free < 0 && !table->refs[i]) { - free = i; - continue; - } - - if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { - /* MAC already registered, increase refernce count */ - *index = i; - ++table->refs[i]; - goto out; - } - } - mlx4_dbg(dev, "Free MAC index is %d\n", free); - - if (table->total == table->max) { - /* No free mac entries */ - err = -ENOSPC; - goto out; - } - - /* Register new MAC */ - table->refs[free] = 1; - table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); - - err = mlx4_set_port_mac_table(dev, port, table->entries); - if (unlikely(err)) { - mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac); - table->refs[free] = 0; - table->entries[free] = 0; - goto out; - } - - *index = free; - ++table->total; -out: - mutex_unlock(&table->mutex); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_register_mac); - -void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index) -{ - struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; - - mutex_lock(&table->mutex); - if (!table->refs[index]) { - mlx4_warn(dev, "No MAC entry for index %d\n", index); - goto out; - } - if (--table->refs[index]) { - mlx4_warn(dev, "Have more references for index %d," - "no need to modify MAC table\n", index); - goto out; - } - table->entries[index] = 0; - mlx4_set_port_mac_table(dev, port, table->entries); - --table->total; -out: - mutex_unlock(&table->mutex); -} -EXPORT_SYMBOL_GPL(mlx4_unregister_mac); - -static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, - __be32 *entries) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 in_mod; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); - in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} - -int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) -{ - struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; - int i, err = 0; - int free = -1; - - mutex_lock(&table->mutex); - for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { - if (free < 0 && (table->refs[i] == 0)) { - free = i; - continue; - } - - if (table->refs[i] && - (vlan == (MLX4_VLAN_MASK & - be32_to_cpu(table->entries[i])))) { - /* Vlan already registered, increase refernce count */ - *index = i; - ++table->refs[i]; - goto out; - } - } - - if (table->total == table->max) { - /* No free vlan entries */ - err = -ENOSPC; - goto out; - } - - /* Register new MAC */ - table->refs[free] = 1; - table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); - - err = mlx4_set_port_vlan_table(dev, port, table->entries); - if (unlikely(err)) { - mlx4_warn(dev, "Failed adding vlan: %u\n", vlan); - table->refs[free] = 0; - table->entries[free] = 0; - goto out; - } - - *index = free; - ++table->total; -out: - mutex_unlock(&table->mutex); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_register_vlan); - -void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) -{ - struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; - - if (index < MLX4_VLAN_REGULAR) { - mlx4_warn(dev, "Trying to free special vlan index %d\n", index); - return; - } - - mutex_lock(&table->mutex); - if (!table->refs[index]) { - mlx4_warn(dev, "No vlan entry for index %d\n", index); - goto out; - } - if (--table->refs[index]) { - mlx4_dbg(dev, "Have more references for index %d," - "no need to modify vlan table\n", index); - goto out; - } - table->entries[index] = 0; - mlx4_set_port_vlan_table(dev, port, table->entries); - --table->total; -out: - mutex_unlock(&table->mutex); -} -EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); - -int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) -{ - struct mlx4_cmd_mailbox *mailbox; - int err; - u8 is_eth = dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memset(mailbox->buf, 0, 256); - if (is_eth) { - ((u8 *) mailbox->buf)[3] = 6; - ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15); - ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15); - } - err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} diff --git a/trunk/drivers/net/mlx4/qp.c b/trunk/drivers/net/mlx4/qp.c index 1c565ef8d179..c49a86044bf7 100644 --- a/trunk/drivers/net/mlx4/qp.c +++ b/trunk/drivers/net/mlx4/qp.c @@ -147,42 +147,19 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, } EXPORT_SYMBOL_GPL(mlx4_qp_modify); -int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - int qpn; - - qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align); - if (qpn == -1) - return -ENOMEM; - - *base = qpn; - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range); - -void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - if (base_qpn < dev->caps.sqp_start + 8) - return; - - mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt); -} -EXPORT_SYMBOL_GPL(mlx4_qp_release_range); - -int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp) +int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_qp_table *qp_table = &priv->qp_table; int err; - if (!qpn) - return -EINVAL; - - qp->qpn = qpn; + if (sqpn) + qp->qpn = sqpn; + else { + qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap); + if (qp->qpn == -1) + return -ENOMEM; + } err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn); if (err) @@ -231,6 +208,9 @@ int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp) mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); err_out: + if (!sqpn) + mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); + return err; } EXPORT_SYMBOL_GPL(mlx4_qp_alloc); @@ -259,6 +239,9 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); + + if (qp->qpn >= dev->caps.sqp_start + 8) + mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); } EXPORT_SYMBOL_GPL(mlx4_qp_free); @@ -272,7 +255,6 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) { struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; int err; - int reserved_from_top = 0; spin_lock_init(&qp_table->lock); INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); @@ -282,40 +264,9 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) * block of special QPs must be aligned to a multiple of 8, so * round up. */ - dev->caps.sqp_start = - ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8); - - { - int sort[MLX4_NUM_QP_REGION]; - int i, j, tmp; - int last_base = dev->caps.num_qps; - - for (i = 1; i < MLX4_NUM_QP_REGION; ++i) - sort[i] = i; - - for (i = MLX4_NUM_QP_REGION; i > 0; --i) { - for (j = 2; j < i; ++j) { - if (dev->caps.reserved_qps_cnt[sort[j]] > - dev->caps.reserved_qps_cnt[sort[j - 1]]) { - tmp = sort[j]; - sort[j] = sort[j - 1]; - sort[j - 1] = tmp; - } - } - } - - for (i = 1; i < MLX4_NUM_QP_REGION; ++i) { - last_base -= dev->caps.reserved_qps_cnt[sort[i]]; - dev->caps.reserved_qps_base[sort[i]] = last_base; - reserved_from_top += - dev->caps.reserved_qps_cnt[sort[i]]; - } - - } - + dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8); err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, - (1 << 23) - 1, dev->caps.sqp_start + 8, - reserved_from_top); + (1 << 24) - 1, dev->caps.sqp_start + 8); if (err) return err; diff --git a/trunk/drivers/net/mlx4/srq.c b/trunk/drivers/net/mlx4/srq.c index fe9f218691f5..533eb6db24b3 100644 --- a/trunk/drivers/net/mlx4/srq.c +++ b/trunk/drivers/net/mlx4/srq.c @@ -245,7 +245,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev) INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC); err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs, - dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0); + dev->caps.num_srqs - 1, dev->caps.reserved_srqs); if (err) return err; diff --git a/trunk/drivers/net/usb/pegasus.c b/trunk/drivers/net/usb/pegasus.c index 7914867110ed..38b90e7a7ed3 100644 --- a/trunk/drivers/net/usb/pegasus.c +++ b/trunk/drivers/net/usb/pegasus.c @@ -168,7 +168,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus) && printk_ratelimit()) dev_err(&pegasus->intf->dev, "%s, status %d\n", - __func__, ret); + __FUNCTION__, ret); goto out; } @@ -192,7 +192,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, if (!buffer) { if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __func__); + __FUNCTION__); return -ENOMEM; } memcpy(buffer, data, size); diff --git a/trunk/drivers/net/xtsonic.c b/trunk/drivers/net/xtsonic.c deleted file mode 100644 index da42aa06a3ba..000000000000 --- a/trunk/drivers/net/xtsonic.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * xtsonic.c - * - * (C) 2001 - 2007 Tensilica Inc. - * Kevin Chea - * Marc Gauthier - * Chris Zankel - * - * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) - * - * This driver is based on work from Andreas Busse, but most of - * the code is rewritten. - * - * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) - * - * A driver for the onboard Sonic ethernet controller on the XT2000. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static char xtsonic_string[] = "xtsonic"; - -extern unsigned xtboard_nvram_valid(void); -extern void xtboard_get_ether_addr(unsigned char *buf); - -#include "sonic.h" - -/* - * According to the documentation for the Sonic ethernet controller, - * EOBC should be 760 words (1520 bytes) for 32-bit applications, and, - * as such, 2 words less than the buffer size. The value for RBSIZE - * defined in sonic.h, however is only 1520. - * - * (Note that in 16-bit configurations, EOBC is 759 words (1518 bytes) and - * RBSIZE 1520 bytes) - */ -#undef SONIC_RBSIZE -#define SONIC_RBSIZE 1524 - -/* - * The chip provides 256 byte register space. - */ -#define SONIC_MEM_SIZE 0x100 - -/* - * Macros to access SONIC registers - */ -#define SONIC_READ(reg) \ - (0xffff & *((volatile unsigned int *)dev->base_addr+reg)) - -#define SONIC_WRITE(reg,val) \ - *((volatile unsigned int *)dev->base_addr+reg) = val - - -/* Use 0 for production, 1 for verification, and >2 for debug */ -#ifdef SONIC_DEBUG -static unsigned int sonic_debug = SONIC_DEBUG; -#else -static unsigned int sonic_debug = 1; -#endif - -/* - * We cannot use station (ethernet) address prefixes to detect the - * sonic controller since these are board manufacturer depended. - * So we check for known Silicon Revision IDs instead. - */ -static unsigned short known_revisions[] = -{ - 0x101, /* SONIC 83934 */ - 0xffff /* end of list */ -}; - -static int xtsonic_open(struct net_device *dev) -{ - if (request_irq(dev->irq,&sonic_interrupt,IRQF_DISABLED,"sonic",dev)) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - dev->name, dev->irq); - return -EAGAIN; - } - return sonic_open(dev); -} - -static int xtsonic_close(struct net_device *dev) -{ - int err; - err = sonic_close(dev); - free_irq(dev->irq, dev); - return err; -} - -static int __init sonic_probe1(struct net_device *dev) -{ - static unsigned version_printed = 0; - unsigned int silicon_revision; - struct sonic_local *lp = netdev_priv(dev); - unsigned int base_addr = dev->base_addr; - int i; - int err = 0; - - if (!request_mem_region(base_addr, 0x100, xtsonic_string)) - return -EBUSY; - - /* - * get the Silicon Revision ID. If this is one of the known - * one assume that we found a SONIC ethernet controller at - * the expected location. - */ - silicon_revision = SONIC_READ(SONIC_SR); - if (sonic_debug > 1) - printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); - - i = 0; - while ((known_revisions[i] != 0xffff) && - (known_revisions[i] != silicon_revision)) - i++; - - if (known_revisions[i] == 0xffff) { - printk("SONIC ethernet controller not found (0x%4x)\n", - silicon_revision); - return -ENODEV; - } - - if (sonic_debug && version_printed++ == 0) - printk(version); - - /* - * Put the sonic into software reset, then retrieve ethernet address. - * Note: we are assuming that the boot-loader has initialized the cam. - */ - SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - SONIC_WRITE(SONIC_DCR, - SONIC_DCR_WC0|SONIC_DCR_DW|SONIC_DCR_LBR|SONIC_DCR_SBUS); - SONIC_WRITE(SONIC_CEP,0); - SONIC_WRITE(SONIC_IMR,0); - - SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP,0); - - for (i=0; i<3; i++) { - unsigned int val = SONIC_READ(SONIC_CAP0-i); - dev->dev_addr[i*2] = val; - dev->dev_addr[i*2+1] = val >> 8; - } - - /* Initialize the device structure. */ - - lp->dma_bitmode = SONIC_BITMODE32; - - /* - * Allocate local private descriptor areas in uncached space. - * The entire structure must be located within the same 64kb segment. - * A simple way to ensure this is to allocate twice the - * size of the structure -- given that the structure is - * much less than 64 kB, at least one of the halves of - * the allocated area will be contained entirely in 64 kB. - * We also allocate extra space for a pointer to allow freeing - * this structure later on (in xtsonic_cleanup_module()). - */ - lp->descriptors = - dma_alloc_coherent(lp->device, - SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), - &lp->descriptors_laddr, GFP_KERNEL); - - if (lp->descriptors == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for " - " descriptors.\n", lp->device->bus_id); - goto out; - } - - lp->cda = lp->descriptors; - lp->tda = lp->cda + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - - /* get the virtual dma address */ - - lp->cda_laddr = lp->descriptors_laddr; - lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS - * SONIC_BUS_SCALE(lp->dma_bitmode)); - - dev->open = xtsonic_open; - dev->stop = xtsonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - dev->tx_timeout = sonic_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - - /* - * clear tally counter - */ - SONIC_WRITE(SONIC_CRCT,0xffff); - SONIC_WRITE(SONIC_FAET,0xffff); - SONIC_WRITE(SONIC_MPT,0xffff); - - return 0; -out: - release_region(dev->base_addr, SONIC_MEM_SIZE); - return err; -} - - -/* - * Probe for a SONIC ethernet controller on an XT2000 board. - * Actually probing is superfluous but we're paranoid. - */ - -int __init xtsonic_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct sonic_local *lp; - struct resource *resmem, *resirq; - int err = 0; - - DECLARE_MAC_BUF(mac); - - if ((resmem = platform_get_resource(pdev, IORESOURCE_MEM, 0)) == NULL) - return -ENODEV; - - if ((resirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0)) == NULL) - return -ENODEV; - - if ((dev = alloc_etherdev(sizeof(struct sonic_local))) == NULL) - return -ENOMEM; - - lp = netdev_priv(dev); - lp->device = &pdev->dev; - SET_NETDEV_DEV(dev, &pdev->dev); - netdev_boot_setup_check(dev); - - dev->base_addr = resmem->start; - dev->irq = resirq->start; - - if ((err = sonic_probe1(dev))) - goto out; - if ((err = register_netdev(dev))) - goto out1; - - printk("%s: SONIC ethernet @%08lx, MAC %s, IRQ %d\n", dev->name, - dev->base_addr, print_mac(mac, dev->dev_addr), dev->irq); - - return 0; - -out1: - release_region(dev->base_addr, SONIC_MEM_SIZE); -out: - free_netdev(dev); - - return err; -} - -MODULE_DESCRIPTION("Xtensa XT2000 SONIC ethernet driver"); -module_param(sonic_debug, int, 0); -MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)"); - -#include "sonic.c" - -static int __devexit xtsonic_device_remove (struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct sonic_local *lp = netdev_priv(dev); - - unregister_netdev(dev); - dma_free_coherent(lp->device, - SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), - lp->descriptors, lp->descriptors_laddr); - release_region (dev->base_addr, SONIC_MEM_SIZE); - free_netdev(dev); - - return 0; -} - -static struct platform_driver xtsonic_driver = { - .probe = xtsonic_probe, - .remove = __devexit_p(xtsonic_device_remove), - .driver = { - .name = xtsonic_string, - }, -}; - -static int __init xtsonic_init(void) -{ - return platform_driver_register(&xtsonic_driver); -} - -static void __exit xtsonic_cleanup(void) -{ - platform_driver_unregister(&xtsonic_driver); -} - -module_init(xtsonic_init); -module_exit(xtsonic_cleanup); diff --git a/trunk/drivers/of/of_i2c.c b/trunk/drivers/of/of_i2c.c index 24bbef777c19..6a98dc8aa30b 100644 --- a/trunk/drivers/of/of_i2c.c +++ b/trunk/drivers/of/of_i2c.c @@ -41,7 +41,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, info.addr = *addr; - request_module("%s", info.type); + request_module(info.type); result = i2c_new_device(adap, &info); if (result == NULL) { diff --git a/trunk/drivers/of/of_spi.c b/trunk/drivers/of/of_spi.c index bed0ed6dcdc1..b01eec026f68 100644 --- a/trunk/drivers/of/of_spi.c +++ b/trunk/drivers/of/of_spi.c @@ -61,8 +61,6 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) spi->mode |= SPI_CPHA; if (of_find_property(nc, "spi-cpol", NULL)) spi->mode |= SPI_CPOL; - if (of_find_property(nc, "spi-cs-high", NULL)) - spi->mode |= SPI_CS_HIGH; /* Device speed */ prop = of_get_property(nc, "spi-max-frequency", &len); diff --git a/trunk/drivers/oprofile/buffer_sync.c b/trunk/drivers/oprofile/buffer_sync.c index 37681700b61a..ed982273fb8b 100644 --- a/trunk/drivers/oprofile/buffer_sync.c +++ b/trunk/drivers/oprofile/buffer_sync.c @@ -628,27 +628,3 @@ void sync_buffer(int cpu) mutex_unlock(&buffer_mutex); } - -/* The function can be used to add a buffer worth of data directly to - * the kernel buffer. The buffer is assumed to be a circular buffer. - * Take the entries from index start and end at index end, wrapping - * at max_entries. - */ -void oprofile_put_buff(unsigned long *buf, unsigned int start, - unsigned int stop, unsigned int max) -{ - int i; - - i = start; - - mutex_lock(&buffer_mutex); - while (i != stop) { - add_event_entry(buf[i++]); - - if (i >= max) - i = 0; - } - - mutex_unlock(&buffer_mutex); -} - diff --git a/trunk/drivers/oprofile/cpu_buffer.c b/trunk/drivers/oprofile/cpu_buffer.c index 7ba39fe20a8a..e1bd5a937f6c 100644 --- a/trunk/drivers/oprofile/cpu_buffer.c +++ b/trunk/drivers/oprofile/cpu_buffer.c @@ -38,26 +38,13 @@ static int work_enabled; void free_cpu_buffers(void) { int i; - + for_each_online_cpu(i) { vfree(per_cpu(cpu_buffer, i).buffer); per_cpu(cpu_buffer, i).buffer = NULL; } } -unsigned long oprofile_get_cpu_buffer_size(void) -{ - return fs_cpu_buffer_size; -} - -void oprofile_cpu_buffer_inc_smpl_lost(void) -{ - struct oprofile_cpu_buffer *cpu_buf - = &__get_cpu_var(cpu_buffer); - - cpu_buf->sample_lost_overflow++; -} - int alloc_cpu_buffers(void) { int i; diff --git a/trunk/drivers/oprofile/event_buffer.h b/trunk/drivers/oprofile/event_buffer.h index 84bf324c5771..5076ed1ebd8f 100644 --- a/trunk/drivers/oprofile/event_buffer.h +++ b/trunk/drivers/oprofile/event_buffer.h @@ -17,13 +17,6 @@ int alloc_event_buffer(void); void free_event_buffer(void); -/** - * Add data to the event buffer. - * The data passed is free-form, but typically consists of - * file offsets, dcookies, context information, and ESCAPE codes. - */ -void add_event_entry(unsigned long data); - /* wake up the process sleeping on the event file */ void wake_up_buffer_waiter(void); diff --git a/trunk/drivers/parisc/ccio-dma.c b/trunk/drivers/parisc/ccio-dma.c index dcc1e9958d2f..b30e38f3a50d 100644 --- a/trunk/drivers/parisc/ccio-dma.c +++ b/trunk/drivers/parisc/ccio-dma.c @@ -66,8 +66,15 @@ #undef DEBUG_CCIO_RUN_SG #ifdef CONFIG_PROC_FS -/* depends on proc fs support. But costs CPU performance. */ -#undef CCIO_COLLECT_STATS +/* + * CCIO_SEARCH_TIME can help measure how fast the bitmap search is. + * impacts performance though - ditch it if you don't use it. + */ +#define CCIO_SEARCH_TIME +#undef CCIO_MAP_STATS +#else +#undef CCIO_SEARCH_TIME +#undef CCIO_MAP_STATS #endif #include @@ -232,10 +239,12 @@ struct ioc { u32 res_size; /* size of resource map in bytes */ spinlock_t res_lock; -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_SEARCH_TIME #define CCIO_SEARCH_SAMPLE 0x100 unsigned long avg_search[CCIO_SEARCH_SAMPLE]; unsigned long avg_idx; /* current index into avg_search */ +#endif +#ifdef CCIO_MAP_STATS unsigned long used_pages; unsigned long msingle_calls; unsigned long msingle_pages; @@ -342,7 +351,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) unsigned int pages_needed = size >> IOVP_SHIFT; unsigned int res_idx; unsigned long boundary_size; -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_SEARCH_TIME unsigned long cr_start = mfctl(16); #endif @@ -397,7 +406,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) DBG_RES("%s() res_idx %d res_hint: %d\n", __func__, res_idx, ioc->res_hint); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_SEARCH_TIME { unsigned long cr_end = mfctl(16); unsigned long tmp = cr_end - cr_start; @@ -407,7 +416,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) ioc->avg_search[ioc->avg_idx++] = cr_start; ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1; #endif -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->used_pages += pages_needed; #endif /* @@ -443,7 +452,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) DBG_RES("%s(): res_idx: %d pages_mapped %d\n", __func__, res_idx, pages_mapped); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->used_pages -= pages_mapped; #endif @@ -755,7 +764,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size, size = ALIGN(size + offset, IOVP_SIZE); spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->msingle_calls++; ioc->msingle_pages += size >> IOVP_SHIFT; #endif @@ -819,7 +828,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size, spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->usingle_calls++; ioc->usingle_pages += size >> IOVP_SHIFT; #endif @@ -885,7 +894,7 @@ ccio_free_consistent(struct device *dev, size_t size, void *cpu_addr, */ #define PIDE_FLAG 0x80000000UL -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS #define IOMMU_MAP_STATS #endif #include "iommu-helpers.h" @@ -929,7 +938,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->msg_calls++; #endif @@ -988,13 +997,13 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, DBG_RUN_SG("%s() START %d entries, %08lx,%x\n", __func__, nents, sg_virt_addr(sglist), sglist->length); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->usg_calls++; #endif while(sg_dma_len(sglist) && nents--) { -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; #endif ccio_unmap_single(dev, sg_dma_address(sglist), @@ -1039,7 +1048,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n", total_pages * 8, total_pages); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n", total_pages - ioc->used_pages, ioc->used_pages, (int)(ioc->used_pages * 100 / total_pages)); @@ -1048,7 +1057,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n", ioc->res_size, total_pages); -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_SEARCH_TIME min = max = ioc->avg_search[0]; for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) { avg += ioc->avg_search[j]; @@ -1061,7 +1070,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max); #endif -#ifdef CCIO_COLLECT_STATS +#ifdef CCIO_MAP_STATS len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", ioc->msingle_calls, ioc->msingle_pages, (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); @@ -1079,7 +1088,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", ioc->usg_calls, ioc->usg_pages, (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); -#endif /* CCIO_COLLECT_STATS */ +#endif /* CCIO_MAP_STATS */ ioc = ioc->next; } diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c index 96f3bdf0ec4b..8a846adf1dcf 100644 --- a/trunk/drivers/parport/parport_pc.c +++ b/trunk/drivers/parport/parport_pc.c @@ -2791,7 +2791,6 @@ enum parport_pc_pci_cards { oxsemi_952, oxsemi_954, oxsemi_840, - oxsemi_pcie_pport, aks_0100, mobility_pp, netmos_9705, @@ -2869,7 +2868,6 @@ static struct parport_pc_pci { /* oxsemi_952 */ { 1, { { 0, 1 }, } }, /* oxsemi_954 */ { 1, { { 0, -1 }, } }, /* oxsemi_840 */ { 1, { { 0, 1 }, } }, - /* oxsemi_pcie_pport */ { 1, { { 0, 1 }, } }, /* aks_0100 */ { 1, { { 0, -1 }, } }, /* mobility_pp */ { 1, { { 0, 1 }, } }, /* netmos_9705 */ { 1, { { 0, -1 }, } }, /* untested */ @@ -2930,6 +2928,7 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { { 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a }, { 0x1409, 0x7268, 0x1409, 0x0104, 0, 0, timedia_4018 }, { 0x1409, 0x7268, 0x1409, 0x9018, 0, 0, timedia_9018a }, + { 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_2P_EPP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP, @@ -2947,25 +2946,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_954 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_12PCI840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_840 }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe840, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe840_G, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_0, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_0_G, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_G, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_U, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport }, { PCI_VENDOR_ID_AKS, PCI_DEVICE_ID_AKS_ALADDINCARD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, aks_0100 }, - { 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp }, /* NetMos communication controllers */ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9705 }, diff --git a/trunk/drivers/pcmcia/Makefile b/trunk/drivers/pcmcia/Makefile index 23e492bf75cf..b46c60b72708 100644 --- a/trunk/drivers/pcmcia/Makefile +++ b/trunk/drivers/pcmcia/Makefile @@ -70,7 +70,7 @@ pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o -pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o +pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 847481dc8d72..f660ef3e5b29 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -246,16 +246,6 @@ config RTC_DRV_TWL92330 platforms. The support is integrated with the rest of the Menelaus driver; it's not separate module. -config RTC_DRV_TWL4030 - tristate "TI TWL4030/TWL5030/TPS659x0" - depends on RTC_CLASS && TWL4030_CORE - help - If you say yes here you get support for the RTC on the - TWL4030 family chips, used mostly with OMAP3 platforms. - - This driver can also be built as a module. If so, the module - will be called rtc-twl4030. - config RTC_DRV_S35390A tristate "Seiko Instruments S-35390A" select BITREVERSE @@ -620,14 +610,6 @@ config RTC_DRV_RS5C313 help If you say yes here you get support for the Ricoh RS5C313 RTC chips. -config RTC_DRV_PARISC - tristate "PA-RISC firmware RTC support" - depends on PARISC - help - Say Y or M here to enable RTC support on PA-RISC systems using - firmware calls. If you do not know what you are doing, you should - just say Y. - config RTC_DRV_PPC tristate "PowerPC machine dependent RTC support" depends on PPC diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index e9e8474cc8fe..d05928b3ca94 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -51,7 +51,6 @@ obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o -obj-$(CONFIG_RTC_DRV_PARISC) += rtc-parisc.o obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o @@ -63,7 +62,6 @@ obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o diff --git a/trunk/drivers/rtc/rtc-parisc.c b/trunk/drivers/rtc/rtc-parisc.c deleted file mode 100644 index 346d633655e7..000000000000 --- a/trunk/drivers/rtc/rtc-parisc.c +++ /dev/null @@ -1,111 +0,0 @@ -/* rtc-parisc: RTC for HP PA-RISC firmware - * - * Copyright (C) 2008 Kyle McMartin - */ - -#include -#include -#include -#include - -#include - -/* as simple as can be, and no simpler. */ -struct parisc_rtc { - struct rtc_device *rtc; - spinlock_t lock; -}; - -static int parisc_get_time(struct device *dev, struct rtc_time *tm) -{ - struct parisc_rtc *p = dev_get_drvdata(dev); - unsigned long flags, ret; - - spin_lock_irqsave(&p->lock, flags); - ret = get_rtc_time(tm); - spin_unlock_irqrestore(&p->lock, flags); - - if (ret & RTC_BATT_BAD) - return -EOPNOTSUPP; - - return 0; -} - -static int parisc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct parisc_rtc *p = dev_get_drvdata(dev); - unsigned long flags, ret; - - spin_lock_irqsave(&p->lock, flags); - ret = set_rtc_time(tm); - spin_unlock_irqrestore(&p->lock, flags); - - if (ret < 0) - return -EOPNOTSUPP; - - return 0; -} - -static const struct rtc_class_ops parisc_rtc_ops = { - .read_time = parisc_get_time, - .set_time = parisc_set_time, -}; - -static int __devinit parisc_rtc_probe(struct platform_device *dev) -{ - struct parisc_rtc *p; - - p = kzalloc(sizeof (*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - spin_lock_init(&p->lock); - - p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, - THIS_MODULE); - if (IS_ERR(p->rtc)) { - int err = PTR_ERR(p->rtc); - kfree(p); - return err; - } - - platform_set_drvdata(dev, p); - - return 0; -} - -static int __devexit parisc_rtc_remove(struct platform_device *dev) -{ - struct parisc_rtc *p = platform_get_drvdata(dev); - - rtc_device_unregister(p->rtc); - kfree(p); - - return 0; -} - -static struct platform_driver parisc_rtc_driver = { - .driver = { - .name = "rtc-parisc", - .owner = THIS_MODULE, - }, - .probe = parisc_rtc_probe, - .remove = __devexit_p(parisc_rtc_remove), -}; - -static int __init parisc_rtc_init(void) -{ - return platform_driver_register(&parisc_rtc_driver); -} - -static void __exit parisc_rtc_fini(void) -{ - platform_driver_unregister(&parisc_rtc_driver); -} - -module_init(parisc_rtc_init); -module_exit(parisc_rtc_fini); - -MODULE_AUTHOR("Kyle McMartin "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("HP PA-RISC RTC driver"); diff --git a/trunk/drivers/rtc/rtc-twl4030.c b/trunk/drivers/rtc/rtc-twl4030.c deleted file mode 100644 index abe87a4d2665..000000000000 --- a/trunk/drivers/rtc/rtc-twl4030.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * rtc-twl4030.c -- TWL4030 Real Time Clock interface - * - * Copyright (C) 2007 MontaVista Software, Inc - * Author: Alexandre Rusev - * - * Based on original TI driver twl4030-rtc.c - * Copyright (C) 2006 Texas Instruments, Inc. - * - * Based on rtc-omap.c - * Copyright (C) 2003 MontaVista Software, Inc. - * Author: George G. Davis or - * Copyright (C) 2006 David Brownell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -/* - * RTC block register offsets (use TWL_MODULE_RTC) - */ -#define REG_SECONDS_REG 0x00 -#define REG_MINUTES_REG 0x01 -#define REG_HOURS_REG 0x02 -#define REG_DAYS_REG 0x03 -#define REG_MONTHS_REG 0x04 -#define REG_YEARS_REG 0x05 -#define REG_WEEKS_REG 0x06 - -#define REG_ALARM_SECONDS_REG 0x07 -#define REG_ALARM_MINUTES_REG 0x08 -#define REG_ALARM_HOURS_REG 0x09 -#define REG_ALARM_DAYS_REG 0x0A -#define REG_ALARM_MONTHS_REG 0x0B -#define REG_ALARM_YEARS_REG 0x0C - -#define REG_RTC_CTRL_REG 0x0D -#define REG_RTC_STATUS_REG 0x0E -#define REG_RTC_INTERRUPTS_REG 0x0F - -#define REG_RTC_COMP_LSB_REG 0x10 -#define REG_RTC_COMP_MSB_REG 0x11 - -/* RTC_CTRL_REG bitfields */ -#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 -#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 -#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 -#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 -#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 -#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 -#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 - -/* RTC_STATUS_REG bitfields */ -#define BIT_RTC_STATUS_REG_RUN_M 0x02 -#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 -#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 -#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 -#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 -#define BIT_RTC_STATUS_REG_ALARM_M 0x40 -#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 - -/* RTC_INTERRUPTS_REG bitfields */ -#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 -#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 -#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 - - -/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ -#define ALL_TIME_REGS 6 - -/*----------------------------------------------------------------------*/ - -/* - * Supports 1 byte read from TWL4030 RTC register. - */ -static int twl4030_rtc_read_u8(u8 *data, u8 reg) -{ - int ret; - - ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); - if (ret < 0) - pr_err("twl4030_rtc: Could not read TWL4030" - "register %X - error %d\n", reg, ret); - return ret; -} - -/* - * Supports 1 byte write to TWL4030 RTC registers. - */ -static int twl4030_rtc_write_u8(u8 data, u8 reg) -{ - int ret; - - ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); - if (ret < 0) - pr_err("twl4030_rtc: Could not write TWL4030" - "register %X - error %d\n", reg, ret); - return ret; -} - -/* - * Cache the value for timer/alarm interrupts register; this is - * only changed by callers holding rtc ops lock (or resume). - */ -static unsigned char rtc_irq_bits; - -/* - * Enable timer and/or alarm interrupts. - */ -static int set_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - int ret; - - val = rtc_irq_bits | bit; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); - if (ret == 0) - rtc_irq_bits = val; - - return ret; -} - -/* - * Disable timer and/or alarm interrupts. - */ -static int mask_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - int ret; - - val = rtc_irq_bits & ~bit; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); - if (ret == 0) - rtc_irq_bits = val; - - return ret; -} - -static inline int twl4030_rtc_alarm_irq_set_state(int enabled) -{ - int ret; - - if (enabled) - ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - else - ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - - return ret; -} - -static inline int twl4030_rtc_irq_set_state(int enabled) -{ - int ret; - - if (enabled) - ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - else - ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - - return ret; -} - -/* - * Gets current TWL4030 RTC time and date parameters. - * - * The RTC's time/alarm representation is not what gmtime(3) requires - * Linux to use: - * - * - Months are 1..12 vs Linux 0-11 - * - Years are 0..99 vs Linux 1900..N (we assume 21st century) - */ -static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - u8 save_control; - - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) - return ret; - - save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; - - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) - return ret; - - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); - - if (ret < 0) { - dev_err(dev, "rtc_read_time error %d\n", ret); - return ret; - } - - tm->tm_sec = bcd2bin(rtc_data[0]); - tm->tm_min = bcd2bin(rtc_data[1]); - tm->tm_hour = bcd2bin(rtc_data[2]); - tm->tm_mday = bcd2bin(rtc_data[3]); - tm->tm_mon = bcd2bin(rtc_data[4]) - 1; - tm->tm_year = bcd2bin(rtc_data[5]) + 100; - - return ret; -} - -static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - unsigned char save_control; - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - - rtc_data[1] = bin2bcd(tm->tm_sec); - rtc_data[2] = bin2bcd(tm->tm_min); - rtc_data[3] = bin2bcd(tm->tm_hour); - rtc_data[4] = bin2bcd(tm->tm_mday); - rtc_data[5] = bin2bcd(tm->tm_mon + 1); - rtc_data[6] = bin2bcd(tm->tm_year - 100); - - /* Stop RTC while updating the TC registers */ - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) - goto out; - - save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; - twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) - goto out; - - /* update all the time registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); - if (ret < 0) { - dev_err(dev, "rtc_set_time error %d\n", ret); - goto out; - } - - /* Start back RTC */ - save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - -out: - return ret; -} - -/* - * Gets current TWL4030 RTC alarm time. - */ -static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); - if (ret < 0) { - dev_err(dev, "rtc_read_alarm error %d\n", ret); - return ret; - } - - /* some of these fields may be wildcard/"match all" */ - alm->time.tm_sec = bcd2bin(rtc_data[0]); - alm->time.tm_min = bcd2bin(rtc_data[1]); - alm->time.tm_hour = bcd2bin(rtc_data[2]); - alm->time.tm_mday = bcd2bin(rtc_data[3]); - alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; - alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; - - /* report cached alarm enable state */ - if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) - alm->enabled = 1; - - return ret; -} - -static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - unsigned char alarm_data[ALL_TIME_REGS + 1]; - int ret; - - ret = twl4030_rtc_alarm_irq_set_state(0); - if (ret) - goto out; - - alarm_data[1] = bin2bcd(alm->time.tm_sec); - alarm_data[2] = bin2bcd(alm->time.tm_min); - alarm_data[3] = bin2bcd(alm->time.tm_hour); - alarm_data[4] = bin2bcd(alm->time.tm_mday); - alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); - alarm_data[6] = bin2bcd(alm->time.tm_year - 100); - - /* update all the alarm registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); - if (ret) { - dev_err(dev, "rtc_set_alarm error %d\n", ret); - goto out; - } - - if (alm->enabled) - ret = twl4030_rtc_alarm_irq_set_state(1); -out: - return ret; -} - -#ifdef CONFIG_RTC_INTF_DEV - -static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { - case RTC_AIE_OFF: - return twl4030_rtc_alarm_irq_set_state(0); - case RTC_AIE_ON: - return twl4030_rtc_alarm_irq_set_state(1); - case RTC_UIE_OFF: - return twl4030_rtc_irq_set_state(0); - case RTC_UIE_ON: - return twl4030_rtc_irq_set_state(1); - - default: - return -ENOIOCTLCMD; - } -} - -#else -#define omap_rtc_ioctl NULL -#endif - -static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) -{ - unsigned long events = 0; - int ret = IRQ_NONE; - int res; - u8 rd_reg; - -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate. Although it might be - * friendlier not to borrow this thread context... - */ - local_irq_enable(); -#endif - - res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); - if (res) - goto out; - /* - * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. - * only one (ALARM or RTC) interrupt source may be enabled - * at time, we also could check our results - * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] - */ - if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) - events |= RTC_IRQF | RTC_AF; - else - events |= RTC_IRQF | RTC_UF; - - res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, - REG_RTC_STATUS_REG); - if (res) - goto out; - - /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 - * needs 2 reads to clear the interrupt. One read is done in - * do_twl4030_pwrirq(). Doing the second read, to clear - * the bit. - * - * FIXME the reason PWR_ISR1 needs an extra read is that - * RTC_IF retriggered until we cleared REG_ALARM_M above. - * But re-reading like this is a bad hack; by doing so we - * risk wrongly clearing status for some other IRQ (losing - * the interrupt). Be smarter about handling RTC_UF ... - */ - res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, - &rd_reg, TWL4030_INT_PWR_ISR1); - if (res) - goto out; - - /* Notify RTC core on event */ - rtc_update_irq(rtc, 1, events); - - ret = IRQ_HANDLED; -out: - return ret; -} - -static struct rtc_class_ops twl4030_rtc_ops = { - .ioctl = twl4030_rtc_ioctl, - .read_time = twl4030_rtc_read_time, - .set_time = twl4030_rtc_set_time, - .read_alarm = twl4030_rtc_read_alarm, - .set_alarm = twl4030_rtc_set_alarm, -}; - -/*----------------------------------------------------------------------*/ - -static int __devinit twl4030_rtc_probe(struct platform_device *pdev) -{ - struct rtc_device *rtc; - int ret = 0; - int irq = platform_get_irq(pdev, 0); - u8 rd_reg; - - if (irq < 0) - return irq; - - rtc = rtc_device_register(pdev->name, - &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - ret = -EINVAL; - dev_err(&pdev->dev, "can't register RTC device, err %ld\n", - PTR_ERR(rtc)); - goto out0; - - } - - platform_set_drvdata(pdev, rtc); - - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); - - if (ret < 0) - goto out1; - - if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) - dev_warn(&pdev->dev, "Power up reset detected.\n"); - - if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) - dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); - - /* Clear RTC Power up reset and pending alarm interrupts */ - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); - if (ret < 0) - goto out1; - - ret = request_irq(irq, twl4030_rtc_interrupt, - IRQF_TRIGGER_RISING, - rtc->dev.bus_id, rtc); - if (ret < 0) { - dev_err(&pdev->dev, "IRQ is not free.\n"); - goto out1; - } - - /* Check RTC module status, Enable if it is off */ - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); - if (ret < 0) - goto out2; - - if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { - dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); - rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); - if (ret < 0) - goto out2; - } - - /* init cached IRQ enable bits */ - ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); - if (ret < 0) - goto out2; - - return ret; - - -out2: - free_irq(irq, rtc); -out1: - rtc_device_unregister(rtc); -out0: - return ret; -} - -/* - * Disable all TWL4030 RTC module interrupts. - * Sets status flag to free. - */ -static int __devexit twl4030_rtc_remove(struct platform_device *pdev) -{ - /* leave rtc running, but disable irqs */ - struct rtc_device *rtc = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - - free_irq(irq, rtc); - - rtc_device_unregister(rtc); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static void twl4030_rtc_shutdown(struct platform_device *pdev) -{ - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); -} - -#ifdef CONFIG_PM - -static unsigned char irqstat; - -static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) -{ - irqstat = rtc_irq_bits; - - /* REVISIT alarm may need to wake us from sleep */ - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - return 0; -} - -static int twl4030_rtc_resume(struct platform_device *pdev) -{ - set_rtc_irq_bit(irqstat); - return 0; -} - -#else -#define twl4030_rtc_suspend NULL -#define twl4030_rtc_resume NULL -#endif - -MODULE_ALIAS("platform:twl4030_rtc"); - -static struct platform_driver twl4030rtc_driver = { - .probe = twl4030_rtc_probe, - .remove = __devexit_p(twl4030_rtc_remove), - .shutdown = twl4030_rtc_shutdown, - .suspend = twl4030_rtc_suspend, - .resume = twl4030_rtc_resume, - .driver = { - .owner = THIS_MODULE, - .name = "twl4030_rtc", - }, -}; - -static int __init twl4030_rtc_init(void) -{ - return platform_driver_register(&twl4030rtc_driver); -} -module_init(twl4030_rtc_init); - -static void __exit twl4030_rtc_exit(void) -{ - platform_driver_unregister(&twl4030rtc_driver); -} -module_exit(twl4030_rtc_exit); - -MODULE_AUTHOR("Texas Instruments, MontaVista Software"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/serial/8250_pci.c b/trunk/drivers/serial/8250_pci.c index 5450a0e5ecdb..c014ffb110e9 100644 --- a/trunk/drivers/serial/8250_pci.c +++ b/trunk/drivers/serial/8250_pci.c @@ -1100,8 +1100,6 @@ enum pci_board_num_t { pbn_b0_4_1843200_200, pbn_b0_8_1843200_200, - pbn_b0_1_4000000, - pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, pbn_b0_bt_8_115200, @@ -1169,10 +1167,6 @@ enum pci_board_num_t { pbn_exsys_4055, pbn_plx_romulus, pbn_oxsemi, - pbn_oxsemi_1_4000000, - pbn_oxsemi_2_4000000, - pbn_oxsemi_4_4000000, - pbn_oxsemi_8_4000000, pbn_intel_i960, pbn_sgi_ioc3, pbn_computone_4, @@ -1296,12 +1290,6 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 1843200, .uart_offset = 0x200, }, - [pbn_b0_1_4000000] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 4000000, - .uart_offset = 8, - }, [pbn_b0_bt_1_115200] = { .flags = FL_BASE0|FL_BASE_BARS, @@ -1637,35 +1625,6 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, - [pbn_oxsemi_1_4000000] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 4000000, - .uart_offset = 0x200, - .first_offset = 0x1000, - }, - [pbn_oxsemi_2_4000000] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 4000000, - .uart_offset = 0x200, - .first_offset = 0x1000, - }, - [pbn_oxsemi_4_4000000] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 4000000, - .uart_offset = 0x200, - .first_offset = 0x1000, - }, - [pbn_oxsemi_8_4000000] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 4000000, - .uart_offset = 0x200, - .first_offset = 0x1000, - }, - /* * EKF addition for i960 Boards form EKF with serial port. @@ -1854,39 +1813,6 @@ serial_pci_matches(struct pciserial_board *board, board->first_offset == guessed->first_offset; } -/* - * Oxford Semiconductor Inc. - * Check that device is part of the Tornado range of devices, then determine - * the number of ports available on the device. - */ -static int pci_oxsemi_tornado_init(struct pci_dev *dev, struct pciserial_board *board) -{ - u8 __iomem *p; - unsigned long deviceID; - unsigned int number_uarts; - - /* OxSemi Tornado devices are all 0xCxxx */ - if (dev->vendor == PCI_VENDOR_ID_OXSEMI && - (dev->device & 0xF000) != 0xC000) - return 0; - - p = pci_iomap(dev, 0, 5); - if (p == NULL) - return -ENOMEM; - - deviceID = ioread32(p); - /* Tornado device */ - if (deviceID == 0x07000200) { - number_uarts = ioread8(p + 4); - board->num_ports = number_uarts; - printk(KERN_DEBUG - "%d ports detected on Oxford PCI Express device\n", - number_uarts); - } - pci_iounmap(dev, p); - return 0; -} - struct serial_private * pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board) { @@ -1895,13 +1821,6 @@ pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board) struct pci_serial_quirk *quirk; int rc, nr_ports, i; - /* - * Find number of ports on board - */ - if (dev->vendor == PCI_VENDOR_ID_OXSEMI || - dev->vendor == PCI_VENDOR_ID_MAINPINE) - pci_oxsemi_tornado_init(dev, board); - nr_ports = board->num_ports; /* @@ -2381,156 +2300,6 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, - /* - * Oxford Semiconductor Inc. Tornado PCI express device range. - */ - { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */ - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, - /* - * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado - */ - { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */ - PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0, - pbn_oxsemi_1_4000000 }, - { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */ - PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0, - pbn_oxsemi_2_4000000 }, - { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */ - PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0, - pbn_oxsemi_4_4000000 }, - { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ - PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, - pbn_oxsemi_8_4000000 }, /* * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, * from skokodyn@yahoo.com diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index c94d3c4b7521..db783b77a881 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -457,7 +457,7 @@ config SERIAL_SAMSUNG config SERIAL_SAMSUNG_DEBUG bool "Samsung SoC serial debug" - depends on SERIAL_SAMSUNG && DEBUG_LL + depends on SERIAL_SAMSUNG help Add support for debugging the serial driver. Since this is generally being used as a console, we use our own output diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index c23a9857ee67..bcefbddeba50 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -97,8 +97,6 @@ source "drivers/usb/core/Kconfig" source "drivers/usb/mon/Kconfig" -source "drivers/usb/wusbcore/Kconfig" - source "drivers/usb/host/Kconfig" source "drivers/usb/musb/Kconfig" diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index 8b7c419b876e..a419c42e880e 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -16,12 +16,9 @@ obj-$(CONFIG_USB_UHCI_HCD) += host/ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ -obj-$(CONFIG_USB_HWA_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ -obj-$(CONFIG_USB_WUSB) += wusbcore/ - obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_PRINTER) += class/ diff --git a/trunk/drivers/usb/host/Kconfig b/trunk/drivers/usb/host/Kconfig index 72fb655e6033..228797e54f9c 100644 --- a/trunk/drivers/usb/host/Kconfig +++ b/trunk/drivers/usb/host/Kconfig @@ -305,31 +305,3 @@ config SUPERH_ON_CHIP_R8A66597 help This driver enables support for the on-chip R8A66597 in the SH7366 and SH7723 processors. - -config USB_WHCI_HCD - tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on PCI && USB - select USB_WUSB - select UWB_WHCI - help - A driver for PCI-based Wireless USB Host Controllers that are - compliant with the WHCI specification. - - To compile this driver a module, choose M here: the module - will be called "whci-hcd". - -config USB_HWA_HCD - tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on USB - select USB_WUSB - select UWB_HWA - help - This driver enables you to connect Wireless USB devices to - your system using a Host Wire Adaptor USB dongle. This is an - UWB Radio Controller and WUSB Host Controller connected to - your machine via USB (specified in WUSB1.0). - - To compile this driver a module, choose M here: the module - will be called "hwa-hc". diff --git a/trunk/drivers/usb/host/Makefile b/trunk/drivers/usb/host/Makefile index 23be22224044..f1edda2dcfde 100644 --- a/trunk/drivers/usb/host/Makefile +++ b/trunk/drivers/usb/host/Makefile @@ -8,8 +8,6 @@ endif isp1760-objs := isp1760-hcd.o isp1760-if.o -obj-$(CONFIG_USB_WHCI_HCD) += whci/ - obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o @@ -21,4 +19,3 @@ obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o -obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o diff --git a/trunk/drivers/usb/host/hwa-hc.c b/trunk/drivers/usb/host/hwa-hc.c deleted file mode 100644 index 64be4d88df11..000000000000 --- a/trunk/drivers/usb/host/hwa-hc.c +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Host Wire Adapter: - * Driver glue, HWA-specific functions, bridges to WAHC and WUSBHC - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * The HWA driver is a simple layer that forwards requests to the WAHC - * (Wire Adater Host Controller) or WUSBHC (Wireless USB Host - * Controller) layers. - * - * Host Wire Adapter is the 'WUSB 1.0 standard' name for Wireless-USB - * Host Controller that is connected to your system via USB (a USB - * dongle that implements a USB host...). There is also a Device Wired - * Adaptor, DWA (Wireless USB hub) that uses the same mechanism for - * transferring data (it is after all a USB host connected via - * Wireless USB), we have a common layer called Wire Adapter Host - * Controller that does all the hard work. The WUSBHC (Wireless USB - * Host Controller) is the part common to WUSB Host Controllers, the - * HWA and the PCI-based one, that is implemented following the WHCI - * spec. All these layers are implemented in ../wusbcore. - * - * The main functions are hwahc_op_urb_{en,de}queue(), that pass the - * job of converting a URB to a Wire Adapter - * - * Entry points: - * - * hwahc_driver_*() Driver initialization, registration and - * teardown. - * - * hwahc_probe() New device came up, create an instance for - * it [from device enumeration]. - * - * hwahc_disconnect() Remove device instance [from device - * enumeration]. - * - * [__]hwahc_op_*() Host-Wire-Adaptor specific functions for - * starting/stopping/etc (some might be made also - * DWA). - */ -#include -#include -#include -#include -#include -#include -#include -#include "../wusbcore/wa-hc.h" -#include "../wusbcore/wusbhc.h" - -#define D_LOCAL 0 -#include - -struct hwahc { - struct wusbhc wusbhc; /* has to be 1st */ - struct wahc wa; - u8 buffer[16]; /* for misc usb transactions */ -}; - -/** - * FIXME should be wusbhc - * - * NOTE: we need to cache the Cluster ID because later...there is no - * way to get it :) - */ -static int __hwahc_set_cluster_id(struct hwahc *hwahc, u8 cluster_id) -{ - int result; - struct wusbhc *wusbhc = &hwahc->wusbhc; - struct wahc *wa = &hwahc->wa; - struct device *dev = &wa->usb_iface->dev; - - result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_SET_CLUSTER_ID, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - cluster_id, - wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) - dev_err(dev, "Cannot set WUSB Cluster ID to 0x%02x: %d\n", - cluster_id, result); - else - wusbhc->cluster_id = cluster_id; - dev_info(dev, "Wireless USB Cluster ID set to 0x%02x\n", cluster_id); - return result; -} - -static int __hwahc_op_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots) -{ - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - - return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_SET_NUM_DNTS, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - interval << 8 | slots, - wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); -} - -/* - * Reset a WUSB host controller and wait for it to complete doing it. - * - * @usb_hcd: Pointer to WUSB Host Controller instance. - * - */ -static int hwahc_op_reset(struct usb_hcd *usb_hcd) -{ - int result; - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - mutex_lock(&wusbhc->mutex); - wa_nep_disarm(&hwahc->wa); - result = __wa_set_feature(&hwahc->wa, WA_RESET); - if (result < 0) { - dev_err(dev, "error commanding HC to reset: %d\n", result); - goto error_unlock; - } - d_printf(3, dev, "reset: waiting for device to change state\n"); - result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0); - if (result < 0) { - dev_err(dev, "error waiting for HC to reset: %d\n", result); - goto error_unlock; - } -error_unlock: - mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return result; -} - -/* - * FIXME: break this function up - */ -static int hwahc_op_start(struct usb_hcd *usb_hcd) -{ - u8 addr; - int result; - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - /* Set up a Host Info WUSB Information Element */ - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - result = -ENOSPC; - mutex_lock(&wusbhc->mutex); - /* Start the numbering from the top so that the bottom - * range of the unauth addr space is used for devices, - * the top for HCs; use 0xfe - RC# */ - addr = wusb_cluster_id_get(); - if (addr == 0) - goto error_cluster_id_get; - result = __hwahc_set_cluster_id(hwahc, addr); - if (result < 0) - goto error_set_cluster_id; - - result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "cannot listen to notifications: %d\n", result); - goto error_stop; - } - usb_hcd->uses_new_polling = 1; - usb_hcd->poll_rh = 1; - usb_hcd->state = HC_STATE_RUNNING; - result = 0; -out: - mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return result; - -error_stop: - __wa_stop(&hwahc->wa); -error_set_cluster_id: - wusb_cluster_id_put(wusbhc->cluster_id); -error_cluster_id_get: - goto out; - -} - -/* - * FIXME: break this function up - */ -static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) -{ - int result; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - /* Set up a Host Info WUSB Information Element */ - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - result = -ENOSPC; - - result = __wa_set_feature(&hwahc->wa, WA_ENABLE); - if (result < 0) { - dev_err(dev, "error commanding HC to start: %d\n", result); - goto error_stop; - } - result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); - if (result < 0) { - dev_err(dev, "error waiting for HC to start: %d\n", result); - goto error_stop; - } - result = 0; -out: - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return result; - -error_stop: - result = __wa_clear_feature(&hwahc->wa, WA_ENABLE); - goto out; -} - -static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - dev_err(wusbhc->dev, "%s (%p [%p], 0x%lx) UNIMPLEMENTED\n", __func__, - usb_hcd, hwahc, *(unsigned long *) &msg); - return -ENOSYS; -} - -static int hwahc_op_resume(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, - usb_hcd, hwahc); - return -ENOSYS; -} - -static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) -{ - int result; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - /* Nothing for now */ - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return; -} - -/* - * No need to abort pipes, as when this is called, all the children - * has been disconnected and that has done it [through - * usb_disable_interface() -> usb_disable_endpoint() -> - * hwahc_op_ep_disable() - >rpipe_ep_disable()]. - */ -static void hwahc_op_stop(struct usb_hcd *usb_hcd) -{ - int result; - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - struct device *dev = &wa->usb_iface->dev; - - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - mutex_lock(&wusbhc->mutex); - wusbhc_stop(wusbhc); - wa_nep_disarm(&hwahc->wa); - result = __wa_stop(&hwahc->wa); - wusb_cluster_id_put(wusbhc->cluster_id); - mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return; -} - -static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, - usb_hcd, hwahc); - return -ENOSYS; -} - -static int hwahc_op_urb_enqueue(struct usb_hcd *usb_hcd, struct urb *urb, - gfp_t gfp) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - return wa_urb_enqueue(&hwahc->wa, urb->ep, urb, gfp); -} - -static int hwahc_op_urb_dequeue(struct usb_hcd *usb_hcd, struct urb *urb, - int status) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - return wa_urb_dequeue(&hwahc->wa, urb); -} - -/* - * Release resources allocated for an endpoint - * - * If there is an associated rpipe to this endpoint, go ahead and put it. - */ -static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd, - struct usb_host_endpoint *ep) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - rpipe_ep_disable(&hwahc->wa, ep); -} - -/* - * Set the UWB MAS allocation for the WUSB cluster - * - * @stream_index: stream to use (-1 for cancelling the allocation) - * @mas: mas bitmap to use - */ -static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 stream_index, - const struct uwb_mas_bm *mas) -{ - int result; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - struct device *dev = &wa->usb_iface->dev; - u8 mas_le[UWB_NUM_MAS/8]; - - /* Set the stream index */ - result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_SET_STREAM_IDX, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - stream_index, - wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Cannot set WUSB stream index: %d\n", result); - goto out; - } - uwb_mas_bm_copy_le(mas_le, mas); - /* Set the MAS allocation */ - result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_SET_WUSB_MAS, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - mas_le, 32, 1000 /* FIXME: arbitrary */); - if (result < 0) - dev_err(dev, "Cannot set WUSB MAS allocation: %d\n", result); -out: - return result; -} - -/* - * Add an IE to the host's MMC - * - * @interval: See WUSB1.0[8.5.3.1] - * @repeat_cnt: See WUSB1.0[8.5.3.1] - * @handle: See WUSB1.0[8.5.3.1] - * @wuie: Pointer to the header of the WUSB IE data to add. - * MUST BE allocated in a kmalloc buffer (no stack or - * vmalloc). - * - * NOTE: the format of the WUSB IEs for MMCs are different to the - * normal MBOA MAC IEs (IE Id + Length in MBOA MAC vs. Length + - * Id in WUSB IEs). Standards...you gotta love'em. - */ -static int __hwahc_op_mmcie_add(struct wusbhc *wusbhc, u8 interval, - u8 repeat_cnt, u8 handle, - struct wuie_hdr *wuie) -{ - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; - - return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_ADD_MMC_IE, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - interval << 8 | repeat_cnt, - handle << 8 | iface_no, - wuie, wuie->bLength, 1000 /* FIXME: arbitrary */); -} - -/* - * Remove an IE to the host's MMC - * - * @handle: See WUSB1.0[8.5.3.1] - */ -static int __hwahc_op_mmcie_rm(struct wusbhc *wusbhc, u8 handle) -{ - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; - return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_REMOVE_MMC_IE, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, handle << 8 | iface_no, - NULL, 0, 1000 /* FIXME: arbitrary */); -} - -/* - * Update device information for a given fake port - * - * @port_idx: Fake port to which device is connected (wusbhc index, not - * USB port number). - */ -static int __hwahc_op_dev_info_set(struct wusbhc *wusbhc, - struct wusb_dev *wusb_dev) -{ - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; - struct hwa_dev_info *dev_info; - int ret; - - /* fill out the Device Info buffer and send it */ - dev_info = kzalloc(sizeof(struct hwa_dev_info), GFP_KERNEL); - if (!dev_info) - return -ENOMEM; - uwb_mas_bm_copy_le(dev_info->bmDeviceAvailability, - &wusb_dev->availability); - dev_info->bDeviceAddress = wusb_dev->addr; - - /* - * If the descriptors haven't been read yet, use a default PHY - * rate of 53.3 Mbit/s only. The correct value will be used - * when this will be called again as part of the - * authentication process (which occurs after the descriptors - * have been read). - */ - if (wusb_dev->wusb_cap_descr) - dev_info->wPHYRates = wusb_dev->wusb_cap_descr->wPHYRates; - else - dev_info->wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53); - - ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - WUSB_REQ_SET_DEV_INFO, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, wusb_dev->port_idx << 8 | iface_no, - dev_info, sizeof(struct hwa_dev_info), - 1000 /* FIXME: arbitrary */); - kfree(dev_info); - return ret; -} - -/* - * Set host's idea of which encryption (and key) method to use when - * talking to ad evice on a given port. - * - * If key is NULL, it means disable encryption for that "virtual port" - * (used when we disconnect). - */ -static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, - const void *key, size_t key_size, - u8 key_idx) -{ - int result = -ENOMEM; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; - struct usb_key_descriptor *keyd; - size_t keyd_len; - - keyd_len = sizeof(*keyd) + key_size; - keyd = kzalloc(keyd_len, GFP_KERNEL); - if (keyd == NULL) - return -ENOMEM; - - keyd->bLength = keyd_len; - keyd->bDescriptorType = USB_DT_KEY; - keyd->tTKID[0] = (tkid >> 0) & 0xff; - keyd->tTKID[1] = (tkid >> 8) & 0xff; - keyd->tTKID[2] = (tkid >> 16) & 0xff; - memcpy(keyd->bKeyData, key, key_size); - - result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - USB_REQ_SET_DESCRIPTOR, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - USB_DT_KEY << 8 | key_idx, - port_idx << 8 | iface_no, - keyd, keyd_len, 1000 /* FIXME: arbitrary */); - - memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */ - kfree(keyd); - return result; -} - -/* - * Set host's idea of which encryption (and key) method to use when - * talking to ad evice on a given port. - * - * If key is NULL, it means disable encryption for that "virtual port" - * (used when we disconnect). - */ -static int __hwahc_op_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, - const void *key, size_t key_size) -{ - int result = -ENOMEM; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; - u8 encryption_value; - - /* Tell the host which key to use to talk to the device */ - if (key) { - u8 key_idx = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_PTK, - WUSB_KEY_INDEX_ORIGINATOR_HOST); - - result = __hwahc_dev_set_key(wusbhc, port_idx, tkid, - key, key_size, key_idx); - if (result < 0) - goto error_set_key; - encryption_value = wusbhc->ccm1_etd->bEncryptionValue; - } else { - /* FIXME: this should come from wusbhc->etd[UNSECURE].value */ - encryption_value = 0; - } - - /* Set the encryption type for commmunicating with the device */ - result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - USB_REQ_SET_ENCRYPTION, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - encryption_value, port_idx << 8 | iface_no, - NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) - dev_err(wusbhc->dev, "Can't set host's WUSB encryption for " - "port index %u to %s (value %d): %d\n", port_idx, - wusb_et_name(wusbhc->ccm1_etd->bEncryptionType), - wusbhc->ccm1_etd->bEncryptionValue, result); -error_set_key: - return result; -} - -/* - * Set host's GTK key - */ -static int __hwahc_op_set_gtk(struct wusbhc *wusbhc, u32 tkid, - const void *key, size_t key_size) -{ - u8 key_idx = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK, - WUSB_KEY_INDEX_ORIGINATOR_HOST); - - return __hwahc_dev_set_key(wusbhc, 0, tkid, key, key_size, key_idx); -} - -/* - * Get the Wire Adapter class-specific descriptor - * - * NOTE: this descriptor comes with the big bundled configuration - * descriptor that includes the interfaces' and endpoints', so - * we just look for it in the cached copy kept by the USB stack. - * - * NOTE2: We convert LE fields to CPU order. - */ -static int wa_fill_descr(struct wahc *wa) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - char *itr; - struct usb_device *usb_dev = wa->usb_dev; - struct usb_descriptor_header *hdr; - struct usb_wa_descriptor *wa_descr; - size_t itr_size, actconfig_idx; - - actconfig_idx = (usb_dev->actconfig - usb_dev->config) / - sizeof(usb_dev->config[0]); - itr = usb_dev->rawdescriptors[actconfig_idx]; - itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); - while (itr_size >= sizeof(*hdr)) { - hdr = (struct usb_descriptor_header *) itr; - d_printf(3, dev, "Extra device descriptor: " - "type %02x/%u bytes @ %zu (%zu left)\n", - hdr->bDescriptorType, hdr->bLength, - (itr - usb_dev->rawdescriptors[actconfig_idx]), - itr_size); - if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER) - goto found; - itr += hdr->bLength; - itr_size -= hdr->bLength; - } - dev_err(dev, "cannot find Wire Adapter Class descriptor\n"); - return -ENODEV; - -found: - result = -EINVAL; - if (hdr->bLength > itr_size) { /* is it available? */ - dev_err(dev, "incomplete Wire Adapter Class descriptor " - "(%zu bytes left, %u needed)\n", - itr_size, hdr->bLength); - goto error; - } - if (hdr->bLength < sizeof(*wa->wa_descr)) { - dev_err(dev, "short Wire Adapter Class descriptor\n"); - goto error; - } - wa->wa_descr = wa_descr = (struct usb_wa_descriptor *) hdr; - /* Make LE fields CPU order */ - wa_descr->bcdWAVersion = le16_to_cpu(wa_descr->bcdWAVersion); - wa_descr->wNumRPipes = le16_to_cpu(wa_descr->wNumRPipes); - wa_descr->wRPipeMaxBlock = le16_to_cpu(wa_descr->wRPipeMaxBlock); - if (wa_descr->bcdWAVersion > 0x0100) - dev_warn(dev, "Wire Adapter v%d.%d newer than groked v1.0\n", - wa_descr->bcdWAVersion & 0xff00 >> 8, - wa_descr->bcdWAVersion & 0x00ff); - result = 0; -error: - return result; -} - -static struct hc_driver hwahc_hc_driver = { - .description = "hwa-hcd", - .product_desc = "Wireless USB HWA host controller", - .hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd), - .irq = NULL, /* FIXME */ - .flags = HCD_USB2, /* FIXME */ - .reset = hwahc_op_reset, - .start = hwahc_op_start, - .pci_suspend = hwahc_op_suspend, - .pci_resume = hwahc_op_resume, - .stop = hwahc_op_stop, - .get_frame_number = hwahc_op_get_frame_number, - .urb_enqueue = hwahc_op_urb_enqueue, - .urb_dequeue = hwahc_op_urb_dequeue, - .endpoint_disable = hwahc_op_endpoint_disable, - - .hub_status_data = wusbhc_rh_status_data, - .hub_control = wusbhc_rh_control, - .bus_suspend = wusbhc_rh_suspend, - .bus_resume = wusbhc_rh_resume, - .start_port_reset = wusbhc_rh_start_port_reset, -}; - -static int hwahc_security_create(struct hwahc *hwahc) -{ - int result; - struct wusbhc *wusbhc = &hwahc->wusbhc; - struct usb_device *usb_dev = hwahc->wa.usb_dev; - struct device *dev = &usb_dev->dev; - struct usb_security_descriptor *secd; - struct usb_encryption_descriptor *etd; - void *itr, *top; - size_t itr_size, needed, bytes; - u8 index; - char buf[64]; - - /* Find the host's security descriptors in the config descr bundle */ - index = (usb_dev->actconfig - usb_dev->config) / - sizeof(usb_dev->config[0]); - itr = usb_dev->rawdescriptors[index]; - itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); - top = itr + itr_size; - result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], - le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), - USB_DT_SECURITY, (void **) &secd); - if (result == -1) { - dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); - return 0; - } - needed = sizeof(*secd); - if (top - (void *)secd < needed) { - dev_err(dev, "BUG? Not enough data to process security " - "descriptor header (%zu bytes left vs %zu needed)\n", - top - (void *) secd, needed); - return 0; - } - needed = le16_to_cpu(secd->wTotalLength); - if (top - (void *)secd < needed) { - dev_err(dev, "BUG? Not enough data to process security " - "descriptors (%zu bytes left vs %zu needed)\n", - top - (void *) secd, needed); - return 0; - } - /* Walk over the sec descriptors and store CCM1's on wusbhc */ - itr = (void *) secd + sizeof(*secd); - top = (void *) secd + le16_to_cpu(secd->wTotalLength); - index = 0; - bytes = 0; - while (itr < top) { - etd = itr; - if (top - itr < sizeof(*etd)) { - dev_err(dev, "BUG: bad host security descriptor; " - "not enough data (%zu vs %zu left)\n", - top - itr, sizeof(*etd)); - break; - } - if (etd->bLength < sizeof(*etd)) { - dev_err(dev, "BUG: bad host encryption descriptor; " - "descriptor is too short " - "(%zu vs %zu needed)\n", - (size_t)etd->bLength, sizeof(*etd)); - break; - } - itr += etd->bLength; - bytes += snprintf(buf + bytes, sizeof(buf) - bytes, - "%s (0x%02x) ", - wusb_et_name(etd->bEncryptionType), - etd->bEncryptionValue); - wusbhc->ccm1_etd = etd; - } - dev_info(dev, "supported encryption types: %s\n", buf); - if (wusbhc->ccm1_etd == NULL) { - dev_err(dev, "E: host doesn't support CCM-1 crypto\n"); - return 0; - } - /* Pretty print what we support */ - return 0; -} - -static void hwahc_security_release(struct hwahc *hwahc) -{ - /* nothing to do here so far... */ -} - -static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface) -{ - int result; - struct device *dev = &iface->dev; - struct wusbhc *wusbhc = &hwahc->wusbhc; - struct wahc *wa = &hwahc->wa; - struct usb_device *usb_dev = interface_to_usbdev(iface); - - wa->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */ - wa->usb_iface = usb_get_intf(iface); - wusbhc->dev = dev; - wusbhc->uwb_rc = uwb_rc_get_by_grandpa(iface->dev.parent); - if (wusbhc->uwb_rc == NULL) { - result = -ENODEV; - dev_err(dev, "Cannot get associated UWB Host Controller\n"); - goto error_rc_get; - } - result = wa_fill_descr(wa); /* Get the device descriptor */ - if (result < 0) - goto error_fill_descriptor; - if (wa->wa_descr->bNumPorts > USB_MAXCHILDREN) { - dev_err(dev, "FIXME: USB_MAXCHILDREN too low for WUSB " - "adapter (%u ports)\n", wa->wa_descr->bNumPorts); - wusbhc->ports_max = USB_MAXCHILDREN; - } else { - wusbhc->ports_max = wa->wa_descr->bNumPorts; - } - wusbhc->mmcies_max = wa->wa_descr->bNumMMCIEs; - wusbhc->start = __hwahc_op_wusbhc_start; - wusbhc->stop = __hwahc_op_wusbhc_stop; - wusbhc->mmcie_add = __hwahc_op_mmcie_add; - wusbhc->mmcie_rm = __hwahc_op_mmcie_rm; - wusbhc->dev_info_set = __hwahc_op_dev_info_set; - wusbhc->bwa_set = __hwahc_op_bwa_set; - wusbhc->set_num_dnts = __hwahc_op_set_num_dnts; - wusbhc->set_ptk = __hwahc_op_set_ptk; - wusbhc->set_gtk = __hwahc_op_set_gtk; - result = hwahc_security_create(hwahc); - if (result < 0) { - dev_err(dev, "Can't initialize security: %d\n", result); - goto error_security_create; - } - wa->wusb = wusbhc; /* FIXME: ugly, need to fix */ - result = wusbhc_create(&hwahc->wusbhc); - if (result < 0) { - dev_err(dev, "Can't create WUSB HC structures: %d\n", result); - goto error_wusbhc_create; - } - result = wa_create(&hwahc->wa, iface); - if (result < 0) - goto error_wa_create; - return 0; - -error_wa_create: - wusbhc_destroy(&hwahc->wusbhc); -error_wusbhc_create: - /* WA Descr fill allocs no resources */ -error_security_create: -error_fill_descriptor: - uwb_rc_put(wusbhc->uwb_rc); -error_rc_get: - usb_put_intf(iface); - usb_put_dev(usb_dev); - return result; -} - -static void hwahc_destroy(struct hwahc *hwahc) -{ - struct wusbhc *wusbhc = &hwahc->wusbhc; - - d_fnstart(1, NULL, "(hwahc %p)\n", hwahc); - mutex_lock(&wusbhc->mutex); - __wa_destroy(&hwahc->wa); - wusbhc_destroy(&hwahc->wusbhc); - hwahc_security_release(hwahc); - hwahc->wusbhc.dev = NULL; - uwb_rc_put(wusbhc->uwb_rc); - usb_put_intf(hwahc->wa.usb_iface); - usb_put_dev(hwahc->wa.usb_dev); - mutex_unlock(&wusbhc->mutex); - d_fnend(1, NULL, "(hwahc %p) = void\n", hwahc); -} - -static void hwahc_init(struct hwahc *hwahc) -{ - wa_init(&hwahc->wa); -} - -static int hwahc_probe(struct usb_interface *usb_iface, - const struct usb_device_id *id) -{ - int result; - struct usb_hcd *usb_hcd; - struct wusbhc *wusbhc; - struct hwahc *hwahc; - struct device *dev = &usb_iface->dev; - - d_fnstart(4, dev, "(%p, %p)\n", usb_iface, id); - result = -ENOMEM; - usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa"); - if (usb_hcd == NULL) { - dev_err(dev, "unable to allocate instance\n"); - goto error_alloc; - } - usb_hcd->wireless = 1; - usb_hcd->flags |= HCD_FLAG_SAW_IRQ; - wusbhc = usb_hcd_to_wusbhc(usb_hcd); - hwahc = container_of(wusbhc, struct hwahc, wusbhc); - hwahc_init(hwahc); - result = hwahc_create(hwahc, usb_iface); - if (result < 0) { - dev_err(dev, "Cannot initialize internals: %d\n", result); - goto error_hwahc_create; - } - result = usb_add_hcd(usb_hcd, 0, 0); - if (result < 0) { - dev_err(dev, "Cannot add HCD: %d\n", result); - goto error_add_hcd; - } - result = wusbhc_b_create(&hwahc->wusbhc); - if (result < 0) { - dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); - goto error_wusbhc_b_create; - } - d_fnend(4, dev, "(%p, %p) = 0\n", usb_iface, id); - return 0; - -error_wusbhc_b_create: - usb_remove_hcd(usb_hcd); -error_add_hcd: - hwahc_destroy(hwahc); -error_hwahc_create: - usb_put_hcd(usb_hcd); -error_alloc: - d_fnend(4, dev, "(%p, %p) = %d\n", usb_iface, id, result); - return result; -} - -static void hwahc_disconnect(struct usb_interface *usb_iface) -{ - struct usb_hcd *usb_hcd; - struct wusbhc *wusbhc; - struct hwahc *hwahc; - - usb_hcd = usb_get_intfdata(usb_iface); - wusbhc = usb_hcd_to_wusbhc(usb_hcd); - hwahc = container_of(wusbhc, struct hwahc, wusbhc); - - d_fnstart(1, NULL, "(hwahc %p [usb_iface %p])\n", hwahc, usb_iface); - wusbhc_b_destroy(&hwahc->wusbhc); - usb_remove_hcd(usb_hcd); - hwahc_destroy(hwahc); - usb_put_hcd(usb_hcd); - d_fnend(1, NULL, "(hwahc %p [usb_iface %p]) = void\n", hwahc, - usb_iface); -} - -/** USB device ID's that we handle */ -static struct usb_device_id hwahc_id_table[] = { - /* FIXME: use class labels for this */ - { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), }, - {}, -}; -MODULE_DEVICE_TABLE(usb, hwahc_id_table); - -static struct usb_driver hwahc_driver = { - .name = "hwa-hc", - .probe = hwahc_probe, - .disconnect = hwahc_disconnect, - .id_table = hwahc_id_table, -}; - -static int __init hwahc_driver_init(void) -{ - int result; - result = usb_register(&hwahc_driver); - if (result < 0) { - printk(KERN_ERR "WA-CDS: Cannot register USB driver: %d\n", - result); - goto error_usb_register; - } - return 0; - -error_usb_register: - return result; - -} -module_init(hwahc_driver_init); - -static void __exit hwahc_driver_exit(void) -{ - usb_deregister(&hwahc_driver); -} -module_exit(hwahc_driver_exit); - - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Host Wired Adapter USB Host Control Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/host/whci/Kbuild b/trunk/drivers/usb/host/whci/Kbuild deleted file mode 100644 index 26a3871ea0f9..000000000000 --- a/trunk/drivers/usb/host/whci/Kbuild +++ /dev/null @@ -1,11 +0,0 @@ -obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o - -whci-hcd-y := \ - asl.o \ - hcd.o \ - hw.o \ - init.o \ - int.o \ - pzl.o \ - qset.o \ - wusb.o diff --git a/trunk/drivers/usb/host/whci/asl.c b/trunk/drivers/usb/host/whci/asl.c deleted file mode 100644 index 4d7078e50572..000000000000 --- a/trunk/drivers/usb/host/whci/asl.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Wireless Host Controller (WHC) asynchronous schedule management. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include -#define D_LOCAL 0 -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -#if D_LOCAL >= 4 -static void dump_asl(struct whc *whc, const char *tag) -{ - struct device *dev = &whc->umc->dev; - struct whc_qset *qset; - - d_printf(4, dev, "ASL %s\n", tag); - - list_for_each_entry(qset, &whc->async_list, list_node) { - dump_qset(qset, dev); - } -} -#else -static inline void dump_asl(struct whc *whc, const char *tag) -{ -} -#endif - - -static void qset_get_next_prev(struct whc *whc, struct whc_qset *qset, - struct whc_qset **next, struct whc_qset **prev) -{ - struct list_head *n, *p; - - BUG_ON(list_empty(&whc->async_list)); - - n = qset->list_node.next; - if (n == &whc->async_list) - n = n->next; - p = qset->list_node.prev; - if (p == &whc->async_list) - p = p->prev; - - *next = container_of(n, struct whc_qset, list_node); - *prev = container_of(p, struct whc_qset, list_node); - -} - -static void asl_qset_insert_begin(struct whc *whc, struct whc_qset *qset) -{ - list_move(&qset->list_node, &whc->async_list); - qset->in_sw_list = true; -} - -static void asl_qset_insert(struct whc *whc, struct whc_qset *qset) -{ - struct whc_qset *next, *prev; - - qset_clear(whc, qset); - - /* Link into ASL. */ - qset_get_next_prev(whc, qset, &next, &prev); - whc_qset_set_link_ptr(&qset->qh.link, next->qset_dma); - whc_qset_set_link_ptr(&prev->qh.link, qset->qset_dma); - qset->in_hw_list = true; -} - -static void asl_qset_remove(struct whc *whc, struct whc_qset *qset) -{ - struct whc_qset *prev, *next; - - qset_get_next_prev(whc, qset, &next, &prev); - - list_move(&qset->list_node, &whc->async_removed_list); - qset->in_sw_list = false; - - /* - * No more qsets in the ASL? The caller must stop the ASL as - * it's no longer valid. - */ - if (list_empty(&whc->async_list)) - return; - - /* Remove from ASL. */ - whc_qset_set_link_ptr(&prev->qh.link, next->qset_dma); - qset->in_hw_list = false; -} - -/** - * process_qset - process any recently inactivated or halted qTDs in a - * qset. - * - * After inactive qTDs are removed, new qTDs can be added if the - * urb queue still contains URBs. - * - * Returns any additional WUSBCMD bits for the ASL sync command (i.e., - * WUSBCMD_ASYNC_QSET_RM if a halted qset was removed). - */ -static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) -{ - enum whc_update update = 0; - uint32_t status = 0; - - while (qset->ntds) { - struct whc_qtd *td; - int t; - - t = qset->td_start; - td = &qset->qtd[qset->td_start]; - status = le32_to_cpu(td->status); - - /* - * Nothing to do with a still active qTD. - */ - if (status & QTD_STS_ACTIVE) - break; - - if (status & QTD_STS_HALTED) { - /* Ug, an error. */ - process_halted_qtd(whc, qset, td); - goto done; - } - - /* Mmm, a completed qTD. */ - process_inactive_qtd(whc, qset, td); - } - - update |= qset_add_qtds(whc, qset); - -done: - /* - * Remove this qset from the ASL if requested, but only if has - * no qTDs. - */ - if (qset->remove && qset->ntds == 0) { - asl_qset_remove(whc, qset); - update |= WHC_UPDATE_REMOVED; - } - return update; -} - -void asl_start(struct whc *whc) -{ - struct whc_qset *qset; - - qset = list_first_entry(&whc->async_list, struct whc_qset, list_node); - - le_writeq(qset->qset_dma | QH_LINK_NTDS(8), whc->base + WUSBASYNCLISTADDR); - - whc_write_wusbcmd(whc, WUSBCMD_ASYNC_EN, WUSBCMD_ASYNC_EN); - whci_wait_for(&whc->umc->dev, whc->base + WUSBSTS, - WUSBSTS_ASYNC_SCHED, WUSBSTS_ASYNC_SCHED, - 1000, "start ASL"); -} - -void asl_stop(struct whc *whc) -{ - whc_write_wusbcmd(whc, WUSBCMD_ASYNC_EN, 0); - whci_wait_for(&whc->umc->dev, whc->base + WUSBSTS, - WUSBSTS_ASYNC_SCHED, 0, - 1000, "stop ASL"); -} - -void asl_update(struct whc *whc, uint32_t wusbcmd) -{ - whc_write_wusbcmd(whc, wusbcmd, wusbcmd); - wait_event(whc->async_list_wq, - (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); -} - -/** - * scan_async_work - scan the ASL for qsets to process. - * - * Process each qset in the ASL in turn and then signal the WHC that - * the ASL has been updated. - * - * Then start, stop or update the asynchronous schedule as required. - */ -void scan_async_work(struct work_struct *work) -{ - struct whc *whc = container_of(work, struct whc, async_work); - struct whc_qset *qset, *t; - enum whc_update update = 0; - - spin_lock_irq(&whc->lock); - - dump_asl(whc, "before processing"); - - /* - * Transerve the software list backwards so new qsets can be - * safely inserted into the ASL without making it non-circular. - */ - list_for_each_entry_safe_reverse(qset, t, &whc->async_list, list_node) { - if (!qset->in_hw_list) { - asl_qset_insert(whc, qset); - update |= WHC_UPDATE_ADDED; - } - - update |= process_qset(whc, qset); - } - - dump_asl(whc, "after processing"); - - spin_unlock_irq(&whc->lock); - - if (update) { - uint32_t wusbcmd = WUSBCMD_ASYNC_UPDATED | WUSBCMD_ASYNC_SYNCED_DB; - if (update & WHC_UPDATE_REMOVED) - wusbcmd |= WUSBCMD_ASYNC_QSET_RM; - asl_update(whc, wusbcmd); - } - - /* - * Now that the ASL is updated, complete the removal of any - * removed qsets. - */ - spin_lock(&whc->lock); - - list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { - qset_remove_complete(whc, qset); - } - - spin_unlock(&whc->lock); -} - -/** - * asl_urb_enqueue - queue an URB onto the asynchronous list (ASL). - * @whc: the WHCI host controller - * @urb: the URB to enqueue - * @mem_flags: flags for any memory allocations - * - * The qset for the endpoint is obtained and the urb queued on to it. - * - * Work is scheduled to update the hardware's view of the ASL. - */ -int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) -{ - struct whc_qset *qset; - int err; - unsigned long flags; - - spin_lock_irqsave(&whc->lock, flags); - - qset = get_qset(whc, urb, GFP_ATOMIC); - if (qset == NULL) - err = -ENOMEM; - else - err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); - if (!err) { - usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); - if (!qset->in_sw_list) - asl_qset_insert_begin(whc, qset); - } - - spin_unlock_irqrestore(&whc->lock, flags); - - if (!err) - queue_work(whc->workqueue, &whc->async_work); - - return 0; -} - -/** - * asl_urb_dequeue - remove an URB (qset) from the async list. - * @whc: the WHCI host controller - * @urb: the URB to dequeue - * @status: the current status of the URB - * - * URBs that do yet have qTDs can simply be removed from the software - * queue, otherwise the qset must be removed from the ASL so the qTDs - * can be removed. - */ -int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status) -{ - struct whc_urb *wurb = urb->hcpriv; - struct whc_qset *qset = wurb->qset; - struct whc_std *std, *t; - int ret; - unsigned long flags; - - spin_lock_irqsave(&whc->lock, flags); - - ret = usb_hcd_check_unlink_urb(&whc->wusbhc.usb_hcd, urb, status); - if (ret < 0) - goto out; - - list_for_each_entry_safe(std, t, &qset->stds, list_node) { - if (std->urb == urb) - qset_free_std(whc, std); - else - std->qtd = NULL; /* so this std is re-added when the qset is */ - } - - asl_qset_remove(whc, qset); - wurb->status = status; - wurb->is_async = true; - queue_work(whc->workqueue, &wurb->dequeue_work); - -out: - spin_unlock_irqrestore(&whc->lock, flags); - - return ret; -} - -/** - * asl_qset_delete - delete a qset from the ASL - */ -void asl_qset_delete(struct whc *whc, struct whc_qset *qset) -{ - qset->remove = 1; - queue_work(whc->workqueue, &whc->async_work); - qset_delete(whc, qset); -} - -/** - * asl_init - initialize the asynchronous schedule list - * - * A dummy qset with no qTDs is added to the ASL to simplify removing - * qsets (no need to stop the ASL when the last qset is removed). - */ -int asl_init(struct whc *whc) -{ - struct whc_qset *qset; - - qset = qset_alloc(whc, GFP_KERNEL); - if (qset == NULL) - return -ENOMEM; - - asl_qset_insert_begin(whc, qset); - asl_qset_insert(whc, qset); - - return 0; -} - -/** - * asl_clean_up - free ASL resources - * - * The ASL is stopped and empty except for the dummy qset. - */ -void asl_clean_up(struct whc *whc) -{ - struct whc_qset *qset; - - if (!list_empty(&whc->async_list)) { - qset = list_first_entry(&whc->async_list, struct whc_qset, list_node); - list_del(&qset->list_node); - qset_free(whc, qset); - } -} diff --git a/trunk/drivers/usb/host/whci/hcd.c b/trunk/drivers/usb/host/whci/hcd.c deleted file mode 100644 index ef3ad4dca945..000000000000 --- a/trunk/drivers/usb/host/whci/hcd.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Wireless Host Controller (WHC) driver. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -/* - * One time initialization. - * - * Nothing to do here. - */ -static int whc_reset(struct usb_hcd *usb_hcd) -{ - return 0; -} - -/* - * Start the wireless host controller. - * - * Start device notification. - * - * Put hc into run state, set DNTS parameters. - */ -static int whc_start(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - u8 bcid; - int ret; - - mutex_lock(&wusbhc->mutex); - - le_writel(WUSBINTR_GEN_CMD_DONE - | WUSBINTR_HOST_ERR - | WUSBINTR_ASYNC_SCHED_SYNCED - | WUSBINTR_DNTS_INT - | WUSBINTR_ERR_INT - | WUSBINTR_INT, - whc->base + WUSBINTR); - - /* set cluster ID */ - bcid = wusb_cluster_id_get(); - ret = whc_set_cluster_id(whc, bcid); - if (ret < 0) - goto out; - wusbhc->cluster_id = bcid; - - /* start HC */ - whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN); - - usb_hcd->uses_new_polling = 1; - usb_hcd->poll_rh = 1; - usb_hcd->state = HC_STATE_RUNNING; - -out: - mutex_unlock(&wusbhc->mutex); - return ret; -} - - -/* - * Stop the wireless host controller. - * - * Stop device notification. - * - * Wait for pending transfer to stop? Put hc into stop state? - */ -static void whc_stop(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - - mutex_lock(&wusbhc->mutex); - - wusbhc_stop(wusbhc); - - /* stop HC */ - le_writel(0, whc->base + WUSBINTR); - whc_write_wusbcmd(whc, WUSBCMD_RUN, 0); - whci_wait_for(&whc->umc->dev, whc->base + WUSBSTS, - WUSBSTS_HCHALTED, WUSBSTS_HCHALTED, - 100, "HC to halt"); - - wusb_cluster_id_put(wusbhc->cluster_id); - - mutex_unlock(&wusbhc->mutex); -} - -static int whc_get_frame_number(struct usb_hcd *usb_hcd) -{ - /* Frame numbers are not applicable to WUSB. */ - return -ENOSYS; -} - - -/* - * Queue an URB to the ASL or PZL - */ -static int whc_urb_enqueue(struct usb_hcd *usb_hcd, struct urb *urb, - gfp_t mem_flags) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - int ret; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - ret = pzl_urb_enqueue(whc, urb, mem_flags); - break; - case PIPE_ISOCHRONOUS: - dev_err(&whc->umc->dev, "isochronous transfers unsupported\n"); - ret = -ENOTSUPP; - break; - case PIPE_CONTROL: - case PIPE_BULK: - default: - ret = asl_urb_enqueue(whc, urb, mem_flags); - break; - }; - - return ret; -} - -/* - * Remove a queued URB from the ASL or PZL. - */ -static int whc_urb_dequeue(struct usb_hcd *usb_hcd, struct urb *urb, int status) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - int ret; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - ret = pzl_urb_dequeue(whc, urb, status); - break; - case PIPE_ISOCHRONOUS: - ret = -ENOTSUPP; - break; - case PIPE_CONTROL: - case PIPE_BULK: - default: - ret = asl_urb_dequeue(whc, urb, status); - break; - }; - - return ret; -} - -/* - * Wait for all URBs to the endpoint to be completed, then delete the - * qset. - */ -static void whc_endpoint_disable(struct usb_hcd *usb_hcd, - struct usb_host_endpoint *ep) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - struct whc_qset *qset; - - qset = ep->hcpriv; - if (qset) { - ep->hcpriv = NULL; - if (usb_endpoint_xfer_bulk(&ep->desc) - || usb_endpoint_xfer_control(&ep->desc)) - asl_qset_delete(whc, qset); - else - pzl_qset_delete(whc, qset); - } -} - -static struct hc_driver whc_hc_driver = { - .description = "whci-hcd", - .product_desc = "Wireless host controller", - .hcd_priv_size = sizeof(struct whc) - sizeof(struct usb_hcd), - .irq = whc_int_handler, - .flags = HCD_USB2, - - .reset = whc_reset, - .start = whc_start, - .stop = whc_stop, - .get_frame_number = whc_get_frame_number, - .urb_enqueue = whc_urb_enqueue, - .urb_dequeue = whc_urb_dequeue, - .endpoint_disable = whc_endpoint_disable, - - .hub_status_data = wusbhc_rh_status_data, - .hub_control = wusbhc_rh_control, - .bus_suspend = wusbhc_rh_suspend, - .bus_resume = wusbhc_rh_resume, - .start_port_reset = wusbhc_rh_start_port_reset, -}; - -static int whc_probe(struct umc_dev *umc) -{ - int ret = -ENOMEM; - struct usb_hcd *usb_hcd; - struct wusbhc *wusbhc = NULL; - struct whc *whc = NULL; - struct device *dev = &umc->dev; - - usb_hcd = usb_create_hcd(&whc_hc_driver, dev, "whci"); - if (usb_hcd == NULL) { - dev_err(dev, "unable to create hcd\n"); - goto error; - } - - usb_hcd->wireless = 1; - - wusbhc = usb_hcd_to_wusbhc(usb_hcd); - whc = wusbhc_to_whc(wusbhc); - whc->umc = umc; - - ret = whc_init(whc); - if (ret) - goto error; - - wusbhc->dev = dev; - wusbhc->uwb_rc = uwb_rc_get_by_grandpa(umc->dev.parent); - if (!wusbhc->uwb_rc) { - ret = -ENODEV; - dev_err(dev, "cannot get radio controller\n"); - goto error; - } - - if (whc->n_devices > USB_MAXCHILDREN) { - dev_warn(dev, "USB_MAXCHILDREN too low for WUSB adapter (%u ports)\n", - whc->n_devices); - wusbhc->ports_max = USB_MAXCHILDREN; - } else - wusbhc->ports_max = whc->n_devices; - wusbhc->mmcies_max = whc->n_mmc_ies; - wusbhc->start = whc_wusbhc_start; - wusbhc->stop = whc_wusbhc_stop; - wusbhc->mmcie_add = whc_mmcie_add; - wusbhc->mmcie_rm = whc_mmcie_rm; - wusbhc->dev_info_set = whc_dev_info_set; - wusbhc->bwa_set = whc_bwa_set; - wusbhc->set_num_dnts = whc_set_num_dnts; - wusbhc->set_ptk = whc_set_ptk; - wusbhc->set_gtk = whc_set_gtk; - - ret = wusbhc_create(wusbhc); - if (ret) - goto error_wusbhc_create; - - ret = usb_add_hcd(usb_hcd, whc->umc->irq, IRQF_SHARED); - if (ret) { - dev_err(dev, "cannot add HCD: %d\n", ret); - goto error_usb_add_hcd; - } - - ret = wusbhc_b_create(wusbhc); - if (ret) { - dev_err(dev, "WUSBHC phase B setup failed: %d\n", ret); - goto error_wusbhc_b_create; - } - - return 0; - -error_wusbhc_b_create: - usb_remove_hcd(usb_hcd); -error_usb_add_hcd: - wusbhc_destroy(wusbhc); -error_wusbhc_create: - uwb_rc_put(wusbhc->uwb_rc); -error: - whc_clean_up(whc); - if (usb_hcd) - usb_put_hcd(usb_hcd); - return ret; -} - - -static void whc_remove(struct umc_dev *umc) -{ - struct usb_hcd *usb_hcd = dev_get_drvdata(&umc->dev); - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - - if (usb_hcd) { - wusbhc_b_destroy(wusbhc); - usb_remove_hcd(usb_hcd); - wusbhc_destroy(wusbhc); - uwb_rc_put(wusbhc->uwb_rc); - whc_clean_up(whc); - usb_put_hcd(usb_hcd); - } -} - -static struct umc_driver whci_hc_driver = { - .name = "whci-hcd", - .cap_id = UMC_CAP_ID_WHCI_WUSB_HC, - .probe = whc_probe, - .remove = whc_remove, -}; - -static int __init whci_hc_driver_init(void) -{ - return umc_driver_register(&whci_hc_driver); -} -module_init(whci_hc_driver_init); - -static void __exit whci_hc_driver_exit(void) -{ - umc_driver_unregister(&whci_hc_driver); -} -module_exit(whci_hc_driver_exit); - -/* PCI device ID's that we handle (so it gets loaded) */ -static struct pci_device_id whci_hcd_id_table[] = { - { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, - { /* empty last entry */ } -}; -MODULE_DEVICE_TABLE(pci, whci_hcd_id_table); - -MODULE_DESCRIPTION("WHCI Wireless USB host controller driver"); -MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/host/whci/hw.c b/trunk/drivers/usb/host/whci/hw.c deleted file mode 100644 index ac86e59c1225..000000000000 --- a/trunk/drivers/usb/host/whci/hw.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Wireless Host Controller (WHC) hardware access helpers. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val) -{ - unsigned long flags; - u32 cmd; - - spin_lock_irqsave(&whc->lock, flags); - - cmd = le_readl(whc->base + WUSBCMD); - cmd = (cmd & ~mask) | val; - le_writel(cmd, whc->base + WUSBCMD); - - spin_unlock_irqrestore(&whc->lock, flags); -} - -/** - * whc_do_gencmd - start a generic command via the WUSBGENCMDSTS register - * @whc: the WHCI HC - * @cmd: command to start. - * @params: parameters for the command (the WUSBGENCMDPARAMS register value). - * @addr: pointer to any data for the command (may be NULL). - * @len: length of the data (if any). - */ -int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len) -{ - unsigned long flags; - dma_addr_t dma_addr; - int t; - - mutex_lock(&whc->mutex); - - /* Wait for previous command to complete. */ - t = wait_event_timeout(whc->cmd_wq, - (le_readl(whc->base + WUSBGENCMDSTS) & WUSBGENCMDSTS_ACTIVE) == 0, - WHC_GENCMD_TIMEOUT_MS); - if (t == 0) { - dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n", - le_readl(whc->base + WUSBGENCMDSTS), - le_readl(whc->base + WUSBGENCMDPARAMS)); - return -ETIMEDOUT; - } - - if (addr) { - memcpy(whc->gen_cmd_buf, addr, len); - dma_addr = whc->gen_cmd_buf_dma; - } else - dma_addr = 0; - - /* Poke registers to start cmd. */ - spin_lock_irqsave(&whc->lock, flags); - - le_writel(params, whc->base + WUSBGENCMDPARAMS); - le_writeq(dma_addr, whc->base + WUSBGENADDR); - - le_writel(WUSBGENCMDSTS_ACTIVE | WUSBGENCMDSTS_IOC | cmd, - whc->base + WUSBGENCMDSTS); - - spin_unlock_irqrestore(&whc->lock, flags); - - mutex_unlock(&whc->mutex); - - return 0; -} diff --git a/trunk/drivers/usb/host/whci/init.c b/trunk/drivers/usb/host/whci/init.c deleted file mode 100644 index 34a783cb0133..000000000000 --- a/trunk/drivers/usb/host/whci/init.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Wireless Host Controller (WHC) initialization. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -/* - * Reset the host controller. - */ -static void whc_hw_reset(struct whc *whc) -{ - le_writel(WUSBCMD_WHCRESET, whc->base + WUSBCMD); - whci_wait_for(&whc->umc->dev, whc->base + WUSBCMD, WUSBCMD_WHCRESET, 0, - 100, "reset"); -} - -static void whc_hw_init_di_buf(struct whc *whc) -{ - int d; - - /* Disable all entries in the Device Information buffer. */ - for (d = 0; d < whc->n_devices; d++) - whc->di_buf[d].addr_sec_info = WHC_DI_DISABLE; - - le_writeq(whc->di_buf_dma, whc->base + WUSBDEVICEINFOADDR); -} - -static void whc_hw_init_dn_buf(struct whc *whc) -{ - /* Clear the Device Notification buffer to ensure the V (valid) - * bits are clear. */ - memset(whc->dn_buf, 0, 4096); - - le_writeq(whc->dn_buf_dma, whc->base + WUSBDNTSBUFADDR); -} - -int whc_init(struct whc *whc) -{ - u32 whcsparams; - int ret, i; - resource_size_t start, len; - - spin_lock_init(&whc->lock); - mutex_init(&whc->mutex); - init_waitqueue_head(&whc->cmd_wq); - init_waitqueue_head(&whc->async_list_wq); - init_waitqueue_head(&whc->periodic_list_wq); - whc->workqueue = create_singlethread_workqueue(dev_name(&whc->umc->dev)); - if (whc->workqueue == NULL) { - ret = -ENOMEM; - goto error; - } - INIT_WORK(&whc->dn_work, whc_dn_work); - - INIT_WORK(&whc->async_work, scan_async_work); - INIT_LIST_HEAD(&whc->async_list); - INIT_LIST_HEAD(&whc->async_removed_list); - - INIT_WORK(&whc->periodic_work, scan_periodic_work); - for (i = 0; i < 5; i++) - INIT_LIST_HEAD(&whc->periodic_list[i]); - INIT_LIST_HEAD(&whc->periodic_removed_list); - - /* Map HC registers. */ - start = whc->umc->resource.start; - len = whc->umc->resource.end - start + 1; - if (!request_mem_region(start, len, "whci-hc")) { - dev_err(&whc->umc->dev, "can't request HC region\n"); - ret = -EBUSY; - goto error; - } - whc->base_phys = start; - whc->base = ioremap(start, len); - if (!whc->base) { - dev_err(&whc->umc->dev, "ioremap\n"); - ret = -ENOMEM; - goto error; - } - - whc_hw_reset(whc); - - /* Read maximum number of devices, keys and MMC IEs. */ - whcsparams = le_readl(whc->base + WHCSPARAMS); - whc->n_devices = WHCSPARAMS_TO_N_DEVICES(whcsparams); - whc->n_keys = WHCSPARAMS_TO_N_KEYS(whcsparams); - whc->n_mmc_ies = WHCSPARAMS_TO_N_MMC_IES(whcsparams); - - dev_dbg(&whc->umc->dev, "N_DEVICES = %d, N_KEYS = %d, N_MMC_IES = %d\n", - whc->n_devices, whc->n_keys, whc->n_mmc_ies); - - whc->qset_pool = dma_pool_create("qset", &whc->umc->dev, - sizeof(struct whc_qset), 64, 0); - if (whc->qset_pool == NULL) { - ret = -ENOMEM; - goto error; - } - - ret = asl_init(whc); - if (ret < 0) - goto error; - ret = pzl_init(whc); - if (ret < 0) - goto error; - - /* Allocate and initialize a buffer for generic commands, the - Device Information buffer, and the Device Notification - buffer. */ - - whc->gen_cmd_buf = dma_alloc_coherent(&whc->umc->dev, WHC_GEN_CMD_DATA_LEN, - &whc->gen_cmd_buf_dma, GFP_KERNEL); - if (whc->gen_cmd_buf == NULL) { - ret = -ENOMEM; - goto error; - } - - whc->dn_buf = dma_alloc_coherent(&whc->umc->dev, - sizeof(struct dn_buf_entry) * WHC_N_DN_ENTRIES, - &whc->dn_buf_dma, GFP_KERNEL); - if (!whc->dn_buf) { - ret = -ENOMEM; - goto error; - } - whc_hw_init_dn_buf(whc); - - whc->di_buf = dma_alloc_coherent(&whc->umc->dev, - sizeof(struct di_buf_entry) * whc->n_devices, - &whc->di_buf_dma, GFP_KERNEL); - if (!whc->di_buf) { - ret = -ENOMEM; - goto error; - } - whc_hw_init_di_buf(whc); - - return 0; - -error: - whc_clean_up(whc); - return ret; -} - -void whc_clean_up(struct whc *whc) -{ - resource_size_t len; - - if (whc->di_buf) - dma_free_coherent(&whc->umc->dev, sizeof(struct di_buf_entry) * whc->n_devices, - whc->di_buf, whc->di_buf_dma); - if (whc->dn_buf) - dma_free_coherent(&whc->umc->dev, sizeof(struct dn_buf_entry) * WHC_N_DN_ENTRIES, - whc->dn_buf, whc->dn_buf_dma); - if (whc->gen_cmd_buf) - dma_free_coherent(&whc->umc->dev, WHC_GEN_CMD_DATA_LEN, - whc->gen_cmd_buf, whc->gen_cmd_buf_dma); - - pzl_clean_up(whc); - asl_clean_up(whc); - - if (whc->qset_pool) - dma_pool_destroy(whc->qset_pool); - - len = whc->umc->resource.end - whc->umc->resource.start + 1; - if (whc->base) - iounmap(whc->base); - if (whc->base_phys) - release_mem_region(whc->base_phys, len); - - if (whc->workqueue) - destroy_workqueue(whc->workqueue); -} diff --git a/trunk/drivers/usb/host/whci/int.c b/trunk/drivers/usb/host/whci/int.c deleted file mode 100644 index fce01174aa9b..000000000000 --- a/trunk/drivers/usb/host/whci/int.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Wireless Host Controller (WHC) interrupt handling. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -static void transfer_done(struct whc *whc) -{ - queue_work(whc->workqueue, &whc->async_work); - queue_work(whc->workqueue, &whc->periodic_work); -} - -irqreturn_t whc_int_handler(struct usb_hcd *hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(hcd); - struct whc *whc = wusbhc_to_whc(wusbhc); - u32 sts; - - sts = le_readl(whc->base + WUSBSTS); - if (!(sts & WUSBSTS_INT_MASK)) - return IRQ_NONE; - le_writel(sts & WUSBSTS_INT_MASK, whc->base + WUSBSTS); - - if (sts & WUSBSTS_GEN_CMD_DONE) - wake_up(&whc->cmd_wq); - - if (sts & WUSBSTS_HOST_ERR) - dev_err(&whc->umc->dev, "FIXME: host system error\n"); - - if (sts & WUSBSTS_ASYNC_SCHED_SYNCED) - wake_up(&whc->async_list_wq); - - if (sts & WUSBSTS_PERIODIC_SCHED_SYNCED) - wake_up(&whc->periodic_list_wq); - - if (sts & WUSBSTS_DNTS_INT) - queue_work(whc->workqueue, &whc->dn_work); - - /* - * A transfer completed (see [WHCI] section 4.7.1.2 for when - * this occurs). - */ - if (sts & (WUSBSTS_INT | WUSBSTS_ERR_INT)) - transfer_done(whc); - - return IRQ_HANDLED; -} - -static int process_dn_buf(struct whc *whc) -{ - struct wusbhc *wusbhc = &whc->wusbhc; - struct dn_buf_entry *dn; - int processed = 0; - - for (dn = whc->dn_buf; dn < whc->dn_buf + WHC_N_DN_ENTRIES; dn++) { - if (dn->status & WHC_DN_STATUS_VALID) { - wusbhc_handle_dn(wusbhc, dn->src_addr, - (struct wusb_dn_hdr *)dn->dn_data, - dn->msg_size); - dn->status &= ~WHC_DN_STATUS_VALID; - processed++; - } - } - return processed; -} - -void whc_dn_work(struct work_struct *work) -{ - struct whc *whc = container_of(work, struct whc, dn_work); - int processed; - - do { - processed = process_dn_buf(whc); - } while (processed); -} diff --git a/trunk/drivers/usb/host/whci/pzl.c b/trunk/drivers/usb/host/whci/pzl.c deleted file mode 100644 index 8d62df0c330b..000000000000 --- a/trunk/drivers/usb/host/whci/pzl.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Wireless Host Controller (WHC) periodic schedule management. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include -#define D_LOCAL 0 -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -#if D_LOCAL >= 4 -static void dump_pzl(struct whc *whc, const char *tag) -{ - struct device *dev = &whc->umc->dev; - struct whc_qset *qset; - int period = 0; - - d_printf(4, dev, "PZL %s\n", tag); - - for (period = 0; period < 5; period++) { - d_printf(4, dev, "Period %d\n", period); - list_for_each_entry(qset, &whc->periodic_list[period], list_node) { - dump_qset(qset, dev); - } - } -} -#else -static inline void dump_pzl(struct whc *whc, const char *tag) -{ -} -#endif - -static void update_pzl_pointers(struct whc *whc, int period, u64 addr) -{ - switch (period) { - case 0: - whc_qset_set_link_ptr(&whc->pz_list[0], addr); - whc_qset_set_link_ptr(&whc->pz_list[2], addr); - whc_qset_set_link_ptr(&whc->pz_list[4], addr); - whc_qset_set_link_ptr(&whc->pz_list[6], addr); - whc_qset_set_link_ptr(&whc->pz_list[8], addr); - whc_qset_set_link_ptr(&whc->pz_list[10], addr); - whc_qset_set_link_ptr(&whc->pz_list[12], addr); - whc_qset_set_link_ptr(&whc->pz_list[14], addr); - break; - case 1: - whc_qset_set_link_ptr(&whc->pz_list[1], addr); - whc_qset_set_link_ptr(&whc->pz_list[5], addr); - whc_qset_set_link_ptr(&whc->pz_list[9], addr); - whc_qset_set_link_ptr(&whc->pz_list[13], addr); - break; - case 2: - whc_qset_set_link_ptr(&whc->pz_list[3], addr); - whc_qset_set_link_ptr(&whc->pz_list[11], addr); - break; - case 3: - whc_qset_set_link_ptr(&whc->pz_list[7], addr); - break; - case 4: - whc_qset_set_link_ptr(&whc->pz_list[15], addr); - break; - } -} - -/* - * Return the 'period' to use for this qset. The minimum interval for - * the endpoint is used so whatever urbs are submitted the device is - * polled often enough. - */ -static int qset_get_period(struct whc *whc, struct whc_qset *qset) -{ - uint8_t bInterval = qset->ep->desc.bInterval; - - if (bInterval < 6) - bInterval = 6; - if (bInterval > 10) - bInterval = 10; - return bInterval - 6; -} - -static void qset_insert_in_sw_list(struct whc *whc, struct whc_qset *qset) -{ - int period; - - period = qset_get_period(whc, qset); - - qset_clear(whc, qset); - list_move(&qset->list_node, &whc->periodic_list[period]); - qset->in_sw_list = true; -} - -static void pzl_qset_remove(struct whc *whc, struct whc_qset *qset) -{ - list_move(&qset->list_node, &whc->periodic_removed_list); - qset->in_hw_list = false; - qset->in_sw_list = false; -} - -/** - * pzl_process_qset - process any recently inactivated or halted qTDs - * in a qset. - * - * After inactive qTDs are removed, new qTDs can be added if the - * urb queue still contains URBs. - * - * Returns the schedule updates required. - */ -static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset) -{ - enum whc_update update = 0; - uint32_t status = 0; - - while (qset->ntds) { - struct whc_qtd *td; - int t; - - t = qset->td_start; - td = &qset->qtd[qset->td_start]; - status = le32_to_cpu(td->status); - - /* - * Nothing to do with a still active qTD. - */ - if (status & QTD_STS_ACTIVE) - break; - - if (status & QTD_STS_HALTED) { - /* Ug, an error. */ - process_halted_qtd(whc, qset, td); - goto done; - } - - /* Mmm, a completed qTD. */ - process_inactive_qtd(whc, qset, td); - } - - update |= qset_add_qtds(whc, qset); - -done: - /* - * If there are no qTDs in this qset, remove it from the PZL. - */ - if (qset->remove && qset->ntds == 0) { - pzl_qset_remove(whc, qset); - update |= WHC_UPDATE_REMOVED; - } - - return update; -} - -/** - * pzl_start - start the periodic schedule - * @whc: the WHCI host controller - * - * The PZL must be valid (e.g., all entries in the list should have - * the T bit set). - */ -void pzl_start(struct whc *whc) -{ - le_writeq(whc->pz_list_dma, whc->base + WUSBPERIODICLISTBASE); - - whc_write_wusbcmd(whc, WUSBCMD_PERIODIC_EN, WUSBCMD_PERIODIC_EN); - whci_wait_for(&whc->umc->dev, whc->base + WUSBSTS, - WUSBSTS_PERIODIC_SCHED, WUSBSTS_PERIODIC_SCHED, - 1000, "start PZL"); -} - -/** - * pzl_stop - stop the periodic schedule - * @whc: the WHCI host controller - */ -void pzl_stop(struct whc *whc) -{ - whc_write_wusbcmd(whc, WUSBCMD_PERIODIC_EN, 0); - whci_wait_for(&whc->umc->dev, whc->base + WUSBSTS, - WUSBSTS_PERIODIC_SCHED, 0, - 1000, "stop PZL"); -} - -void pzl_update(struct whc *whc, uint32_t wusbcmd) -{ - whc_write_wusbcmd(whc, wusbcmd, wusbcmd); - wait_event(whc->periodic_list_wq, - (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); -} - -static void update_pzl_hw_view(struct whc *whc) -{ - struct whc_qset *qset, *t; - int period; - u64 tmp_qh = 0; - - for (period = 0; period < 5; period++) { - list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) { - whc_qset_set_link_ptr(&qset->qh.link, tmp_qh); - tmp_qh = qset->qset_dma; - qset->in_hw_list = true; - } - update_pzl_pointers(whc, period, tmp_qh); - } -} - -/** - * scan_periodic_work - scan the PZL for qsets to process. - * - * Process each qset in the PZL in turn and then signal the WHC that - * the PZL has been updated. - * - * Then start, stop or update the periodic schedule as required. - */ -void scan_periodic_work(struct work_struct *work) -{ - struct whc *whc = container_of(work, struct whc, periodic_work); - struct whc_qset *qset, *t; - enum whc_update update = 0; - int period; - - spin_lock_irq(&whc->lock); - - dump_pzl(whc, "before processing"); - - for (period = 4; period >= 0; period--) { - list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) { - if (!qset->in_hw_list) - update |= WHC_UPDATE_ADDED; - update |= pzl_process_qset(whc, qset); - } - } - - if (update & (WHC_UPDATE_ADDED | WHC_UPDATE_REMOVED)) - update_pzl_hw_view(whc); - - dump_pzl(whc, "after processing"); - - spin_unlock_irq(&whc->lock); - - if (update) { - uint32_t wusbcmd = WUSBCMD_PERIODIC_UPDATED | WUSBCMD_PERIODIC_SYNCED_DB; - if (update & WHC_UPDATE_REMOVED) - wusbcmd |= WUSBCMD_PERIODIC_QSET_RM; - pzl_update(whc, wusbcmd); - } - - /* - * Now that the PZL is updated, complete the removal of any - * removed qsets. - */ - spin_lock(&whc->lock); - - list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) { - qset_remove_complete(whc, qset); - } - - spin_unlock(&whc->lock); -} - -/** - * pzl_urb_enqueue - queue an URB onto the periodic list (PZL) - * @whc: the WHCI host controller - * @urb: the URB to enqueue - * @mem_flags: flags for any memory allocations - * - * The qset for the endpoint is obtained and the urb queued on to it. - * - * Work is scheduled to update the hardware's view of the PZL. - */ -int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) -{ - struct whc_qset *qset; - int err; - unsigned long flags; - - spin_lock_irqsave(&whc->lock, flags); - - qset = get_qset(whc, urb, GFP_ATOMIC); - if (qset == NULL) - err = -ENOMEM; - else - err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); - if (!err) { - usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb); - if (!qset->in_sw_list) - qset_insert_in_sw_list(whc, qset); - } - - spin_unlock_irqrestore(&whc->lock, flags); - - if (!err) - queue_work(whc->workqueue, &whc->periodic_work); - - return 0; -} - -/** - * pzl_urb_dequeue - remove an URB (qset) from the periodic list - * @whc: the WHCI host controller - * @urb: the URB to dequeue - * @status: the current status of the URB - * - * URBs that do yet have qTDs can simply be removed from the software - * queue, otherwise the qset must be removed so the qTDs can be safely - * removed. - */ -int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status) -{ - struct whc_urb *wurb = urb->hcpriv; - struct whc_qset *qset = wurb->qset; - struct whc_std *std, *t; - int ret; - unsigned long flags; - - spin_lock_irqsave(&whc->lock, flags); - - ret = usb_hcd_check_unlink_urb(&whc->wusbhc.usb_hcd, urb, status); - if (ret < 0) - goto out; - - list_for_each_entry_safe(std, t, &qset->stds, list_node) { - if (std->urb == urb) - qset_free_std(whc, std); - else - std->qtd = NULL; /* so this std is re-added when the qset is */ - } - - pzl_qset_remove(whc, qset); - wurb->status = status; - wurb->is_async = false; - queue_work(whc->workqueue, &wurb->dequeue_work); - -out: - spin_unlock_irqrestore(&whc->lock, flags); - - return ret; -} - -/** - * pzl_qset_delete - delete a qset from the PZL - */ -void pzl_qset_delete(struct whc *whc, struct whc_qset *qset) -{ - qset->remove = 1; - queue_work(whc->workqueue, &whc->periodic_work); - qset_delete(whc, qset); -} - - -/** - * pzl_init - initialize the periodic zone list - * @whc: the WHCI host controller - */ -int pzl_init(struct whc *whc) -{ - int i; - - whc->pz_list = dma_alloc_coherent(&whc->umc->dev, sizeof(u64) * 16, - &whc->pz_list_dma, GFP_KERNEL); - if (whc->pz_list == NULL) - return -ENOMEM; - - /* Set T bit on all elements in PZL. */ - for (i = 0; i < 16; i++) - whc->pz_list[i] = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T); - - le_writeq(whc->pz_list_dma, whc->base + WUSBPERIODICLISTBASE); - - return 0; -} - -/** - * pzl_clean_up - free PZL resources - * @whc: the WHCI host controller - * - * The PZL is stopped and empty. - */ -void pzl_clean_up(struct whc *whc) -{ - if (whc->pz_list) - dma_free_coherent(&whc->umc->dev, sizeof(u64) * 16, whc->pz_list, - whc->pz_list_dma); -} diff --git a/trunk/drivers/usb/host/whci/qset.c b/trunk/drivers/usb/host/whci/qset.c deleted file mode 100644 index 0420037d2e18..000000000000 --- a/trunk/drivers/usb/host/whci/qset.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Wireless Host Controller (WHC) qset management. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -void dump_qset(struct whc_qset *qset, struct device *dev) -{ - struct whc_std *std; - struct urb *urb = NULL; - int i; - - dev_dbg(dev, "qset %08x\n", (u32)qset->qset_dma); - dev_dbg(dev, " -> %08x\n", (u32)qset->qh.link); - dev_dbg(dev, " info: %08x %08x %08x\n", - qset->qh.info1, qset->qh.info2, qset->qh.info3); - dev_dbg(dev, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); - dev_dbg(dev, " TD: sts: %08x opts: %08x\n", - qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); - - for (i = 0; i < WHCI_QSET_TD_MAX; i++) { - dev_dbg(dev, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", - i == qset->td_start ? 'S' : ' ', - i == qset->td_end ? 'E' : ' ', - i, qset->qtd[i].status, qset->qtd[i].options, - (u32)qset->qtd[i].page_list_ptr); - } - dev_dbg(dev, " ntds: %d\n", qset->ntds); - list_for_each_entry(std, &qset->stds, list_node) { - if (urb != std->urb) { - urb = std->urb; - dev_dbg(dev, " urb %p transferred: %d bytes\n", urb, - urb->actual_length); - } - if (std->qtd) - dev_dbg(dev, " sTD[%td]: %zu bytes @ %08x\n", - std->qtd - &qset->qtd[0], - std->len, std->num_pointers ? - (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); - else - dev_dbg(dev, " sTD[-]: %zd bytes @ %08x\n", - std->len, std->num_pointers ? - (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); - } -} - -struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) -{ - struct whc_qset *qset; - dma_addr_t dma; - - qset = dma_pool_alloc(whc->qset_pool, mem_flags, &dma); - if (qset == NULL) - return NULL; - memset(qset, 0, sizeof(struct whc_qset)); - - qset->qset_dma = dma; - qset->whc = whc; - - INIT_LIST_HEAD(&qset->list_node); - INIT_LIST_HEAD(&qset->stds); - - return qset; -} - -/** - * qset_fill_qh - fill the static endpoint state in a qset's QHead - * @qset: the qset whose QH needs initializing with static endpoint - * state - * @urb: an urb for a transfer to this endpoint - */ -static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) -{ - struct usb_device *usb_dev = urb->dev; - struct usb_wireless_ep_comp_descriptor *epcd; - bool is_out; - - is_out = usb_pipeout(urb->pipe); - - epcd = (struct usb_wireless_ep_comp_descriptor *)qset->ep->extra; - - if (epcd) { - qset->max_seq = epcd->bMaxSequence; - qset->max_burst = epcd->bMaxBurst; - } else { - qset->max_seq = 2; - qset->max_burst = 1; - } - - qset->qh.info1 = cpu_to_le32( - QH_INFO1_EP(usb_pipeendpoint(urb->pipe)) - | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN) - | usb_pipe_to_qh_type(urb->pipe) - | QH_INFO1_DEV_INFO_IDX(wusb_port_no_to_idx(usb_dev->portnum)) - | QH_INFO1_MAX_PKT_LEN(usb_maxpacket(urb->dev, urb->pipe, is_out)) - ); - qset->qh.info2 = cpu_to_le32( - QH_INFO2_BURST(qset->max_burst) - | QH_INFO2_DBP(0) - | QH_INFO2_MAX_COUNT(3) - | QH_INFO2_MAX_RETRY(3) - | QH_INFO2_MAX_SEQ(qset->max_seq - 1) - ); - /* FIXME: where can we obtain these Tx parameters from? Why - * doesn't the chip know what Tx power to use? It knows the Rx - * strength and can presumably guess the Tx power required - * from that? */ - qset->qh.info3 = cpu_to_le32( - QH_INFO3_TX_RATE_53_3 - | QH_INFO3_TX_PWR(0) /* 0 == max power */ - ); -} - -/** - * qset_clear - clear fields in a qset so it may be reinserted into a - * schedule - */ -void qset_clear(struct whc *whc, struct whc_qset *qset) -{ - qset->td_start = qset->td_end = qset->ntds = 0; - qset->remove = 0; - - qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); - qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start)); - qset->qh.err_count = 0; - qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); - qset->qh.scratch[0] = 0; - qset->qh.scratch[1] = 0; - qset->qh.scratch[2] = 0; - - memset(&qset->qh.overlay, 0, sizeof(qset->qh.overlay)); - - init_completion(&qset->remove_complete); -} - -/** - * get_qset - get the qset for an async endpoint - * - * A new qset is created if one does not already exist. - */ -struct whc_qset *get_qset(struct whc *whc, struct urb *urb, - gfp_t mem_flags) -{ - struct whc_qset *qset; - - qset = urb->ep->hcpriv; - if (qset == NULL) { - qset = qset_alloc(whc, mem_flags); - if (qset == NULL) - return NULL; - - qset->ep = urb->ep; - urb->ep->hcpriv = qset; - qset_fill_qh(qset, urb); - } - return qset; -} - -void qset_remove_complete(struct whc *whc, struct whc_qset *qset) -{ - list_del_init(&qset->list_node); - complete(&qset->remove_complete); -} - -/** - * qset_add_qtds - add qTDs for an URB to a qset - * - * Returns true if the list (ASL/PZL) must be updated because (for a - * WHCI 0.95 controller) an activated qTD was pointed to be iCur. - */ -enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset) -{ - struct whc_std *std; - enum whc_update update = 0; - - list_for_each_entry(std, &qset->stds, list_node) { - struct whc_qtd *qtd; - uint32_t status; - - if (qset->ntds >= WHCI_QSET_TD_MAX - || (qset->pause_after_urb && std->urb != qset->pause_after_urb)) - break; - - if (std->qtd) - continue; /* already has a qTD */ - - qtd = std->qtd = &qset->qtd[qset->td_end]; - - /* Fill in setup bytes for control transfers. */ - if (usb_pipecontrol(std->urb->pipe)) - memcpy(qtd->setup, std->urb->setup_packet, 8); - - status = QTD_STS_ACTIVE | QTD_STS_LEN(std->len); - - if (whc_std_last(std) && usb_pipeout(std->urb->pipe)) - status |= QTD_STS_LAST_PKT; - - /* - * For an IN transfer the iAlt field should be set so - * the h/w will automatically advance to the next - * transfer. However, if there are 8 or more TDs - * remaining in this transfer then iAlt cannot be set - * as it could point to somewhere in this transfer. - */ - if (std->ntds_remaining < WHCI_QSET_TD_MAX) { - int ialt; - ialt = (qset->td_end + std->ntds_remaining) % WHCI_QSET_TD_MAX; - status |= QTD_STS_IALT(ialt); - } else if (usb_pipein(std->urb->pipe)) - qset->pause_after_urb = std->urb; - - if (std->num_pointers) - qtd->options = cpu_to_le32(QTD_OPT_IOC); - else - qtd->options = cpu_to_le32(QTD_OPT_IOC | QTD_OPT_SMALL); - qtd->page_list_ptr = cpu_to_le64(std->dma_addr); - - qtd->status = cpu_to_le32(status); - - if (QH_STATUS_TO_ICUR(qset->qh.status) == qset->td_end) - update = WHC_UPDATE_UPDATED; - - if (++qset->td_end >= WHCI_QSET_TD_MAX) - qset->td_end = 0; - qset->ntds++; - } - - return update; -} - -/** - * qset_remove_qtd - remove the first qTD from a qset. - * - * The qTD might be still active (if it's part of a IN URB that - * resulted in a short read) so ensure it's deactivated. - */ -static void qset_remove_qtd(struct whc *whc, struct whc_qset *qset) -{ - qset->qtd[qset->td_start].status = 0; - - if (++qset->td_start >= WHCI_QSET_TD_MAX) - qset->td_start = 0; - qset->ntds--; -} - -/** - * qset_free_std - remove an sTD and free it. - * @whc: the WHCI host controller - * @std: the sTD to remove and free. - */ -void qset_free_std(struct whc *whc, struct whc_std *std) -{ - list_del(&std->list_node); - if (std->num_pointers) { - dma_unmap_single(whc->wusbhc.dev, std->dma_addr, - std->num_pointers * sizeof(struct whc_page_list_entry), - DMA_TO_DEVICE); - kfree(std->pl_virt); - } - - kfree(std); -} - -/** - * qset_remove_qtds - remove an URB's qTDs (and sTDs). - */ -static void qset_remove_qtds(struct whc *whc, struct whc_qset *qset, - struct urb *urb) -{ - struct whc_std *std, *t; - - list_for_each_entry_safe(std, t, &qset->stds, list_node) { - if (std->urb != urb) - break; - if (std->qtd != NULL) - qset_remove_qtd(whc, qset); - qset_free_std(whc, std); - } -} - -/** - * qset_free_stds - free any remaining sTDs for an URB. - */ -static void qset_free_stds(struct whc_qset *qset, struct urb *urb) -{ - struct whc_std *std, *t; - - list_for_each_entry_safe(std, t, &qset->stds, list_node) { - if (std->urb == urb) - qset_free_std(qset->whc, std); - } -} - -static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_flags) -{ - dma_addr_t dma_addr = std->dma_addr; - dma_addr_t sp, ep; - size_t std_len = std->len; - size_t pl_len; - int p; - - sp = ALIGN(dma_addr, WHCI_PAGE_SIZE); - ep = dma_addr + std_len; - std->num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); - - pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); - std->pl_virt = kmalloc(pl_len, mem_flags); - if (std->pl_virt == NULL) - return -ENOMEM; - std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE); - - for (p = 0; p < std->num_pointers; p++) { - std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); - dma_addr = ALIGN(dma_addr + WHCI_PAGE_SIZE, WHCI_PAGE_SIZE); - } - - return 0; -} - -/** - * urb_dequeue_work - executes asl/pzl update and gives back the urb to the system. - */ -static void urb_dequeue_work(struct work_struct *work) -{ - struct whc_urb *wurb = container_of(work, struct whc_urb, dequeue_work); - struct whc_qset *qset = wurb->qset; - struct whc *whc = qset->whc; - unsigned long flags; - - if (wurb->is_async == true) - asl_update(whc, WUSBCMD_ASYNC_UPDATED - | WUSBCMD_ASYNC_SYNCED_DB - | WUSBCMD_ASYNC_QSET_RM); - else - pzl_update(whc, WUSBCMD_PERIODIC_UPDATED - | WUSBCMD_PERIODIC_SYNCED_DB - | WUSBCMD_PERIODIC_QSET_RM); - - spin_lock_irqsave(&whc->lock, flags); - qset_remove_urb(whc, qset, wurb->urb, wurb->status); - spin_unlock_irqrestore(&whc->lock, flags); -} - -/** - * qset_add_urb - add an urb to the qset's queue. - * - * The URB is chopped into sTDs, one for each qTD that will required. - * At least one qTD (and sTD) is required even if the transfer has no - * data (e.g., for some control transfers). - */ -int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, - gfp_t mem_flags) -{ - struct whc_urb *wurb; - int remaining = urb->transfer_buffer_length; - u64 transfer_dma = urb->transfer_dma; - int ntds_remaining; - - ntds_remaining = DIV_ROUND_UP(remaining, QTD_MAX_XFER_SIZE); - if (ntds_remaining == 0) - ntds_remaining = 1; - - wurb = kzalloc(sizeof(struct whc_urb), mem_flags); - if (wurb == NULL) - goto err_no_mem; - urb->hcpriv = wurb; - wurb->qset = qset; - wurb->urb = urb; - INIT_WORK(&wurb->dequeue_work, urb_dequeue_work); - - while (ntds_remaining) { - struct whc_std *std; - size_t std_len; - - std = kmalloc(sizeof(struct whc_std), mem_flags); - if (std == NULL) - goto err_no_mem; - - std_len = remaining; - if (std_len > QTD_MAX_XFER_SIZE) - std_len = QTD_MAX_XFER_SIZE; - - std->urb = urb; - std->dma_addr = transfer_dma; - std->len = std_len; - std->ntds_remaining = ntds_remaining; - std->qtd = NULL; - - INIT_LIST_HEAD(&std->list_node); - list_add_tail(&std->list_node, &qset->stds); - - if (std_len > WHCI_PAGE_SIZE) { - if (qset_fill_page_list(whc, std, mem_flags) < 0) - goto err_no_mem; - } else - std->num_pointers = 0; - - ntds_remaining--; - remaining -= std_len; - transfer_dma += std_len; - } - - return 0; - -err_no_mem: - qset_free_stds(qset, urb); - return -ENOMEM; -} - -/** - * qset_remove_urb - remove an URB from the urb queue. - * - * The URB is returned to the USB subsystem. - */ -void qset_remove_urb(struct whc *whc, struct whc_qset *qset, - struct urb *urb, int status) -{ - struct wusbhc *wusbhc = &whc->wusbhc; - struct whc_urb *wurb = urb->hcpriv; - - usb_hcd_unlink_urb_from_ep(&wusbhc->usb_hcd, urb); - /* Drop the lock as urb->complete() may enqueue another urb. */ - spin_unlock(&whc->lock); - wusbhc_giveback_urb(wusbhc, urb, status); - spin_lock(&whc->lock); - - kfree(wurb); -} - -/** - * get_urb_status_from_qtd - get the completed urb status from qTD status - * @urb: completed urb - * @status: qTD status - */ -static int get_urb_status_from_qtd(struct urb *urb, u32 status) -{ - if (status & QTD_STS_HALTED) { - if (status & QTD_STS_DBE) - return usb_pipein(urb->pipe) ? -ENOSR : -ECOMM; - else if (status & QTD_STS_BABBLE) - return -EOVERFLOW; - else if (status & QTD_STS_RCE) - return -ETIME; - return -EPIPE; - } - if (usb_pipein(urb->pipe) - && (urb->transfer_flags & URB_SHORT_NOT_OK) - && urb->actual_length < urb->transfer_buffer_length) - return -EREMOTEIO; - return 0; -} - -/** - * process_inactive_qtd - process an inactive (but not halted) qTD. - * - * Update the urb with the transfer bytes from the qTD, if the urb is - * completely transfered or (in the case of an IN only) the LPF is - * set, then the transfer is complete and the urb should be returned - * to the system. - */ -void process_inactive_qtd(struct whc *whc, struct whc_qset *qset, - struct whc_qtd *qtd) -{ - struct whc_std *std = list_first_entry(&qset->stds, struct whc_std, list_node); - struct urb *urb = std->urb; - uint32_t status; - bool complete; - - status = le32_to_cpu(qtd->status); - - urb->actual_length += std->len - QTD_STS_TO_LEN(status); - - if (usb_pipein(urb->pipe) && (status & QTD_STS_LAST_PKT)) - complete = true; - else - complete = whc_std_last(std); - - qset_remove_qtd(whc, qset); - qset_free_std(whc, std); - - /* - * Transfers for this URB are complete? Then return it to the - * USB subsystem. - */ - if (complete) { - qset_remove_qtds(whc, qset, urb); - qset_remove_urb(whc, qset, urb, get_urb_status_from_qtd(urb, status)); - - /* - * If iAlt isn't valid then the hardware didn't - * advance iCur. Adjust the start and end pointers to - * match iCur. - */ - if (!(status & QTD_STS_IALT_VALID)) - qset->td_start = qset->td_end - = QH_STATUS_TO_ICUR(le16_to_cpu(qset->qh.status)); - qset->pause_after_urb = NULL; - } -} - -/** - * process_halted_qtd - process a qset with a halted qtd - * - * Remove all the qTDs for the failed URB and return the failed URB to - * the USB subsystem. Then remove all other qTDs so the qset can be - * removed. - * - * FIXME: this is the point where rate adaptation can be done. If a - * transfer failed because it exceeded the maximum number of retries - * then it could be reactivated with a slower rate without having to - * remove the qset. - */ -void process_halted_qtd(struct whc *whc, struct whc_qset *qset, - struct whc_qtd *qtd) -{ - struct whc_std *std = list_first_entry(&qset->stds, struct whc_std, list_node); - struct urb *urb = std->urb; - int urb_status; - - urb_status = get_urb_status_from_qtd(urb, le32_to_cpu(qtd->status)); - - qset_remove_qtds(whc, qset, urb); - qset_remove_urb(whc, qset, urb, urb_status); - - list_for_each_entry(std, &qset->stds, list_node) { - if (qset->ntds == 0) - break; - qset_remove_qtd(whc, qset); - std->qtd = NULL; - } - - qset->remove = 1; -} - -void qset_free(struct whc *whc, struct whc_qset *qset) -{ - dma_pool_free(whc->qset_pool, qset, qset->qset_dma); -} - -/** - * qset_delete - wait for a qset to be unused, then free it. - */ -void qset_delete(struct whc *whc, struct whc_qset *qset) -{ - wait_for_completion(&qset->remove_complete); - qset_free(whc, qset); -} diff --git a/trunk/drivers/usb/host/whci/whcd.h b/trunk/drivers/usb/host/whci/whcd.h deleted file mode 100644 index 1d2a53bd39fd..000000000000 --- a/trunk/drivers/usb/host/whci/whcd.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Wireless Host Controller (WHC) private header. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#ifndef __WHCD_H -#define __WHCD_H - -#include -#include - -#include "whci-hc.h" - -/* Generic command timeout. */ -#define WHC_GENCMD_TIMEOUT_MS 100 - - -struct whc { - struct wusbhc wusbhc; - struct umc_dev *umc; - - resource_size_t base_phys; - void __iomem *base; - int irq; - - u8 n_devices; - u8 n_keys; - u8 n_mmc_ies; - - u64 *pz_list; - struct dn_buf_entry *dn_buf; - struct di_buf_entry *di_buf; - dma_addr_t pz_list_dma; - dma_addr_t dn_buf_dma; - dma_addr_t di_buf_dma; - - spinlock_t lock; - struct mutex mutex; - - void * gen_cmd_buf; - dma_addr_t gen_cmd_buf_dma; - wait_queue_head_t cmd_wq; - - struct workqueue_struct *workqueue; - struct work_struct dn_work; - - struct dma_pool *qset_pool; - - struct list_head async_list; - struct list_head async_removed_list; - wait_queue_head_t async_list_wq; - struct work_struct async_work; - - struct list_head periodic_list[5]; - struct list_head periodic_removed_list; - wait_queue_head_t periodic_list_wq; - struct work_struct periodic_work; -}; - -#define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc)) - -/** - * struct whc_std - a software TD. - * @urb: the URB this sTD is for. - * @offset: start of the URB's data for this TD. - * @len: the length of data in the associated TD. - * @ntds_remaining: number of TDs (starting from this one) in this transfer. - * - * Queued URBs may require more TDs than are available in a qset so we - * use a list of these "software TDs" (sTDs) to hold per-TD data. - */ -struct whc_std { - struct urb *urb; - size_t len; - int ntds_remaining; - struct whc_qtd *qtd; - - struct list_head list_node; - int num_pointers; - dma_addr_t dma_addr; - struct whc_page_list_entry *pl_virt; -}; - -/** - * struct whc_urb - per URB host controller structure. - * @urb: the URB this struct is for. - * @qset: the qset associated to the URB. - * @dequeue_work: the work to remove the URB when dequeued. - * @is_async: the URB belongs to async sheduler or not. - * @status: the status to be returned when calling wusbhc_giveback_urb. - */ -struct whc_urb { - struct urb *urb; - struct whc_qset *qset; - struct work_struct dequeue_work; - bool is_async; - int status; -}; - -/** - * whc_std_last - is this sTD the URB's last? - * @std: the sTD to check. - */ -static inline bool whc_std_last(struct whc_std *std) -{ - return std->ntds_remaining <= 1; -} - -enum whc_update { - WHC_UPDATE_ADDED = 0x01, - WHC_UPDATE_REMOVED = 0x02, - WHC_UPDATE_UPDATED = 0x04, -}; - -/* init.c */ -int whc_init(struct whc *whc); -void whc_clean_up(struct whc *whc); - -/* hw.c */ -void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); -int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); - -/* wusb.c */ -int whc_wusbhc_start(struct wusbhc *wusbhc); -void whc_wusbhc_stop(struct wusbhc *wusbhc); -int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, - u8 handle, struct wuie_hdr *wuie); -int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); -int whc_bwa_set(struct wusbhc *wusbhc, s8 stream_index, const struct uwb_mas_bm *mas_bm); -int whc_dev_info_set(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev); -int whc_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots); -int whc_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, - const void *ptk, size_t key_size); -int whc_set_gtk(struct wusbhc *wusbhc, u32 tkid, - const void *gtk, size_t key_size); -int whc_set_cluster_id(struct whc *whc, u8 bcid); - -/* int.c */ -irqreturn_t whc_int_handler(struct usb_hcd *hcd); -void whc_dn_work(struct work_struct *work); - -/* asl.c */ -void asl_start(struct whc *whc); -void asl_stop(struct whc *whc); -int asl_init(struct whc *whc); -void asl_clean_up(struct whc *whc); -int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags); -int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status); -void asl_qset_delete(struct whc *whc, struct whc_qset *qset); -void scan_async_work(struct work_struct *work); - -/* pzl.c */ -int pzl_init(struct whc *whc); -void pzl_clean_up(struct whc *whc); -void pzl_start(struct whc *whc); -void pzl_stop(struct whc *whc); -int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags); -int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status); -void pzl_qset_delete(struct whc *whc, struct whc_qset *qset); -void scan_periodic_work(struct work_struct *work); - -/* qset.c */ -struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags); -void qset_free(struct whc *whc, struct whc_qset *qset); -struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); -void qset_delete(struct whc *whc, struct whc_qset *qset); -void qset_clear(struct whc *whc, struct whc_qset *qset); -int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, - gfp_t mem_flags); -void qset_free_std(struct whc *whc, struct whc_std *std); -void qset_remove_urb(struct whc *whc, struct whc_qset *qset, - struct urb *urb, int status); -void process_halted_qtd(struct whc *whc, struct whc_qset *qset, - struct whc_qtd *qtd); -void process_inactive_qtd(struct whc *whc, struct whc_qset *qset, - struct whc_qtd *qtd); -enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset); -void qset_remove_complete(struct whc *whc, struct whc_qset *qset); -void dump_qset(struct whc_qset *qset, struct device *dev); -void pzl_update(struct whc *whc, uint32_t wusbcmd); -void asl_update(struct whc *whc, uint32_t wusbcmd); - -#endif /* #ifndef __WHCD_H */ diff --git a/trunk/drivers/usb/host/whci/whci-hc.h b/trunk/drivers/usb/host/whci/whci-hc.h deleted file mode 100644 index bff1eb7a35cf..000000000000 --- a/trunk/drivers/usb/host/whci/whci-hc.h +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Wireless Host Controller (WHC) data structures. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#ifndef _WHCI_WHCI_HC_H -#define _WHCI_WHCI_HC_H - -#include - -/** - * WHCI_PAGE_SIZE - page size use by WHCI - * - * WHCI assumes that host system uses pages of 4096 octets. - */ -#define WHCI_PAGE_SIZE 4096 - - -/** - * QTD_MAX_TXFER_SIZE - max number of bytes to transfer with a single - * qtd. - * - * This is 2^20 - 1. - */ -#define QTD_MAX_XFER_SIZE 1048575 - - -/** - * struct whc_qtd - Queue Element Transfer Descriptors (qTD) - * - * This describes the data for a bulk, control or interrupt transfer. - * - * [WHCI] section 3.2.4 - */ -struct whc_qtd { - __le32 status; /*< remaining transfer len and transfer status */ - __le32 options; - __le64 page_list_ptr; /*< physical pointer to data buffer page list*/ - __u8 setup[8]; /*< setup data for control transfers */ -} __attribute__((packed)); - -#define QTD_STS_ACTIVE (1 << 31) /* enable execution of transaction */ -#define QTD_STS_HALTED (1 << 30) /* transfer halted */ -#define QTD_STS_DBE (1 << 29) /* data buffer error */ -#define QTD_STS_BABBLE (1 << 28) /* babble detected */ -#define QTD_STS_RCE (1 << 27) /* retry count exceeded */ -#define QTD_STS_LAST_PKT (1 << 26) /* set Last Packet Flag in WUSB header */ -#define QTD_STS_INACTIVE (1 << 25) /* queue set is marked inactive */ -#define QTD_STS_IALT_VALID (1 << 23) /* iAlt field is valid */ -#define QTD_STS_IALT(i) (QTD_STS_IALT_VALID | ((i) << 20)) /* iAlt field */ -#define QTD_STS_LEN(l) ((l) << 0) /* transfer length */ -#define QTD_STS_TO_LEN(s) ((s) & 0x000fffff) - -#define QTD_OPT_IOC (1 << 1) /* page_list_ptr points to buffer directly */ -#define QTD_OPT_SMALL (1 << 0) /* interrupt on complete */ - -/** - * struct whc_itd - Isochronous Queue Element Transfer Descriptors (iTD) - * - * This describes the data and other parameters for an isochronous - * transfer. - * - * [WHCI] section 3.2.5 - */ -struct whc_itd { - __le16 presentation_time; /*< presentation time for OUT transfers */ - __u8 num_segments; /*< number of data segments in segment list */ - __u8 status; /*< command execution status */ - __le32 options; /*< misc transfer options */ - __le64 page_list_ptr; /*< physical pointer to data buffer page list */ - __le64 seg_list_ptr; /*< physical pointer to segment list */ -} __attribute__((packed)); - -#define ITD_STS_ACTIVE (1 << 7) /* enable execution of transaction */ -#define ITD_STS_DBE (1 << 5) /* data buffer error */ -#define ITD_STS_BABBLE (1 << 4) /* babble detected */ -#define ITD_STS_INACTIVE (1 << 1) /* queue set is marked inactive */ - -#define ITD_OPT_IOC (1 << 1) /* interrupt on complete */ -#define ITD_OPT_SMALL (1 << 0) /* page_list_ptr points to buffer directly */ - -/** - * Page list entry. - * - * A TD's page list must contain sufficient page list entries for the - * total data length in the TD. - * - * [WHCI] section 3.2.4.3 - */ -struct whc_page_list_entry { - __le64 buf_ptr; /*< physical pointer to buffer */ -} __attribute__((packed)); - -/** - * struct whc_seg_list_entry - Segment list entry. - * - * Describes a portion of the data buffer described in the containing - * qTD's page list. - * - * seg_ptr = qtd->page_list_ptr[qtd->seg_list_ptr[seg].idx].buf_ptr - * + qtd->seg_list_ptr[seg].offset; - * - * Segments can't cross page boundries. - * - * [WHCI] section 3.2.5.5 - */ -struct whc_seg_list_entry { - __le16 len; /*< segment length */ - __u8 idx; /*< index into page list */ - __u8 status; /*< segment status */ - __le16 offset; /*< 12 bit offset into page */ -} __attribute__((packed)); - -/** - * struct whc_qhead - endpoint and status information for a qset. - * - * [WHCI] section 3.2.6 - */ -struct whc_qhead { - __le64 link; /*< next qset in list */ - __le32 info1; - __le32 info2; - __le32 info3; - __le16 status; - __le16 err_count; /*< transaction error count */ - __le32 cur_window; - __le32 scratch[3]; /*< h/w scratch area */ - union { - struct whc_qtd qtd; - struct whc_itd itd; - } overlay; -} __attribute__((packed)); - -#define QH_LINK_PTR_MASK (~0x03Full) -#define QH_LINK_PTR(ptr) ((ptr) & QH_LINK_PTR_MASK) -#define QH_LINK_IQS (1 << 4) /* isochronous queue set */ -#define QH_LINK_NTDS(n) (((n) - 1) << 1) /* number of TDs in queue set */ -#define QH_LINK_T (1 << 0) /* last queue set in periodic schedule list */ - -#define QH_INFO1_EP(e) ((e) << 0) /* endpoint number */ -#define QH_INFO1_DIR_IN (1 << 4) /* IN transfer */ -#define QH_INFO1_DIR_OUT (0 << 4) /* OUT transfer */ -#define QH_INFO1_TR_TYPE_CTRL (0x0 << 5) /* control transfer */ -#define QH_INFO1_TR_TYPE_ISOC (0x1 << 5) /* isochronous transfer */ -#define QH_INFO1_TR_TYPE_BULK (0x2 << 5) /* bulk transfer */ -#define QH_INFO1_TR_TYPE_INT (0x3 << 5) /* interrupt */ -#define QH_INFO1_TR_TYPE_LP_INT (0x7 << 5) /* low power interrupt */ -#define QH_INFO1_DEV_INFO_IDX(i) ((i) << 8) /* index into device info buffer */ -#define QH_INFO1_SET_INACTIVE (1 << 15) /* set inactive after transfer */ -#define QH_INFO1_MAX_PKT_LEN(l) ((l) << 16) /* maximum packet length */ - -#define QH_INFO2_BURST(b) ((b) << 0) /* maximum burst length */ -#define QH_INFO2_DBP(p) ((p) << 5) /* data burst policy (see [WUSB] table 5-7) */ -#define QH_INFO2_MAX_COUNT(c) ((c) << 8) /* max isoc/int pkts per zone */ -#define QH_INFO2_RQS (1 << 15) /* reactivate queue set */ -#define QH_INFO2_MAX_RETRY(r) ((r) << 16) /* maximum transaction retries */ -#define QH_INFO2_MAX_SEQ(s) ((s) << 20) /* maximum sequence number */ -#define QH_INFO3_MAX_DELAY(d) ((d) << 0) /* maximum stream delay in 125 us units (isoc only) */ -#define QH_INFO3_INTERVAL(i) ((i) << 16) /* segment interval in 125 us units (isoc only) */ - -#define QH_INFO3_TX_RATE_53_3 (0 << 24) -#define QH_INFO3_TX_RATE_80 (1 << 24) -#define QH_INFO3_TX_RATE_106_7 (2 << 24) -#define QH_INFO3_TX_RATE_160 (3 << 24) -#define QH_INFO3_TX_RATE_200 (4 << 24) -#define QH_INFO3_TX_RATE_320 (5 << 24) -#define QH_INFO3_TX_RATE_400 (6 << 24) -#define QH_INFO3_TX_RATE_480 (7 << 24) -#define QH_INFO3_TX_PWR(p) ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */ - -#define QH_STATUS_FLOW_CTRL (1 << 15) -#define QH_STATUS_ICUR(i) ((i) << 5) -#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) - -/** - * usb_pipe_to_qh_type - USB core pipe type to QH transfer type - * - * Returns the QH type field for a USB core pipe type. - */ -static inline unsigned usb_pipe_to_qh_type(unsigned pipe) -{ - static const unsigned type[] = { - [PIPE_ISOCHRONOUS] = QH_INFO1_TR_TYPE_ISOC, - [PIPE_INTERRUPT] = QH_INFO1_TR_TYPE_INT, - [PIPE_CONTROL] = QH_INFO1_TR_TYPE_CTRL, - [PIPE_BULK] = QH_INFO1_TR_TYPE_BULK, - }; - return type[usb_pipetype(pipe)]; -} - -/** - * Maxiumum number of TDs in a qset. - */ -#define WHCI_QSET_TD_MAX 8 - -/** - * struct whc_qset - WUSB data transfers to a specific endpoint - * @qh: the QHead of this qset - * @qtd: up to 8 qTDs (for qsets for control, bulk and interrupt - * transfers) - * @itd: up to 8 iTDs (for qsets for isochronous transfers) - * @qset_dma: DMA address for this qset - * @whc: WHCI HC this qset is for - * @ep: endpoint - * @stds: list of sTDs queued to this qset - * @ntds: number of qTDs queued (not necessarily the same as nTDs - * field in the QH) - * @td_start: index of the first qTD in the list - * @td_end: index of next free qTD in the list (provided - * ntds < WHCI_QSET_TD_MAX) - * - * Queue Sets (qsets) are added to the asynchronous schedule list - * (ASL) or the periodic zone list (PZL). - * - * qsets may contain up to 8 TDs (either qTDs or iTDs as appropriate). - * Each TD may refer to at most 1 MiB of data. If a single transfer - * has > 8MiB of data, TDs can be reused as they are completed since - * the TD list is used as a circular buffer. Similarly, several - * (smaller) transfers may be queued in a qset. - * - * WHCI controllers may cache portions of the qsets in the ASL and - * PZL, requiring the WHCD to inform the WHC that the lists have been - * updated (fields changed or qsets inserted or removed). For safe - * insertion and removal of qsets from the lists the schedule must be - * stopped to avoid races in updating the QH link pointers. - * - * Since the HC is free to execute qsets in any order, all transfers - * to an endpoint should use the same qset to ensure transfers are - * executed in the order they're submitted. - * - * [WHCI] section 3.2.3 - */ -struct whc_qset { - struct whc_qhead qh; - union { - struct whc_qtd qtd[WHCI_QSET_TD_MAX]; - struct whc_itd itd[WHCI_QSET_TD_MAX]; - }; - - /* private data for WHCD */ - dma_addr_t qset_dma; - struct whc *whc; - struct usb_host_endpoint *ep; - struct list_head stds; - int ntds; - int td_start; - int td_end; - struct list_head list_node; - unsigned in_sw_list:1; - unsigned in_hw_list:1; - unsigned remove:1; - struct urb *pause_after_urb; - struct completion remove_complete; - int max_burst; - int max_seq; -}; - -static inline void whc_qset_set_link_ptr(u64 *ptr, u64 target) -{ - if (target) - *ptr = (*ptr & ~(QH_LINK_PTR_MASK | QH_LINK_T)) | QH_LINK_PTR(target); - else - *ptr = QH_LINK_T; -} - -/** - * struct di_buf_entry - Device Information (DI) buffer entry. - * - * There's one of these per connected device. - */ -struct di_buf_entry { - __le32 availability_info[8]; /*< MAS availability information, one MAS per bit */ - __le32 addr_sec_info; /*< addressing and security info */ - __le32 reserved[7]; -} __attribute__((packed)); - -#define WHC_DI_SECURE (1 << 31) -#define WHC_DI_DISABLE (1 << 30) -#define WHC_DI_KEY_IDX(k) ((k) << 8) -#define WHC_DI_KEY_IDX_MASK 0x0000ff00 -#define WHC_DI_DEV_ADDR(a) ((a) << 0) -#define WHC_DI_DEV_ADDR_MASK 0x000000ff - -/** - * struct dn_buf_entry - Device Notification (DN) buffer entry. - * - * [WHCI] section 3.2.8 - */ -struct dn_buf_entry { - __u8 msg_size; /*< number of octets of valid DN data */ - __u8 reserved1; - __u8 src_addr; /*< source address */ - __u8 status; /*< buffer entry status */ - __le32 tkid; /*< TKID for source device, valid if secure bit is set */ - __u8 dn_data[56]; /*< up to 56 octets of DN data */ -} __attribute__((packed)); - -#define WHC_DN_STATUS_VALID (1 << 7) /* buffer entry is valid */ -#define WHC_DN_STATUS_SECURE (1 << 6) /* notification received using secure frame */ - -#define WHC_N_DN_ENTRIES (4096 / sizeof(struct dn_buf_entry)) - -/* The Add MMC IE WUSB Generic Command may take up to 256 bytes of - data. [WHCI] section 2.4.7. */ -#define WHC_GEN_CMD_DATA_LEN 256 - -/* - * HC registers. - * - * [WHCI] section 2.4 - */ - -#define WHCIVERSION 0x00 - -#define WHCSPARAMS 0x04 -# define WHCSPARAMS_TO_N_MMC_IES(p) (((p) >> 16) & 0xff) -# define WHCSPARAMS_TO_N_KEYS(p) (((p) >> 8) & 0xff) -# define WHCSPARAMS_TO_N_DEVICES(p) (((p) >> 0) & 0x7f) - -#define WUSBCMD 0x08 -# define WUSBCMD_BCID(b) ((b) << 16) -# define WUSBCMD_BCID_MASK (0xff << 16) -# define WUSBCMD_ASYNC_QSET_RM (1 << 12) -# define WUSBCMD_PERIODIC_QSET_RM (1 << 11) -# define WUSBCMD_WUSBSI(s) ((s) << 8) -# define WUSBCMD_WUSBSI_MASK (0x7 << 8) -# define WUSBCMD_ASYNC_SYNCED_DB (1 << 7) -# define WUSBCMD_PERIODIC_SYNCED_DB (1 << 6) -# define WUSBCMD_ASYNC_UPDATED (1 << 5) -# define WUSBCMD_PERIODIC_UPDATED (1 << 4) -# define WUSBCMD_ASYNC_EN (1 << 3) -# define WUSBCMD_PERIODIC_EN (1 << 2) -# define WUSBCMD_WHCRESET (1 << 1) -# define WUSBCMD_RUN (1 << 0) - -#define WUSBSTS 0x0c -# define WUSBSTS_ASYNC_SCHED (1 << 15) -# define WUSBSTS_PERIODIC_SCHED (1 << 14) -# define WUSBSTS_DNTS_SCHED (1 << 13) -# define WUSBSTS_HCHALTED (1 << 12) -# define WUSBSTS_GEN_CMD_DONE (1 << 9) -# define WUSBSTS_CHAN_TIME_ROLLOVER (1 << 8) -# define WUSBSTS_DNTS_OVERFLOW (1 << 7) -# define WUSBSTS_BPST_ADJUSTMENT_CHANGED (1 << 6) -# define WUSBSTS_HOST_ERR (1 << 5) -# define WUSBSTS_ASYNC_SCHED_SYNCED (1 << 4) -# define WUSBSTS_PERIODIC_SCHED_SYNCED (1 << 3) -# define WUSBSTS_DNTS_INT (1 << 2) -# define WUSBSTS_ERR_INT (1 << 1) -# define WUSBSTS_INT (1 << 0) -# define WUSBSTS_INT_MASK 0x3ff - -#define WUSBINTR 0x10 -# define WUSBINTR_GEN_CMD_DONE (1 << 9) -# define WUSBINTR_CHAN_TIME_ROLLOVER (1 << 8) -# define WUSBINTR_DNTS_OVERFLOW (1 << 7) -# define WUSBINTR_BPST_ADJUSTMENT_CHANGED (1 << 6) -# define WUSBINTR_HOST_ERR (1 << 5) -# define WUSBINTR_ASYNC_SCHED_SYNCED (1 << 4) -# define WUSBINTR_PERIODIC_SCHED_SYNCED (1 << 3) -# define WUSBINTR_DNTS_INT (1 << 2) -# define WUSBINTR_ERR_INT (1 << 1) -# define WUSBINTR_INT (1 << 0) -# define WUSBINTR_ALL 0x3ff - -#define WUSBGENCMDSTS 0x14 -# define WUSBGENCMDSTS_ACTIVE (1 << 31) -# define WUSBGENCMDSTS_ERROR (1 << 24) -# define WUSBGENCMDSTS_IOC (1 << 23) -# define WUSBGENCMDSTS_MMCIE_ADD 0x01 -# define WUSBGENCMDSTS_MMCIE_RM 0x02 -# define WUSBGENCMDSTS_SET_MAS 0x03 -# define WUSBGENCMDSTS_CHAN_STOP 0x04 -# define WUSBGENCMDSTS_RWP_EN 0x05 - -#define WUSBGENCMDPARAMS 0x18 -#define WUSBGENADDR 0x20 -#define WUSBASYNCLISTADDR 0x28 -#define WUSBDNTSBUFADDR 0x30 -#define WUSBDEVICEINFOADDR 0x38 - -#define WUSBSETSECKEYCMD 0x40 -# define WUSBSETSECKEYCMD_SET (1 << 31) -# define WUSBSETSECKEYCMD_ERASE (1 << 30) -# define WUSBSETSECKEYCMD_GTK (1 << 8) -# define WUSBSETSECKEYCMD_IDX(i) ((i) << 0) - -#define WUSBTKID 0x44 -#define WUSBSECKEY 0x48 -#define WUSBPERIODICLISTBASE 0x58 -#define WUSBMASINDEX 0x60 - -#define WUSBDNTSCTRL 0x64 -# define WUSBDNTSCTRL_ACTIVE (1 << 31) -# define WUSBDNTSCTRL_INTERVAL(i) ((i) << 8) -# define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) - -#define WUSBTIME 0x68 -#define WUSBBPST 0x6c -#define WUSBDIBUPDATED 0x70 - -#endif /* #ifndef _WHCI_WHCI_HC_H */ diff --git a/trunk/drivers/usb/host/whci/wusb.c b/trunk/drivers/usb/host/whci/wusb.c deleted file mode 100644 index 66e4ddcd961d..000000000000 --- a/trunk/drivers/usb/host/whci/wusb.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Wireless Host Controller (WHC) WUSB operations. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include -#define D_LOCAL 1 -#include - -#include "../../wusbcore/wusbhc.h" - -#include "whcd.h" - -#if D_LOCAL >= 1 -static void dump_di(struct whc *whc, int idx) -{ - struct di_buf_entry *di = &whc->di_buf[idx]; - struct device *dev = &whc->umc->dev; - char buf[128]; - - bitmap_scnprintf(buf, sizeof(buf), (unsigned long *)di->availability_info, UWB_NUM_MAS); - - d_printf(1, dev, "DI[%d]\n", idx); - d_printf(1, dev, " availability: %s\n", buf); - d_printf(1, dev, " %c%c key idx: %d dev addr: %d\n", - (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ', - (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ', - (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8, - (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK)); -} -#else -static inline void dump_di(struct whc *whc, int idx) -{ -} -#endif - -static int whc_update_di(struct whc *whc, int idx) -{ - int offset = idx / 32; - u32 bit = 1 << (idx % 32); - - dump_di(whc, idx); - - le_writel(bit, whc->base + WUSBDIBUPDATED + offset); - - return whci_wait_for(&whc->umc->dev, - whc->base + WUSBDIBUPDATED + offset, bit, 0, - 100, "DI update"); -} - -/* - * WHCI starts and stops MMCs based on there being a valid GTK so - * these need only start/stop the asynchronous and periodic schedules. - */ - -int whc_wusbhc_start(struct wusbhc *wusbhc) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - - asl_start(whc); - pzl_start(whc); - - return 0; -} - -void whc_wusbhc_stop(struct wusbhc *wusbhc) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - - pzl_stop(whc); - asl_stop(whc); -} - -int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, - u8 handle, struct wuie_hdr *wuie) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - u32 params; - - params = (interval << 24) - | (repeat_cnt << 16) - | (wuie->bLength << 8) - | handle; - - return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_ADD, params, wuie, wuie->bLength); -} - -int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - u32 params; - - params = handle; - - return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_RM, params, NULL, 0); -} - -int whc_bwa_set(struct wusbhc *wusbhc, s8 stream_index, const struct uwb_mas_bm *mas_bm) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - - if (stream_index >= 0) - whc_write_wusbcmd(whc, WUSBCMD_WUSBSI_MASK, WUSBCMD_WUSBSI(stream_index)); - - return whc_do_gencmd(whc, WUSBGENCMDSTS_SET_MAS, 0, (void *)mas_bm, sizeof(*mas_bm)); -} - -int whc_dev_info_set(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - int idx = wusb_dev->port_idx; - struct di_buf_entry *di = &whc->di_buf[idx]; - int ret; - - mutex_lock(&whc->mutex); - - uwb_mas_bm_copy_le(di->availability_info, &wusb_dev->availability); - di->addr_sec_info &= ~(WHC_DI_DISABLE | WHC_DI_DEV_ADDR_MASK); - di->addr_sec_info |= WHC_DI_DEV_ADDR(wusb_dev->addr); - - ret = whc_update_di(whc, idx); - - mutex_unlock(&whc->mutex); - - return ret; -} - -/* - * Set the number of Device Notification Time Slots (DNTS) and enable - * device notifications. - */ -int whc_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - u32 dntsctrl; - - dntsctrl = WUSBDNTSCTRL_ACTIVE - | WUSBDNTSCTRL_INTERVAL(interval) - | WUSBDNTSCTRL_SLOTS(slots); - - le_writel(dntsctrl, whc->base + WUSBDNTSCTRL); - - return 0; -} - -static int whc_set_key(struct whc *whc, u8 key_index, uint32_t tkid, - const void *key, size_t key_size, bool is_gtk) -{ - uint32_t setkeycmd; - uint32_t seckey[4]; - int i; - int ret; - - memcpy(seckey, key, key_size); - setkeycmd = WUSBSETSECKEYCMD_SET | WUSBSETSECKEYCMD_IDX(key_index); - if (is_gtk) - setkeycmd |= WUSBSETSECKEYCMD_GTK; - - le_writel(tkid, whc->base + WUSBTKID); - for (i = 0; i < 4; i++) - le_writel(seckey[i], whc->base + WUSBSECKEY + 4*i); - le_writel(setkeycmd, whc->base + WUSBSETSECKEYCMD); - - ret = whci_wait_for(&whc->umc->dev, whc->base + WUSBSETSECKEYCMD, - WUSBSETSECKEYCMD_SET, 0, 100, "set key"); - - return ret; -} - -/** - * whc_set_ptk - set the PTK to use for a device. - * - * The index into the key table for this PTK is the same as the - * device's port index. - */ -int whc_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, - const void *ptk, size_t key_size) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - struct di_buf_entry *di = &whc->di_buf[port_idx]; - int ret; - - mutex_lock(&whc->mutex); - - if (ptk) { - ret = whc_set_key(whc, port_idx, tkid, ptk, key_size, false); - if (ret) - goto out; - - di->addr_sec_info &= ~WHC_DI_KEY_IDX_MASK; - di->addr_sec_info |= WHC_DI_SECURE | WHC_DI_KEY_IDX(port_idx); - } else - di->addr_sec_info &= ~WHC_DI_SECURE; - - ret = whc_update_di(whc, port_idx); -out: - mutex_unlock(&whc->mutex); - return ret; -} - -/** - * whc_set_gtk - set the GTK for subsequent broadcast packets - * - * The GTK is stored in the last entry in the key table (the previous - * N_DEVICES entries are for the per-device PTKs). - */ -int whc_set_gtk(struct wusbhc *wusbhc, u32 tkid, - const void *gtk, size_t key_size) -{ - struct whc *whc = wusbhc_to_whc(wusbhc); - int ret; - - mutex_lock(&whc->mutex); - - ret = whc_set_key(whc, whc->n_devices, tkid, gtk, key_size, true); - - mutex_unlock(&whc->mutex); - - return ret; -} - -int whc_set_cluster_id(struct whc *whc, u8 bcid) -{ - whc_write_wusbcmd(whc, WUSBCMD_BCID_MASK, WUSBCMD_BCID(bcid)); - return 0; -} diff --git a/trunk/drivers/usb/wusbcore/Kconfig b/trunk/drivers/usb/wusbcore/Kconfig deleted file mode 100644 index eb09a0a14a80..000000000000 --- a/trunk/drivers/usb/wusbcore/Kconfig +++ /dev/null @@ -1,41 +0,0 @@ -# -# Wireless USB Core configuration -# -config USB_WUSB - tristate "Enable Wireless USB extensions (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on USB - select UWB - select CRYPTO - select CRYPTO_BLKCIPHER - select CRYPTO_CBC - select CRYPTO_MANAGER - select CRYPTO_AES - help - Enable the host-side support for Wireless USB. - - To compile this support select Y (built in). It is safe to - select even if you don't have the hardware. - -config USB_WUSB_CBAF - tristate "Support WUSB Cable Based Association (CBA)" - depends on USB - help - Some WUSB devices support Cable Based Association. It's used to - enable the secure communication between the host and the - device. - - Enable this option if your WUSB device must to be connected - via wired USB before establishing a wireless link. - - It is safe to select even if you don't have a compatible - hardware. - -config USB_WUSB_CBAF_DEBUG - bool "Enable CBA debug messages" - depends on USB_WUSB_CBAF - help - Say Y here if you want the CBA to produce a bunch of debug messages - to the system log. Select this if you are having a problem with - CBA support and want to see more of what is going on. - diff --git a/trunk/drivers/usb/wusbcore/Makefile b/trunk/drivers/usb/wusbcore/Makefile deleted file mode 100644 index 75f1ade66258..000000000000 --- a/trunk/drivers/usb/wusbcore/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -obj-$(CONFIG_USB_WUSB) += wusbcore.o -obj-$(CONFIG_USB_HWA_HCD) += wusb-wa.o -obj-$(CONFIG_USB_WUSB_CBAF) += wusb-cbaf.o - - -wusbcore-objs := \ - crypto.o \ - devconnect.o \ - dev-sysfs.o \ - mmc.o \ - pal.o \ - rh.o \ - reservation.o \ - security.o \ - wusbhc.o - -wusb-cbaf-objs := cbaf.o - -wusb-wa-objs := wa-hc.o \ - wa-nep.o \ - wa-rpipe.o \ - wa-xfer.o - -ifeq ($(CONFIG_USB_WUSB_CBAF_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif diff --git a/trunk/drivers/usb/wusbcore/cbaf.c b/trunk/drivers/usb/wusbcore/cbaf.c deleted file mode 100644 index ab4788d1785a..000000000000 --- a/trunk/drivers/usb/wusbcore/cbaf.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Wireless USB - Cable Based Association - * - * - * Copyright (C) 2006 Intel Corporation - * Inaky Perez-Gonzalez - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * WUSB devices have to be paired (associated in WUSB lingo) so - * that they can connect to the system. - * - * One way of pairing is using CBA-Cable Based Association. First - * time you plug the device with a cable, association is done between - * host and device and subsequent times, you can connect wirelessly - * without having to associate again. That's the idea. - * - * This driver does nothing Earth shattering. It just provides an - * interface to chat with the wire-connected device so we can get a - * CDID (device ID) that might have been previously associated to a - * CHID (host ID) and to set up a new triplet - * (connection context), with the CK being the secret, or connection - * key. This is the pairing data. - * - * When a device with the CBA capability connects, the probe routine - * just creates a bunch of sysfs files that a user space enumeration - * manager uses to allow it to connect wirelessly to the system or not. - * - * The process goes like this: - * - * 1. Device plugs, cbaf is loaded, notifications happen. - * - * 2. The connection manager (CM) sees a device with CBAF capability - * (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE). - * - * 3. The CM writes the host name, supported band groups, and the CHID - * (host ID) into the wusb_host_name, wusb_host_band_groups and - * wusb_chid files. These get sent to the device and the CDID (if - * any) for this host is requested. - * - * 4. The CM can verify that the device's supported band groups - * (wusb_device_band_groups) are compatible with the host. - * - * 5. The CM reads the wusb_cdid file. - * - * 6. The CM looks up its database - * - * 6.1 If it has a matching CHID,CDID entry, the device has been - * authorized before (paired) and nothing further needs to be - * done. - * - * 6.2 If the CDID is zero (or the CM doesn't find a matching CDID in - * its database), the device is assumed to be not known. The CM - * may associate the host with device by: writing a randomly - * generated CDID to wusb_cdid and then a random CK to wusb_ck - * (this uploads the new CC to the device). - * - * CMD may choose to prompt the user before associating with a new - * device. - * - * 7. Device is unplugged. - * - * When the device tries to connect wirelessly, it will present its - * CDID to the WUSB host controller. The CM will query the - * database. If the CHID/CDID pair found, it will (with a 4-way - * handshake) challenge the device to demonstrate it has the CK secret - * key (from our database) without actually exchanging it. Once - * satisfied, crypto keys are derived from the CK, the device is - * connected and all communication is encrypted. - * - * References: - * [WUSB-AM] Association Models Supplement to the Certified Wireless - * Universal Serial Bus Specification, version 1.0. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */ - -/* An instance of a Cable-Based-Association-Framework device */ -struct cbaf { - struct usb_device *usb_dev; - struct usb_interface *usb_iface; - void *buffer; - size_t buffer_size; - - struct wusb_ckhdid chid; - char host_name[CBA_NAME_LEN]; - u16 host_band_groups; - - struct wusb_ckhdid cdid; - char device_name[CBA_NAME_LEN]; - u16 device_band_groups; - - struct wusb_ckhdid ck; -}; - -/* - * Verify that a CBAF USB-interface has what we need - * - * According to [WUSB-AM], CBA devices should provide at least two - * interfaces: - * - RETRIEVE_HOST_INFO - * - ASSOCIATE - * - * If the device doesn't provide these interfaces, we do not know how - * to deal with it. - */ -static int cbaf_check(struct cbaf *cbaf) -{ - int result; - struct device *dev = &cbaf->usb_iface->dev; - struct wusb_cbaf_assoc_info *assoc_info; - struct wusb_cbaf_assoc_request *assoc_request; - size_t assoc_size; - void *itr, *top; - int ar_rhi = 0, ar_assoc = 0; - - result = usb_control_msg( - cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0), - CBAF_REQ_GET_ASSOCIATION_INFORMATION, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Cannot get available association types: %d\n", - result); - return result; - } - - assoc_info = cbaf->buffer; - if (result < sizeof(*assoc_info)) { - dev_err(dev, "Not enough data to decode association info " - "header (%zu vs %zu bytes required)\n", - (size_t)result, sizeof(*assoc_info)); - return result; - } - - assoc_size = le16_to_cpu(assoc_info->Length); - if (result < assoc_size) { - dev_err(dev, "Not enough data to decode association info " - "(%zu vs %zu bytes required)\n", - (size_t)assoc_size, sizeof(*assoc_info)); - return result; - } - /* - * From now on, we just verify, but won't error out unless we - * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE} - * types. - */ - itr = cbaf->buffer + sizeof(*assoc_info); - top = cbaf->buffer + assoc_size; - dev_dbg(dev, "Found %u association requests (%zu bytes)\n", - assoc_info->NumAssociationRequests, assoc_size); - - while (itr < top) { - u16 ar_type, ar_subtype; - u32 ar_size; - const char *ar_name; - - assoc_request = itr; - - if (top - itr < sizeof(*assoc_request)) { - dev_err(dev, "Not enough data to decode associaton " - "request (%zu vs %zu bytes needed)\n", - top - itr, sizeof(*assoc_request)); - break; - } - - ar_type = le16_to_cpu(assoc_request->AssociationTypeId); - ar_subtype = le16_to_cpu(assoc_request->AssociationSubTypeId); - ar_size = le32_to_cpu(assoc_request->AssociationTypeInfoSize); - ar_name = "unknown"; - - switch (ar_type) { - case AR_TYPE_WUSB: - /* Verify we have what is mandated by [WUSB-AM]. */ - switch (ar_subtype) { - case AR_TYPE_WUSB_RETRIEVE_HOST_INFO: - ar_name = "RETRIEVE_HOST_INFO"; - ar_rhi = 1; - break; - case AR_TYPE_WUSB_ASSOCIATE: - /* send assoc data */ - ar_name = "ASSOCIATE"; - ar_assoc = 1; - break; - }; - break; - }; - - dev_dbg(dev, "Association request #%02u: 0x%04x/%04x " - "(%zu bytes): %s\n", - assoc_request->AssociationDataIndex, ar_type, - ar_subtype, (size_t)ar_size, ar_name); - - itr += sizeof(*assoc_request); - } - - if (!ar_rhi) { - dev_err(dev, "Missing RETRIEVE_HOST_INFO association " - "request\n"); - return -EINVAL; - } - if (!ar_assoc) { - dev_err(dev, "Missing ASSOCIATE association request\n"); - return -EINVAL; - } - - return 0; -} - -static const struct wusb_cbaf_host_info cbaf_host_info_defaults = { - .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, - .AssociationTypeId = cpu_to_le16(AR_TYPE_WUSB), - .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId, - .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO), - .CHID_hdr = WUSB_AR_CHID, - .LangID_hdr = WUSB_AR_LangID, - .HostFriendlyName_hdr = WUSB_AR_HostFriendlyName, -}; - -/* Send WUSB host information (CHID and name) to a CBAF device */ -static int cbaf_send_host_info(struct cbaf *cbaf) -{ - struct wusb_cbaf_host_info *hi; - size_t name_len; - size_t hi_size; - - hi = cbaf->buffer; - memset(hi, 0, sizeof(*hi)); - *hi = cbaf_host_info_defaults; - hi->CHID = cbaf->chid; - hi->LangID = 0; /* FIXME: I guess... */ - strlcpy(hi->HostFriendlyName, cbaf->host_name, CBA_NAME_LEN); - name_len = strlen(cbaf->host_name); - hi->HostFriendlyName_hdr.len = cpu_to_le16(name_len); - hi_size = sizeof(*hi) + name_len; - - return usb_control_msg(cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0), - CBAF_REQ_SET_ASSOCIATION_RESPONSE, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0x0101, - cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - hi, hi_size, 1000 /* FIXME: arbitrary */); -} - -/* - * Get device's information (CDID) associated to CHID - * - * The device will return it's information (CDID, name, bandgroups) - * associated to the CHID we have set before, or 0 CDID and default - * name and bandgroup if no CHID set or unknown. - */ -static int cbaf_cdid_get(struct cbaf *cbaf) -{ - int result; - struct device *dev = &cbaf->usb_iface->dev; - struct wusb_cbaf_device_info *di; - size_t needed; - - di = cbaf->buffer; - result = usb_control_msg( - cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0), - CBAF_REQ_GET_ASSOCIATION_REQUEST, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Cannot request device information: %d\n", result); - return result; - } - - needed = result < sizeof(*di) ? sizeof(*di) : le32_to_cpu(di->Length); - if (result < needed) { - dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs " - "%zu bytes needed)\n", (size_t)result, needed); - return result; - } - - strlcpy(cbaf->device_name, di->DeviceFriendlyName, CBA_NAME_LEN); - cbaf->cdid = di->CDID; - cbaf->device_band_groups = le16_to_cpu(di->BandGroups); - - return 0; -} - -static ssize_t cbaf_wusb_chid_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - char pr_chid[WUSB_CKHDID_STRSIZE]; - - ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid); - return scnprintf(buf, PAGE_SIZE, "%s\n", pr_chid); -} - -static ssize_t cbaf_wusb_chid_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - ssize_t result; - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - result = sscanf(buf, - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx", - &cbaf->chid.data[0] , &cbaf->chid.data[1], - &cbaf->chid.data[2] , &cbaf->chid.data[3], - &cbaf->chid.data[4] , &cbaf->chid.data[5], - &cbaf->chid.data[6] , &cbaf->chid.data[7], - &cbaf->chid.data[8] , &cbaf->chid.data[9], - &cbaf->chid.data[10], &cbaf->chid.data[11], - &cbaf->chid.data[12], &cbaf->chid.data[13], - &cbaf->chid.data[14], &cbaf->chid.data[15]); - - if (result != 16) - return -EINVAL; - - result = cbaf_send_host_info(cbaf); - if (result < 0) - return result; - result = cbaf_cdid_get(cbaf); - if (result < 0) - return -result; - return size; -} -static DEVICE_ATTR(wusb_chid, 0600, cbaf_wusb_chid_show, cbaf_wusb_chid_store); - -static ssize_t cbaf_wusb_host_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->host_name); -} - -static ssize_t cbaf_wusb_host_name_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - ssize_t result; - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - result = sscanf(buf, "%63s", cbaf->host_name); - if (result != 1) - return -EINVAL; - - return size; -} -static DEVICE_ATTR(wusb_host_name, 0600, cbaf_wusb_host_name_show, - cbaf_wusb_host_name_store); - -static ssize_t cbaf_wusb_host_band_groups_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->host_band_groups); -} - -static ssize_t cbaf_wusb_host_band_groups_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - ssize_t result; - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - u16 band_groups = 0; - - result = sscanf(buf, "%04hx", &band_groups); - if (result != 1) - return -EINVAL; - - cbaf->host_band_groups = band_groups; - - return size; -} - -static DEVICE_ATTR(wusb_host_band_groups, 0600, - cbaf_wusb_host_band_groups_show, - cbaf_wusb_host_band_groups_store); - -static const struct wusb_cbaf_device_info cbaf_device_info_defaults = { - .Length_hdr = WUSB_AR_Length, - .CDID_hdr = WUSB_AR_CDID, - .BandGroups_hdr = WUSB_AR_BandGroups, - .LangID_hdr = WUSB_AR_LangID, - .DeviceFriendlyName_hdr = WUSB_AR_DeviceFriendlyName, -}; - -static ssize_t cbaf_wusb_cdid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - char pr_cdid[WUSB_CKHDID_STRSIZE]; - - ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid); - return scnprintf(buf, PAGE_SIZE, "%s\n", pr_cdid); -} - -static ssize_t cbaf_wusb_cdid_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - ssize_t result; - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - struct wusb_ckhdid cdid; - - result = sscanf(buf, - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx", - &cdid.data[0] , &cdid.data[1], - &cdid.data[2] , &cdid.data[3], - &cdid.data[4] , &cdid.data[5], - &cdid.data[6] , &cdid.data[7], - &cdid.data[8] , &cdid.data[9], - &cdid.data[10], &cdid.data[11], - &cdid.data[12], &cdid.data[13], - &cdid.data[14], &cdid.data[15]); - if (result != 16) - return -EINVAL; - - cbaf->cdid = cdid; - - return size; -} -static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, cbaf_wusb_cdid_store); - -static ssize_t cbaf_wusb_device_band_groups_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->device_band_groups); -} - -static DEVICE_ATTR(wusb_device_band_groups, 0600, - cbaf_wusb_device_band_groups_show, - NULL); - -static ssize_t cbaf_wusb_device_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->device_name); -} -static DEVICE_ATTR(wusb_device_name, 0600, cbaf_wusb_device_name_show, NULL); - -static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = { - .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, - .AssociationTypeId = cpu_to_le16(AR_TYPE_WUSB), - .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId, - .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE), - .Length_hdr = WUSB_AR_Length, - .Length = cpu_to_le32(sizeof(struct wusb_cbaf_cc_data)), - .ConnectionContext_hdr = WUSB_AR_ConnectionContext, - .BandGroups_hdr = WUSB_AR_BandGroups, -}; - -static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults = { - .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, - .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId, - .Length_hdr = WUSB_AR_Length, - .AssociationStatus_hdr = WUSB_AR_AssociationStatus, -}; - -/* - * Send a new CC to the device. - */ -static int cbaf_cc_upload(struct cbaf *cbaf) -{ - int result; - struct device *dev = &cbaf->usb_iface->dev; - struct wusb_cbaf_cc_data *ccd; - char pr_cdid[WUSB_CKHDID_STRSIZE]; - - ccd = cbaf->buffer; - *ccd = cbaf_cc_data_defaults; - ccd->CHID = cbaf->chid; - ccd->CDID = cbaf->cdid; - ccd->CK = cbaf->ck; - ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups); - - dev_dbg(dev, "Trying to upload CC:\n"); - ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID); - dev_dbg(dev, " CHID %s\n", pr_cdid); - ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID); - dev_dbg(dev, " CDID %s\n", pr_cdid); - dev_dbg(dev, " Bandgroups 0x%04x\n", cbaf->host_band_groups); - - result = usb_control_msg( - cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0), - CBAF_REQ_SET_ASSOCIATION_RESPONSE, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, - ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */); - - return result; -} - -static ssize_t cbaf_wusb_ck_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - ssize_t result; - struct usb_interface *iface = to_usb_interface(dev); - struct cbaf *cbaf = usb_get_intfdata(iface); - - result = sscanf(buf, - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx", - &cbaf->ck.data[0] , &cbaf->ck.data[1], - &cbaf->ck.data[2] , &cbaf->ck.data[3], - &cbaf->ck.data[4] , &cbaf->ck.data[5], - &cbaf->ck.data[6] , &cbaf->ck.data[7], - &cbaf->ck.data[8] , &cbaf->ck.data[9], - &cbaf->ck.data[10], &cbaf->ck.data[11], - &cbaf->ck.data[12], &cbaf->ck.data[13], - &cbaf->ck.data[14], &cbaf->ck.data[15]); - if (result != 16) - return -EINVAL; - - result = cbaf_cc_upload(cbaf); - if (result < 0) - return result; - - return size; -} -static DEVICE_ATTR(wusb_ck, 0600, NULL, cbaf_wusb_ck_store); - -static struct attribute *cbaf_dev_attrs[] = { - &dev_attr_wusb_host_name.attr, - &dev_attr_wusb_host_band_groups.attr, - &dev_attr_wusb_chid.attr, - &dev_attr_wusb_cdid.attr, - &dev_attr_wusb_device_name.attr, - &dev_attr_wusb_device_band_groups.attr, - &dev_attr_wusb_ck.attr, - NULL, -}; - -static struct attribute_group cbaf_dev_attr_group = { - .name = NULL, /* we want them in the same directory */ - .attrs = cbaf_dev_attrs, -}; - -static int cbaf_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - struct cbaf *cbaf; - struct device *dev = &iface->dev; - int result = -ENOMEM; - - cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL); - if (cbaf == NULL) - goto error_kzalloc; - cbaf->buffer = kmalloc(512, GFP_KERNEL); - if (cbaf->buffer == NULL) - goto error_kmalloc_buffer; - - cbaf->buffer_size = 512; - cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface)); - cbaf->usb_iface = usb_get_intf(iface); - result = cbaf_check(cbaf); - if (result < 0) { - dev_err(dev, "This device is not WUSB-CBAF compliant" - "and is not supported yet.\n"); - goto error_check; - } - - result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group); - if (result < 0) { - dev_err(dev, "Can't register sysfs attr group: %d\n", result); - goto error_create_group; - } - usb_set_intfdata(iface, cbaf); - return 0; - -error_create_group: -error_check: - kfree(cbaf->buffer); -error_kmalloc_buffer: - kfree(cbaf); -error_kzalloc: - return result; -} - -static void cbaf_disconnect(struct usb_interface *iface) -{ - struct cbaf *cbaf = usb_get_intfdata(iface); - struct device *dev = &iface->dev; - sysfs_remove_group(&dev->kobj, &cbaf_dev_attr_group); - usb_set_intfdata(iface, NULL); - usb_put_intf(iface); - kfree(cbaf->buffer); - /* paranoia: clean up crypto keys */ - memset(cbaf, 0, sizeof(*cbaf)); - kfree(cbaf); -} - -static struct usb_device_id cbaf_id_table[] = { - { USB_INTERFACE_INFO(0xef, 0x03, 0x01), }, - { }, -}; -MODULE_DEVICE_TABLE(usb, cbaf_id_table); - -static struct usb_driver cbaf_driver = { - .name = "wusb-cbaf", - .id_table = cbaf_id_table, - .probe = cbaf_probe, - .disconnect = cbaf_disconnect, -}; - -static int __init cbaf_driver_init(void) -{ - return usb_register(&cbaf_driver); -} -module_init(cbaf_driver_init); - -static void __exit cbaf_driver_exit(void) -{ - usb_deregister(&cbaf_driver); -} -module_exit(cbaf_driver_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Wireless USB Cable Based Association"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/wusbcore/crypto.c b/trunk/drivers/usb/wusbcore/crypto.c deleted file mode 100644 index c36c4389baae..000000000000 --- a/trunk/drivers/usb/wusbcore/crypto.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Ultra Wide Band - * AES-128 CCM Encryption - * - * Copyright (C) 2007 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * We don't do any encryption here; we use the Linux Kernel's AES-128 - * crypto modules to construct keys and payload blocks in a way - * defined by WUSB1.0[6]. Check the erratas, as typos are are patched - * there. - * - * Thanks a zillion to John Keys for his help and clarifications over - * the designed-by-a-committee text. - * - * So the idea is that there is this basic Pseudo-Random-Function - * defined in WUSB1.0[6.5] which is the core of everything. It works - * by tweaking some blocks, AES crypting them and then xoring - * something else with them (this seems to be called CBC(AES) -- can - * you tell I know jack about crypto?). So we just funnel it into the - * Linux Crypto API. - * - * We leave a crypto test module so we can verify that vectors match, - * every now and then. - * - * Block size: 16 bytes -- AES seems to do things in 'block sizes'. I - * am learning a lot... - * - * Conveniently, some data structures that need to be - * funneled through AES are...16 bytes in size! - */ - -#include -#include -#include -#include -#include -#include -#define D_LOCAL 0 -#include - - -/* - * Block of data, as understood by AES-CCM - * - * The code assumes this structure is nothing but a 16 byte array - * (packed in a struct to avoid common mess ups that I usually do with - * arrays and enforcing type checking). - */ -struct aes_ccm_block { - u8 data[16]; -} __attribute__((packed)); - -/* - * Counter-mode Blocks (WUSB1.0[6.4]) - * - * According to CCM (or so it seems), for the purpose of calculating - * the MIC, the message is broken in N counter-mode blocks, B0, B1, - * ... BN. - * - * B0 contains flags, the CCM nonce and l(m). - * - * B1 contains l(a), the MAC header, the encryption offset and padding. - * - * If EO is nonzero, additional blocks are built from payload bytes - * until EO is exahusted (FIXME: padding to 16 bytes, I guess). The - * padding is not xmitted. - */ - -/* WUSB1.0[T6.4] */ -struct aes_ccm_b0 { - u8 flags; /* 0x59, per CCM spec */ - struct aes_ccm_nonce ccm_nonce; - __be16 lm; -} __attribute__((packed)); - -/* WUSB1.0[T6.5] */ -struct aes_ccm_b1 { - __be16 la; - u8 mac_header[10]; - __le16 eo; - u8 security_reserved; /* This is always zero */ - u8 padding; /* 0 */ -} __attribute__((packed)); - -/* - * Encryption Blocks (WUSB1.0[6.4.4]) - * - * CCM uses Ax blocks to generate a keystream with which the MIC and - * the message's payload are encoded. A0 always encrypts/decrypts the - * MIC. Ax (x>0) are used for the sucesive payload blocks. - * - * The x is the counter, and is increased for each block. - */ -struct aes_ccm_a { - u8 flags; /* 0x01, per CCM spec */ - struct aes_ccm_nonce ccm_nonce; - __be16 counter; /* Value of x */ -} __attribute__((packed)); - -static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, - size_t size) -{ - u8 *bo = _bo; - const u8 *bi1 = _bi1, *bi2 = _bi2; - size_t itr; - for (itr = 0; itr < size; itr++) - bo[itr] = bi1[itr] ^ bi2[itr]; -} - -/* - * CC-MAC function WUSB1.0[6.5] - * - * Take a data string and produce the encrypted CBC Counter-mode MIC - * - * Note the names for most function arguments are made to (more or - * less) match those used in the pseudo-function definition given in - * WUSB1.0[6.5]. - * - * @tfm_cbc: CBC(AES) blkcipher handle (initialized) - * - * @tfm_aes: AES cipher handle (initialized) - * - * @mic: buffer for placing the computed MIC (Message Integrity - * Code). This is exactly 8 bytes, and we expect the buffer to - * be at least eight bytes in length. - * - * @key: 128 bit symmetric key - * - * @n: CCM nonce - * - * @a: ASCII string, 14 bytes long (I guess zero padded if needed; - * we use exactly 14 bytes). - * - * @b: data stream to be processed; cannot be a global or const local - * (will confuse the scatterlists) - * - * @blen: size of b... - * - * Still not very clear how this is done, but looks like this: we - * create block B0 (as WUSB1.0[6.5] says), then we AES-crypt it with - * @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we - * take the payload and divide it in blocks (16 bytes), xor them with - * the previous crypto result (16 bytes) and crypt it, repeat the next - * block with the output of the previous one, rinse wash (I guess this - * is what AES CBC mode means...but I truly have no idea). So we use - * the CBC(AES) blkcipher, that does precisely that. The IV (Initial - * Vector) is 16 bytes and is set to zero, so - * - * See rfc3610. Linux crypto has a CBC implementation, but the - * documentation is scarce, to say the least, and the example code is - * so intricated that is difficult to understand how things work. Most - * of this is guess work -- bite me. - * - * (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and - * using the 14 bytes of @a to fill up - * b1.{mac_header,e0,security_reserved,padding}. - * - * NOTE: The definiton of l(a) in WUSB1.0[6.5] vs the definition of - * l(m) is orthogonal, they bear no relationship, so it is not - * in conflict with the parameter's relation that - * WUSB1.0[6.4.2]) defines. - * - * NOTE: WUSB1.0[A.1]: Host Nonce is missing a nibble? (1e); fixed in - * first errata released on 2005/07. - * - * NOTE: we need to clean IV to zero at each invocation to make sure - * we start with a fresh empty Initial Vector, so that the CBC - * works ok. - * - * NOTE: blen is not aligned to a block size, we'll pad zeros, that's - * what sg[4] is for. Maybe there is a smarter way to do this. - */ -static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, - struct crypto_cipher *tfm_aes, void *mic, - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, const void *b, - size_t blen) -{ - int result = 0; - struct blkcipher_desc desc; - struct aes_ccm_b0 b0; - struct aes_ccm_b1 b1; - struct aes_ccm_a ax; - struct scatterlist sg[4], sg_dst; - void *iv, *dst_buf; - size_t ivsize, dst_size; - const u8 bzero[16] = { 0 }; - size_t zero_padding; - - d_fnstart(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, " - "n %p, a %p, b %p, blen %zu)\n", - tfm_cbc, tfm_aes, mic, n, a, b, blen); - /* - * These checks should be compile time optimized out - * ensure @a fills b1's mac_header and following fields - */ - WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la)); - WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block)); - WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block)); - WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block)); - - result = -ENOMEM; - zero_padding = sizeof(struct aes_ccm_block) - - blen % sizeof(struct aes_ccm_block); - zero_padding = blen % sizeof(struct aes_ccm_block); - if (zero_padding) - zero_padding = sizeof(struct aes_ccm_block) - zero_padding; - dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding; - dst_buf = kzalloc(dst_size, GFP_KERNEL); - if (dst_buf == NULL) { - printk(KERN_ERR "E: can't alloc destination buffer\n"); - goto error_dst_buf; - } - - iv = crypto_blkcipher_crt(tfm_cbc)->iv; - ivsize = crypto_blkcipher_ivsize(tfm_cbc); - memset(iv, 0, ivsize); - - /* Setup B0 */ - b0.flags = 0x59; /* Format B0 */ - b0.ccm_nonce = *n; - b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */ - - /* Setup B1 - * - * The WUSB spec is anything but clear! WUSB1.0[6.5] - * says that to initialize B1 from A with 'l(a) = blen + - * 14'--after clarification, it means to use A's contents - * for MAC Header, EO, sec reserved and padding. - */ - b1.la = cpu_to_be16(blen + 14); - memcpy(&b1.mac_header, a, sizeof(*a)); - - d_printf(4, NULL, "I: B0 (%zu bytes)\n", sizeof(b0)); - d_dump(4, NULL, &b0, sizeof(b0)); - d_printf(4, NULL, "I: B1 (%zu bytes)\n", sizeof(b1)); - d_dump(4, NULL, &b1, sizeof(b1)); - d_printf(4, NULL, "I: B (%zu bytes)\n", blen); - d_dump(4, NULL, b, blen); - d_printf(4, NULL, "I: B 0-padding (%zu bytes)\n", zero_padding); - d_printf(4, NULL, "D: IV before crypto (%zu)\n", ivsize); - d_dump(4, NULL, iv, ivsize); - - sg_init_table(sg, ARRAY_SIZE(sg)); - sg_set_buf(&sg[0], &b0, sizeof(b0)); - sg_set_buf(&sg[1], &b1, sizeof(b1)); - sg_set_buf(&sg[2], b, blen); - /* 0 if well behaved :) */ - sg_set_buf(&sg[3], bzero, zero_padding); - sg_init_one(&sg_dst, dst_buf, dst_size); - - desc.tfm = tfm_cbc; - desc.flags = 0; - result = crypto_blkcipher_encrypt(&desc, &sg_dst, sg, dst_size); - if (result < 0) { - printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", - result); - goto error_cbc_crypt; - } - d_printf(4, NULL, "D: MIC tag\n"); - d_dump(4, NULL, iv, ivsize); - - /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] - * The procedure is to AES crypt the A0 block and XOR the MIC - * Tag agains it; we only do the first 8 bytes and place it - * directly in the destination buffer. - * - * POS Crypto API: size is assumed to be AES's block size. - * Thanks for documenting it -- tip taken from airo.c - */ - ax.flags = 0x01; /* as per WUSB 1.0 spec */ - ax.ccm_nonce = *n; - ax.counter = 0; - crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); - bytewise_xor(mic, &ax, iv, 8); - d_printf(4, NULL, "D: CTR[MIC]\n"); - d_dump(4, NULL, &ax, 8); - d_printf(4, NULL, "D: CCM-MIC tag\n"); - d_dump(4, NULL, mic, 8); - result = 8; -error_cbc_crypt: - kfree(dst_buf); -error_dst_buf: - d_fnend(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, " - "n %p, a %p, b %p, blen %zu)\n", - tfm_cbc, tfm_aes, mic, n, a, b, blen); - return result; -} - -/* - * WUSB Pseudo Random Function (WUSB1.0[6.5]) - * - * @b: buffer to the source data; cannot be a global or const local - * (will confuse the scatterlists) - */ -ssize_t wusb_prf(void *out, size_t out_size, - const u8 key[16], const struct aes_ccm_nonce *_n, - const struct aes_ccm_label *a, - const void *b, size_t blen, size_t len) -{ - ssize_t result, bytes = 0, bitr; - struct aes_ccm_nonce n = *_n; - struct crypto_blkcipher *tfm_cbc; - struct crypto_cipher *tfm_aes; - u64 sfn = 0; - __le64 sfn_le; - - d_fnstart(3, NULL, "(out %p, out_size %zu, key %p, _n %p, " - "a %p, b %p, blen %zu, len %zu)\n", out, out_size, - key, _n, a, b, blen, len); - - tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm_cbc)) { - result = PTR_ERR(tfm_cbc); - printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result); - goto error_alloc_cbc; - } - result = crypto_blkcipher_setkey(tfm_cbc, key, 16); - if (result < 0) { - printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result); - goto error_setkey_cbc; - } - - tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm_aes)) { - result = PTR_ERR(tfm_aes); - printk(KERN_ERR "E: can't load AES: %d\n", (int)result); - goto error_alloc_aes; - } - result = crypto_cipher_setkey(tfm_aes, key, 16); - if (result < 0) { - printk(KERN_ERR "E: can't set AES key: %d\n", (int)result); - goto error_setkey_aes; - } - - for (bitr = 0; bitr < (len + 63) / 64; bitr++) { - sfn_le = cpu_to_le64(sfn++); - memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */ - result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes, - &n, a, b, blen); - if (result < 0) - goto error_ccm_mac; - bytes += result; - } - result = bytes; -error_ccm_mac: -error_setkey_aes: - crypto_free_cipher(tfm_aes); -error_alloc_aes: -error_setkey_cbc: - crypto_free_blkcipher(tfm_cbc); -error_alloc_cbc: - d_fnend(3, NULL, "(out %p, out_size %zu, key %p, _n %p, " - "a %p, b %p, blen %zu, len %zu) = %d\n", out, out_size, - key, _n, a, b, blen, len, (int)bytes); - return result; -} - -/* WUSB1.0[A.2] test vectors */ -static const u8 stv_hsmic_key[16] = { - 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d, - 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f -}; - -static const struct aes_ccm_nonce stv_hsmic_n = { - .sfn = { 0 }, - .tkid = { 0x76, 0x98, 0x01, }, - .dest_addr = { .data = { 0xbe, 0x00 } }, - .src_addr = { .data = { 0x76, 0x98 } }, -}; - -/* - * Out-of-band MIC Generation verification code - * - */ -static int wusb_oob_mic_verify(void) -{ - int result; - u8 mic[8]; - /* WUSB1.0[A.2] test vectors - * - * Need to keep it in the local stack as GCC 4.1.3something - * messes up and generates noise. - */ - struct usb_handshake stv_hsmic_hs = { - .bMessageNumber = 2, - .bStatus = 00, - .tTKID = { 0x76, 0x98, 0x01 }, - .bReserved = 00, - .CDID = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x3e, 0x3f }, - .nonce = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f }, - .MIC = { 0x75, 0x6a, 0x97, 0x51, 0x0c, 0x8c, - 0x14, 0x7b } , - }; - size_t hs_size; - - result = wusb_oob_mic(mic, stv_hsmic_key, &stv_hsmic_n, &stv_hsmic_hs); - if (result < 0) - printk(KERN_ERR "E: WUSB OOB MIC test: failed: %d\n", result); - else if (memcmp(stv_hsmic_hs.MIC, mic, sizeof(mic))) { - printk(KERN_ERR "E: OOB MIC test: " - "mismatch between MIC result and WUSB1.0[A2]\n"); - hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC); - printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size); - dump_bytes(NULL, &stv_hsmic_hs, hs_size); - printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n", - sizeof(stv_hsmic_n)); - dump_bytes(NULL, &stv_hsmic_n, sizeof(stv_hsmic_n)); - printk(KERN_ERR "E: MIC out:\n"); - dump_bytes(NULL, mic, sizeof(mic)); - printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n"); - dump_bytes(NULL, stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC)); - result = -EINVAL; - } else - result = 0; - return result; -} - -/* - * Test vectors for Key derivation - * - * These come from WUSB1.0[6.5.1], the vectors in WUSB1.0[A.1] - * (errata corrected in 2005/07). - */ -static const u8 stv_key_a1[16] __attribute__ ((__aligned__(4))) = { - 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, - 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f -}; - -static const struct aes_ccm_nonce stv_keydvt_n_a1 = { - .sfn = { 0 }, - .tkid = { 0x76, 0x98, 0x01, }, - .dest_addr = { .data = { 0xbe, 0x00 } }, - .src_addr = { .data = { 0x76, 0x98 } }, -}; - -static const struct wusb_keydvt_out stv_keydvt_out_a1 = { - .kck = { - 0x4b, 0x79, 0xa3, 0xcf, 0xe5, 0x53, 0x23, 0x9d, - 0xd7, 0xc1, 0x6d, 0x1c, 0x2d, 0xab, 0x6d, 0x3f - }, - .ptk = { - 0xc8, 0x70, 0x62, 0x82, 0xb6, 0x7c, 0xe9, 0x06, - 0x7b, 0xc5, 0x25, 0x69, 0xf2, 0x36, 0x61, 0x2d - } -}; - -/* - * Performa a test to make sure we match the vectors defined in - * WUSB1.0[A.1](Errata2006/12) - */ -static int wusb_key_derive_verify(void) -{ - int result = 0; - struct wusb_keydvt_out keydvt_out; - /* These come from WUSB1.0[A.1] + 2006/12 errata - * NOTE: can't make this const or global -- somehow it seems - * the scatterlists for crypto get confused and we get - * bad data. There is no doc on this... */ - struct wusb_keydvt_in stv_keydvt_in_a1 = { - .hnonce = { - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }, - .dnonce = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f - } - }; - - result = wusb_key_derive(&keydvt_out, stv_key_a1, &stv_keydvt_n_a1, - &stv_keydvt_in_a1); - if (result < 0) - printk(KERN_ERR "E: WUSB key derivation test: " - "derivation failed: %d\n", result); - if (memcmp(&stv_keydvt_out_a1, &keydvt_out, sizeof(keydvt_out))) { - printk(KERN_ERR "E: WUSB key derivation test: " - "mismatch between key derivation result " - "and WUSB1.0[A1] Errata 2006/12\n"); - printk(KERN_ERR "E: keydvt in: key (%zu bytes)\n", - sizeof(stv_key_a1)); - dump_bytes(NULL, stv_key_a1, sizeof(stv_key_a1)); - printk(KERN_ERR "E: keydvt in: nonce (%zu bytes)\n", - sizeof(stv_keydvt_n_a1)); - dump_bytes(NULL, &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1)); - printk(KERN_ERR "E: keydvt in: hnonce & dnonce (%zu bytes)\n", - sizeof(stv_keydvt_in_a1)); - dump_bytes(NULL, &stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1)); - printk(KERN_ERR "E: keydvt out: KCK\n"); - dump_bytes(NULL, &keydvt_out.kck, sizeof(keydvt_out.kck)); - printk(KERN_ERR "E: keydvt out: PTK\n"); - dump_bytes(NULL, &keydvt_out.ptk, sizeof(keydvt_out.ptk)); - result = -EINVAL; - } else - result = 0; - return result; -} - -/* - * Initialize crypto system - * - * FIXME: we do nothing now, other than verifying. Later on we'll - * cache the encryption stuff, so that's why we have a separate init. - */ -int wusb_crypto_init(void) -{ - int result; - - result = wusb_key_derive_verify(); - if (result < 0) - return result; - return wusb_oob_mic_verify(); -} - -void wusb_crypto_exit(void) -{ - /* FIXME: free cached crypto transforms */ -} diff --git a/trunk/drivers/usb/wusbcore/dev-sysfs.c b/trunk/drivers/usb/wusbcore/dev-sysfs.c deleted file mode 100644 index 7897a19652e5..000000000000 --- a/trunk/drivers/usb/wusbcore/dev-sysfs.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * WUSB devices - * sysfs bindings - * - * Copyright (C) 2007 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Get them out of the way... - */ - -#include -#include -#include -#include "wusbhc.h" - -#undef D_LOCAL -#define D_LOCAL 4 -#include - -static ssize_t wusb_disconnect_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct usb_device *usb_dev; - struct wusbhc *wusbhc; - unsigned command; - u8 port_idx; - - if (sscanf(buf, "%u", &command) != 1) - return -EINVAL; - if (command == 0) - return size; - usb_dev = to_usb_device(dev); - wusbhc = wusbhc_get_by_usb_dev(usb_dev); - if (wusbhc == NULL) - return -ENODEV; - - mutex_lock(&wusbhc->mutex); - port_idx = wusb_port_no_to_idx(usb_dev->portnum); - __wusbhc_dev_disable(wusbhc, port_idx); - mutex_unlock(&wusbhc->mutex); - wusbhc_put(wusbhc); - return size; -} -static DEVICE_ATTR(wusb_disconnect, 0200, NULL, wusb_disconnect_store); - -static ssize_t wusb_cdid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - ssize_t result; - struct wusb_dev *wusb_dev; - - wusb_dev = wusb_dev_get_by_usb_dev(to_usb_device(dev)); - if (wusb_dev == NULL) - return -ENODEV; - result = ckhdid_printf(buf, PAGE_SIZE, &wusb_dev->cdid); - strcat(buf, "\n"); - wusb_dev_put(wusb_dev); - return result + 1; -} -static DEVICE_ATTR(wusb_cdid, 0444, wusb_cdid_show, NULL); - -static ssize_t wusb_ck_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - int result; - struct usb_device *usb_dev; - struct wusbhc *wusbhc; - struct wusb_ckhdid ck; - - result = sscanf(buf, - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx\n", - &ck.data[0] , &ck.data[1], - &ck.data[2] , &ck.data[3], - &ck.data[4] , &ck.data[5], - &ck.data[6] , &ck.data[7], - &ck.data[8] , &ck.data[9], - &ck.data[10], &ck.data[11], - &ck.data[12], &ck.data[13], - &ck.data[14], &ck.data[15]); - if (result != 16) - return -EINVAL; - - usb_dev = to_usb_device(dev); - wusbhc = wusbhc_get_by_usb_dev(usb_dev); - if (wusbhc == NULL) - return -ENODEV; - result = wusb_dev_4way_handshake(wusbhc, usb_dev->wusb_dev, &ck); - memset(&ck, 0, sizeof(ck)); - wusbhc_put(wusbhc); - return result < 0 ? result : size; -} -static DEVICE_ATTR(wusb_ck, 0200, NULL, wusb_ck_store); - -static struct attribute *wusb_dev_attrs[] = { - &dev_attr_wusb_disconnect.attr, - &dev_attr_wusb_cdid.attr, - &dev_attr_wusb_ck.attr, - NULL, -}; - -static struct attribute_group wusb_dev_attr_group = { - .name = NULL, /* we want them in the same directory */ - .attrs = wusb_dev_attrs, -}; - -int wusb_dev_sysfs_add(struct wusbhc *wusbhc, struct usb_device *usb_dev, - struct wusb_dev *wusb_dev) -{ - int result = sysfs_create_group(&usb_dev->dev.kobj, - &wusb_dev_attr_group); - struct device *dev = &usb_dev->dev; - if (result < 0) - dev_err(dev, "Cannot register WUSB-dev attributes: %d\n", - result); - return result; -} - -void wusb_dev_sysfs_rm(struct wusb_dev *wusb_dev) -{ - struct usb_device *usb_dev = wusb_dev->usb_dev; - if (usb_dev) - sysfs_remove_group(&usb_dev->dev.kobj, &wusb_dev_attr_group); -} diff --git a/trunk/drivers/usb/wusbcore/devconnect.c b/trunk/drivers/usb/wusbcore/devconnect.c deleted file mode 100644 index f45d777bef34..000000000000 --- a/trunk/drivers/usb/wusbcore/devconnect.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * WUSB Wire Adapter: Control/Data Streaming Interface (WUSB[8]) - * Device Connect handling - * - * Copyright (C) 2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * FIXME: this file needs to be broken up, it's grown too big - * - * - * WUSB1.0[7.1, 7.5.1, ] - * - * WUSB device connection is kind of messy. Some background: - * - * When a device wants to connect it scans the UWB radio channels - * looking for a WUSB Channel; a WUSB channel is defined by MMCs - * (Micro Managed Commands or something like that) [see - * Design-overview for more on this] . - * - * So, device scans the radio, finds MMCs and thus a host and checks - * when the next DNTS is. It sends a Device Notification Connect - * (DN_Connect); the host picks it up (through nep.c and notif.c, ends - * up in wusb_devconnect_ack(), which creates a wusb_dev structure in - * wusbhc->port[port_number].wusb_dev), assigns an unauth address - * to the device (this means from 0x80 to 0xfe) and sends, in the MMC - * a Connect Ack Information Element (ConnAck IE). - * - * So now the device now has a WUSB address. From now on, we use - * that to talk to it in the RPipes. - * - * ASSUMPTIONS: - * - * - We use the the as device address the port number where it is - * connected (port 0 doesn't exist). For unauth, it is 128 + that. - * - * ROADMAP: - * - * This file contains the logic for doing that--entry points: - * - * wusb_devconnect_ack() Ack a device until _acked() called. - * Called by notif.c:wusb_handle_dn_connect() - * when a DN_Connect is received. - * - * wusbhc_devconnect_auth() Called by rh.c:wusbhc_rh_port_reset() when - * doing the device connect sequence. - * - * wusb_devconnect_acked() Ack done, release resources. - * - * wusb_handle_dn_alive() Called by notif.c:wusb_handle_dn() - * for processing a DN_Alive pong from a device. - * - * wusb_handle_dn_disconnect()Called by notif.c:wusb_handle_dn() to - * process a disconenct request from a - * device. - * - * wusb_dev_reset() Called by rh.c:wusbhc_rh_port_reset() when - * resetting a device. - * - * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when - * disabling a port. - * - * wusb_devconnect_create() Called when creating the host by - * lc.c:wusbhc_create(). - * - * wusb_devconnect_destroy() Cleanup called removing the host. Called - * by lc.c:wusbhc_destroy(). - * - * Each Wireless USB host maintains a list of DN_Connect requests - * (actually we maintain a list of pending Connect Acks, the - * wusbhc->ca_list). - * - * LIFE CYCLE OF port->wusb_dev - * - * Before the @wusbhc structure put()s the reference it owns for - * port->wusb_dev [and clean the wusb_dev pointer], it needs to - * lock @wusbhc->mutex. - */ - -#include -#include -#include -#include "wusbhc.h" - -#undef D_LOCAL -#define D_LOCAL 1 -#include - -static void wusbhc_devconnect_acked_work(struct work_struct *work); - -static void wusb_dev_free(struct wusb_dev *wusb_dev) -{ - if (wusb_dev) { - kfree(wusb_dev->set_gtk_req); - usb_free_urb(wusb_dev->set_gtk_urb); - kfree(wusb_dev); - } -} - -static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) -{ - struct wusb_dev *wusb_dev; - struct urb *urb; - struct usb_ctrlrequest *req; - - wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL); - if (wusb_dev == NULL) - goto err; - - wusb_dev->wusbhc = wusbhc; - - INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work); - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) - goto err; - - req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (req == NULL) - goto err; - - req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req->bRequest = USB_REQ_SET_DESCRIPTOR; - req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index); - req->wIndex = 0; - req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength); - - wusb_dev->set_gtk_urb = urb; - wusb_dev->set_gtk_req = req; - - return wusb_dev; -err: - wusb_dev_free(wusb_dev); - return NULL; -} - - -/* - * Using the Connect-Ack list, fill out the @wusbhc Connect-Ack WUSB IE - * properly so that it can be added to the MMC. - * - * We just get the @wusbhc->ca_list and fill out the first four ones or - * less (per-spec WUSB1.0[7.5, before T7-38). If the ConnectAck WUSB - * IE is not allocated, we alloc it. - * - * @wusbhc->mutex must be taken - */ -static void wusbhc_fill_cack_ie(struct wusbhc *wusbhc) -{ - unsigned cnt; - struct wusb_dev *dev_itr; - struct wuie_connect_ack *cack_ie; - - cack_ie = &wusbhc->cack_ie; - cnt = 0; - list_for_each_entry(dev_itr, &wusbhc->cack_list, cack_node) { - cack_ie->blk[cnt].CDID = dev_itr->cdid; - cack_ie->blk[cnt].bDeviceAddress = dev_itr->addr; - if (++cnt >= WUIE_ELT_MAX) - break; - } - cack_ie->hdr.bLength = sizeof(cack_ie->hdr) - + cnt * sizeof(cack_ie->blk[0]); -} - -/* - * Register a new device that wants to connect - * - * A new device wants to connect, so we add it to the Connect-Ack - * list. We give it an address in the unauthorized range (bit 8 set); - * user space will have to drive authorization further on. - * - * @dev_addr: address to use for the device (which is also the port - * number). - * - * @wusbhc->mutex must be taken - */ -static struct wusb_dev *wusbhc_cack_add(struct wusbhc *wusbhc, - struct wusb_dn_connect *dnc, - const char *pr_cdid, u8 port_idx) -{ - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; - int new_connection = wusb_dn_connect_new_connection(dnc); - u8 dev_addr; - int result; - - /* Is it registered already? */ - list_for_each_entry(wusb_dev, &wusbhc->cack_list, cack_node) - if (!memcmp(&wusb_dev->cdid, &dnc->CDID, - sizeof(wusb_dev->cdid))) - return wusb_dev; - /* We don't have it, create an entry, register it */ - wusb_dev = wusb_dev_alloc(wusbhc); - if (wusb_dev == NULL) - return NULL; - wusb_dev_init(wusb_dev); - wusb_dev->cdid = dnc->CDID; - wusb_dev->port_idx = port_idx; - - /* - * Devices are always available within the cluster reservation - * and since the hardware will take the intersection of the - * per-device availability and the cluster reservation, the - * per-device availability can simply be set to always - * available. - */ - bitmap_fill(wusb_dev->availability.bm, UWB_NUM_MAS); - - /* FIXME: handle reconnects instead of assuming connects are - always new. */ - if (1 && new_connection == 0) - new_connection = 1; - if (new_connection) { - dev_addr = (port_idx + 2) | WUSB_DEV_ADDR_UNAUTH; - - dev_info(dev, "Connecting new WUSB device to address %u, " - "port %u\n", dev_addr, port_idx); - - result = wusb_set_dev_addr(wusbhc, wusb_dev, dev_addr); - if (result < 0) - return NULL; - } - wusb_dev->entry_ts = jiffies; - list_add_tail(&wusb_dev->cack_node, &wusbhc->cack_list); - wusbhc->cack_count++; - wusbhc_fill_cack_ie(wusbhc); - return wusb_dev; -} - -/* - * Remove a Connect-Ack context entry from the HCs view - * - * @wusbhc->mutex must be taken - */ -static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct device *dev = wusbhc->dev; - d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev); - list_del_init(&wusb_dev->cack_node); - wusbhc->cack_count--; - wusbhc_fill_cack_ie(wusbhc); - d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev); -} - -/* - * @wusbhc->mutex must be taken */ -static -void wusbhc_devconnect_acked(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct device *dev = wusbhc->dev; - d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev); - wusbhc_cack_rm(wusbhc, wusb_dev); - if (wusbhc->cack_count) - wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->cack_ie.hdr); - else - wusbhc_mmcie_rm(wusbhc, &wusbhc->cack_ie.hdr); - d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev); -} - -static void wusbhc_devconnect_acked_work(struct work_struct *work) -{ - struct wusb_dev *wusb_dev = container_of(work, struct wusb_dev, - devconnect_acked_work); - struct wusbhc *wusbhc = wusb_dev->wusbhc; - - mutex_lock(&wusbhc->mutex); - wusbhc_devconnect_acked(wusbhc, wusb_dev); - mutex_unlock(&wusbhc->mutex); -} - -/* - * Ack a device for connection - * - * FIXME: docs - * - * @pr_cdid: Printable CDID...hex Use @dnc->cdid for the real deal. - * - * So we get the connect ack IE (may have been allocated already), - * find an empty connect block, an empty virtual port, create an - * address with it (see below), make it an unauth addr [bit 7 set] and - * set the MMC. - * - * Addresses: because WUSB hosts have no downstream hubs, we can do a - * 1:1 mapping between 'port number' and device - * address. This simplifies many things, as during this - * initial connect phase the USB stack has no knoledge of - * the device and hasn't assigned an address yet--we know - * USB's choose_address() will use the same euristics we - * use here, so we can assume which address will be assigned. - * - * USB stack always assigns address 1 to the root hub, so - * to the port number we add 2 (thus virtual port #0 is - * addr #2). - * - * @wusbhc shall be referenced - */ -static -void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc, - const char *pr_cdid) -{ - int result; - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; - struct wusb_port *port; - unsigned idx, devnum; - - d_fnstart(3, dev, "(%p, %p, %s)\n", wusbhc, dnc, pr_cdid); - mutex_lock(&wusbhc->mutex); - - /* Check we are not handling it already */ - for (idx = 0; idx < wusbhc->ports_max; idx++) { - port = wusb_port_by_idx(wusbhc, idx); - if (port->wusb_dev - && memcmp(&dnc->CDID, &port->wusb_dev->cdid, sizeof(dnc->CDID)) == 0) - goto error_unlock; - } - /* Look up those fake ports we have for a free one */ - for (idx = 0; idx < wusbhc->ports_max; idx++) { - port = wusb_port_by_idx(wusbhc, idx); - if ((port->status & USB_PORT_STAT_POWER) - && !(port->status & USB_PORT_STAT_CONNECTION)) - break; - } - if (idx >= wusbhc->ports_max) { - dev_err(dev, "Host controller can't connect more devices " - "(%u already connected); device %s rejected\n", - wusbhc->ports_max, pr_cdid); - /* NOTE: we could send a WUIE_Disconnect here, but we haven't - * event acked, so the device will eventually timeout the - * connection, right? */ - goto error_unlock; - } - - devnum = idx + 2; - - /* Make sure we are using no crypto on that "virtual port" */ - wusbhc->set_ptk(wusbhc, idx, 0, NULL, 0); - - /* Grab a filled in Connect-Ack context, fill out the - * Connect-Ack Wireless USB IE, set the MMC */ - wusb_dev = wusbhc_cack_add(wusbhc, dnc, pr_cdid, idx); - if (wusb_dev == NULL) - goto error_unlock; - result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->cack_ie.hdr); - if (result < 0) - goto error_unlock; - /* Give the device at least 2ms (WUSB1.0[7.5.1p3]), let's do - * three for a good measure */ - msleep(3); - port->wusb_dev = wusb_dev; - port->status |= USB_PORT_STAT_CONNECTION; - port->change |= USB_PORT_STAT_C_CONNECTION; - port->reset_count = 0; - /* Now the port status changed to connected; khubd will - * pick the change up and try to reset the port to bring it to - * the enabled state--so this process returns up to the stack - * and it calls back into wusbhc_rh_port_reset() who will call - * devconnect_auth(). - */ -error_unlock: - mutex_unlock(&wusbhc->mutex); - d_fnend(3, dev, "(%p, %p, %s) = void\n", wusbhc, dnc, pr_cdid); - return; - -} - -/* - * Disconnect a Wireless USB device from its fake port - * - * Marks the port as disconnected so that khubd can pick up the change - * and drops our knowledge about the device. - * - * Assumes there is a device connected - * - * @port_index: zero based port number - * - * NOTE: @wusbhc->mutex is locked - * - * WARNING: From here it is not very safe to access anything hanging off - * wusb_dev - */ -static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, - struct wusb_port *port) -{ - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev = port->wusb_dev; - - d_fnstart(3, dev, "(wusbhc %p, port %p)\n", wusbhc, port); - port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE - | USB_PORT_STAT_SUSPEND | USB_PORT_STAT_RESET - | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); - port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; - if (wusb_dev) { - if (!list_empty(&wusb_dev->cack_node)) - list_del_init(&wusb_dev->cack_node); - /* For the one in cack_add() */ - wusb_dev_put(wusb_dev); - } - port->wusb_dev = NULL; - /* don't reset the reset_count to zero or wusbhc_rh_port_reset will get - * confused! We only reset to zero when we connect a new device. - */ - - /* After a device disconnects, change the GTK (see [WUSB] - * section 6.2.11.2). */ - wusbhc_gtk_rekey(wusbhc); - - d_fnend(3, dev, "(wusbhc %p, port %p) = void\n", wusbhc, port); - /* The Wireless USB part has forgotten about the device already; now - * khubd's timer will pick up the disconnection and remove the USB - * device from the system - */ -} - -/* - * Authenticate a device into the WUSB Cluster - * - * Called from the Root Hub code (rh.c:wusbhc_rh_port_reset()) when - * asking for a reset on a port that is not enabled (ie: first connect - * on the port). - * - * Performs the 4way handshake to allow the device to comunicate w/ the - * WUSB Cluster securely; once done, issue a request to the device for - * it to change to address 0. - * - * This mimics the reset step of Wired USB that once resetting a - * device, leaves the port in enabled state and the dev with the - * default address (0). - * - * WUSB1.0[7.1.2] - * - * @port_idx: port where the change happened--This is the index into - * the wusbhc port array, not the USB port number. - */ -int wusbhc_devconnect_auth(struct wusbhc *wusbhc, u8 port_idx) -{ - struct device *dev = wusbhc->dev; - struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); - - d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); - port->status &= ~USB_PORT_STAT_RESET; - port->status |= USB_PORT_STAT_ENABLE; - port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; - d_fnend(3, dev, "(%p, %u) = 0\n", wusbhc, port_idx); - return 0; -} - -/* - * Refresh the list of keep alives to emit in the MMC - * - * Some devices don't respond to keep alives unless they've been - * authenticated, so skip unauthenticated devices. - * - * We only publish the first four devices that have a coming timeout - * condition. Then when we are done processing those, we go for the - * next ones. We ignore the ones that have timed out already (they'll - * be purged). - * - * This might cause the first devices to timeout the last devices in - * the port array...FIXME: come up with a better algorithm? - * - * Note we can't do much about MMC's ops errors; we hope next refresh - * will kind of handle it. - * - * NOTE: @wusbhc->mutex is locked - */ -static void __wusbhc_keep_alive(struct wusbhc *wusbhc) -{ - struct device *dev = wusbhc->dev; - unsigned cnt; - struct wusb_dev *wusb_dev; - struct wusb_port *wusb_port; - struct wuie_keep_alive *ie = &wusbhc->keep_alive_ie; - unsigned keep_alives, old_keep_alives; - - old_keep_alives = ie->hdr.bLength - sizeof(ie->hdr); - keep_alives = 0; - for (cnt = 0; - keep_alives <= WUIE_ELT_MAX && cnt < wusbhc->ports_max; - cnt++) { - unsigned tt = msecs_to_jiffies(wusbhc->trust_timeout); - - wusb_port = wusb_port_by_idx(wusbhc, cnt); - wusb_dev = wusb_port->wusb_dev; - - if (wusb_dev == NULL) - continue; - if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated) - continue; - - if (time_after(jiffies, wusb_dev->entry_ts + tt)) { - dev_err(dev, "KEEPALIVE: device %u timed out\n", - wusb_dev->addr); - __wusbhc_dev_disconnect(wusbhc, wusb_port); - } else if (time_after(jiffies, wusb_dev->entry_ts + tt/2)) { - /* Approaching timeout cut out, need to refresh */ - ie->bDeviceAddress[keep_alives++] = wusb_dev->addr; - } - } - if (keep_alives & 0x1) /* pad to even number ([WUSB] section 7.5.9) */ - ie->bDeviceAddress[keep_alives++] = 0x7f; - ie->hdr.bLength = sizeof(ie->hdr) + - keep_alives*sizeof(ie->bDeviceAddress[0]); - if (keep_alives > 0) - wusbhc_mmcie_set(wusbhc, 10, 5, &ie->hdr); - else if (old_keep_alives != 0) - wusbhc_mmcie_rm(wusbhc, &ie->hdr); -} - -/* - * Do a run through all devices checking for timeouts - */ -static void wusbhc_keep_alive_run(struct work_struct *ws) -{ - struct delayed_work *dw = - container_of(ws, struct delayed_work, work); - struct wusbhc *wusbhc = - container_of(dw, struct wusbhc, keep_alive_timer); - - d_fnstart(5, wusbhc->dev, "(wusbhc %p)\n", wusbhc); - if (wusbhc->active) { - mutex_lock(&wusbhc->mutex); - __wusbhc_keep_alive(wusbhc); - mutex_unlock(&wusbhc->mutex); - queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, - (wusbhc->trust_timeout * CONFIG_HZ)/1000/2); - } - d_fnend(5, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); - return; -} - -/* - * Find the wusb_dev from its device address. - * - * The device can be found directly from the address (see - * wusb_cack_add() for where the device address is set to port_idx - * +2), except when the address is zero. - */ -static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr) -{ - int p; - - if (addr == 0xff) /* unconnected */ - return NULL; - - if (addr > 0) { - int port = (addr & ~0x80) - 2; - if (port < 0 || port >= wusbhc->ports_max) - return NULL; - return wusb_port_by_idx(wusbhc, port)->wusb_dev; - } - - /* Look for the device with address 0. */ - for (p = 0; p < wusbhc->ports_max; p++) { - struct wusb_dev *wusb_dev = wusb_port_by_idx(wusbhc, p)->wusb_dev; - if (wusb_dev && wusb_dev->addr == addr) - return wusb_dev; - } - return NULL; -} - -/* - * Handle a DN_Alive notification (WUSB1.0[7.6.1]) - * - * This just updates the device activity timestamp and then refreshes - * the keep alive IE. - * - * @wusbhc shall be referenced and unlocked - */ -static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct device *dev = wusbhc->dev; - - d_printf(2, dev, "DN ALIVE: device 0x%02x pong\n", wusb_dev->addr); - - mutex_lock(&wusbhc->mutex); - wusb_dev->entry_ts = jiffies; - __wusbhc_keep_alive(wusbhc); - mutex_unlock(&wusbhc->mutex); -} - -/* - * Handle a DN_Connect notification (WUSB1.0[7.6.1]) - * - * @wusbhc - * @pkt_hdr - * @size: Size of the buffer where the notification resides; if the - * notification data suggests there should be more data than - * available, an error will be signaled and the whole buffer - * consumed. - * - * @wusbhc->mutex shall be held - */ -static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc, - struct wusb_dn_hdr *dn_hdr, - size_t size) -{ - struct device *dev = wusbhc->dev; - struct wusb_dn_connect *dnc; - char pr_cdid[WUSB_CKHDID_STRSIZE]; - static const char *beacon_behaviour[] = { - "reserved", - "self-beacon", - "directed-beacon", - "no-beacon" - }; - - d_fnstart(3, dev, "(%p, %p, %zu)\n", wusbhc, dn_hdr, size); - if (size < sizeof(*dnc)) { - dev_err(dev, "DN CONNECT: short notification (%zu < %zu)\n", - size, sizeof(*dnc)); - goto out; - } - - dnc = container_of(dn_hdr, struct wusb_dn_connect, hdr); - ckhdid_printf(pr_cdid, sizeof(pr_cdid), &dnc->CDID); - dev_info(dev, "DN CONNECT: device %s @ %x (%s) wants to %s\n", - pr_cdid, - wusb_dn_connect_prev_dev_addr(dnc), - beacon_behaviour[wusb_dn_connect_beacon_behavior(dnc)], - wusb_dn_connect_new_connection(dnc) ? "connect" : "reconnect"); - /* ACK the connect */ - wusbhc_devconnect_ack(wusbhc, dnc, pr_cdid); -out: - d_fnend(3, dev, "(%p, %p, %zu) = void\n", - wusbhc, dn_hdr, size); - return; -} - -/* - * Handle a DN_Disconnect notification (WUSB1.0[7.6.1]) - * - * Device is going down -- do the disconnect. - * - * @wusbhc shall be referenced and unlocked - */ -static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct device *dev = wusbhc->dev; - - dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr); - - mutex_lock(&wusbhc->mutex); - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx)); - mutex_unlock(&wusbhc->mutex); -} - -/* - * Reset a WUSB device on a HWA - * - * @wusbhc - * @port_idx Index of the port where the device is - * - * In Wireless USB, a reset is more or less equivalent to a full - * disconnect; so we just do a full disconnect and send the device a - * Device Reset IE (WUSB1.0[7.5.11]) giving it a few millisecs (6 MMCs). - * - * @wusbhc should be refcounted and unlocked - */ -int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port_idx) -{ - int result; - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; - struct wuie_reset *ie; - - d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); - mutex_lock(&wusbhc->mutex); - result = 0; - wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; - if (wusb_dev == NULL) { - /* reset no device? ignore */ - dev_dbg(dev, "RESET: no device at port %u, ignoring\n", - port_idx); - goto error_unlock; - } - result = -ENOMEM; - ie = kzalloc(sizeof(*ie), GFP_KERNEL); - if (ie == NULL) - goto error_unlock; - ie->hdr.bLength = sizeof(ie->hdr) + sizeof(ie->CDID); - ie->hdr.bIEIdentifier = WUIE_ID_RESET_DEVICE; - ie->CDID = wusb_dev->cdid; - result = wusbhc_mmcie_set(wusbhc, 0xff, 6, &ie->hdr); - if (result < 0) { - dev_err(dev, "RESET: cant's set MMC: %d\n", result); - goto error_kfree; - } - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); - - /* 120ms, hopefully 6 MMCs (FIXME) */ - msleep(120); - wusbhc_mmcie_rm(wusbhc, &ie->hdr); -error_kfree: - kfree(ie); -error_unlock: - mutex_unlock(&wusbhc->mutex); - d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result); - return result; -} - -/* - * Handle a Device Notification coming a host - * - * The Device Notification comes from a host (HWA, DWA or WHCI) - * wrapped in a set of headers. Somebody else has peeled off those - * headers for us and we just get one Device Notifications. - * - * Invalid DNs (e.g., too short) are discarded. - * - * @wusbhc shall be referenced - * - * FIXMES: - * - implement priorities as in WUSB1.0[Table 7-55]? - */ -void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr, - struct wusb_dn_hdr *dn_hdr, size_t size) -{ - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; - - d_fnstart(3, dev, "(%p, %p)\n", wusbhc, dn_hdr); - - if (size < sizeof(struct wusb_dn_hdr)) { - dev_err(dev, "DN data shorter than DN header (%d < %d)\n", - (int)size, (int)sizeof(struct wusb_dn_hdr)); - goto out; - } - - wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); - if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) { - dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n", - dn_hdr->bType, srcaddr); - goto out; - } - - switch (dn_hdr->bType) { - case WUSB_DN_CONNECT: - wusbhc_handle_dn_connect(wusbhc, dn_hdr, size); - break; - case WUSB_DN_ALIVE: - wusbhc_handle_dn_alive(wusbhc, wusb_dev); - break; - case WUSB_DN_DISCONNECT: - wusbhc_handle_dn_disconnect(wusbhc, wusb_dev); - break; - case WUSB_DN_MASAVAILCHANGED: - case WUSB_DN_RWAKE: - case WUSB_DN_SLEEP: - /* FIXME: handle these DNs. */ - break; - case WUSB_DN_EPRDY: - /* The hardware handles these. */ - break; - default: - dev_warn(dev, "unknown DN %u (%d octets) from %u\n", - dn_hdr->bType, (int)size, srcaddr); - } -out: - d_fnend(3, dev, "(%p, %p) = void\n", wusbhc, dn_hdr); - return; -} -EXPORT_SYMBOL_GPL(wusbhc_handle_dn); - -/* - * Disconnect a WUSB device from a the cluster - * - * @wusbhc - * @port Fake port where the device is (wusbhc index, not USB port number). - * - * In Wireless USB, a disconnect is basically telling the device he is - * being disconnected and forgetting about him. - * - * We send the device a Device Disconnect IE (WUSB1.0[7.5.11]) for 100 - * ms and then keep going. - * - * We don't do much in case of error; we always pretend we disabled - * the port and disconnected the device. If physically the request - * didn't get there (many things can fail in the way there), the stack - * will reject the device's communication attempts. - * - * @wusbhc should be refcounted and locked - */ -void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port_idx) -{ - int result; - struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; - struct wuie_disconnect *ie; - - d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); - result = 0; - wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; - if (wusb_dev == NULL) { - /* reset no device? ignore */ - dev_dbg(dev, "DISCONNECT: no device at port %u, ignoring\n", - port_idx); - goto error; - } - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); - - result = -ENOMEM; - ie = kzalloc(sizeof(*ie), GFP_KERNEL); - if (ie == NULL) - goto error; - ie->hdr.bLength = sizeof(*ie); - ie->hdr.bIEIdentifier = WUIE_ID_DEVICE_DISCONNECT; - ie->bDeviceAddress = wusb_dev->addr; - result = wusbhc_mmcie_set(wusbhc, 0, 0, &ie->hdr); - if (result < 0) { - dev_err(dev, "DISCONNECT: can't set MMC: %d\n", result); - goto error_kfree; - } - - /* 120ms, hopefully 6 MMCs */ - msleep(100); - wusbhc_mmcie_rm(wusbhc, &ie->hdr); -error_kfree: - kfree(ie); -error: - d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result); - return; -} - -static void wusb_cap_descr_printf(const unsigned level, struct device *dev, - const struct usb_wireless_cap_descriptor *wcd) -{ - d_printf(level, dev, - "WUSB Capability Descriptor\n" - " bDevCapabilityType 0x%02x\n" - " bmAttributes 0x%02x\n" - " wPhyRates 0x%04x\n" - " bmTFITXPowerInfo 0x%02x\n" - " bmFFITXPowerInfo 0x%02x\n" - " bmBandGroup 0x%04x\n" - " bReserved 0x%02x\n", - wcd->bDevCapabilityType, - wcd->bmAttributes, - le16_to_cpu(wcd->wPHYRates), - wcd->bmTFITXPowerInfo, - wcd->bmFFITXPowerInfo, - wcd->bmBandGroup, - wcd->bReserved); -} - -/* - * Walk over the BOS descriptor, verify and grok it - * - * @usb_dev: referenced - * @wusb_dev: referenced and unlocked - * - * The BOS descriptor is defined at WUSB1.0[7.4.1], and it defines a - * "flexible" way to wrap all kinds of descriptors inside an standard - * descriptor (wonder why they didn't use normal descriptors, - * btw). Not like they lack code. - * - * At the end we go to look for the WUSB Device Capabilities - * (WUSB1.0[7.4.1.1]) that is wrapped in a device capability descriptor - * that is part of the BOS descriptor set. That tells us what does the - * device support (dual role, beacon type, UWB PHY rates). - */ -static int wusb_dev_bos_grok(struct usb_device *usb_dev, - struct wusb_dev *wusb_dev, - struct usb_bos_descriptor *bos, size_t desc_size) -{ - ssize_t result; - struct device *dev = &usb_dev->dev; - void *itr, *top; - - /* Walk over BOS capabilities, verify them */ - itr = (void *)bos + sizeof(*bos); - top = itr + desc_size - sizeof(*bos); - while (itr < top) { - struct usb_dev_cap_header *cap_hdr = itr; - size_t cap_size; - u8 cap_type; - if (top - itr < sizeof(*cap_hdr)) { - dev_err(dev, "Device BUG? premature end of BOS header " - "data [offset 0x%02x]: only %zu bytes left\n", - (int)(itr - (void *)bos), top - itr); - result = -ENOSPC; - goto error_bad_cap; - } - cap_size = cap_hdr->bLength; - cap_type = cap_hdr->bDevCapabilityType; - d_printf(4, dev, "BOS Capability: 0x%02x (%zu bytes)\n", - cap_type, cap_size); - if (cap_size == 0) - break; - if (cap_size > top - itr) { - dev_err(dev, "Device BUG? premature end of BOS data " - "[offset 0x%02x cap %02x %zu bytes]: " - "only %zu bytes left\n", - (int)(itr - (void *)bos), - cap_type, cap_size, top - itr); - result = -EBADF; - goto error_bad_cap; - } - d_dump(3, dev, itr, cap_size); - switch (cap_type) { - case USB_CAP_TYPE_WIRELESS_USB: - if (cap_size != sizeof(*wusb_dev->wusb_cap_descr)) - dev_err(dev, "Device BUG? WUSB Capability " - "descriptor is %zu bytes vs %zu " - "needed\n", cap_size, - sizeof(*wusb_dev->wusb_cap_descr)); - else { - wusb_dev->wusb_cap_descr = itr; - wusb_cap_descr_printf(3, dev, itr); - } - break; - default: - dev_err(dev, "BUG? Unknown BOS capability 0x%02x " - "(%zu bytes) at offset 0x%02x\n", cap_type, - cap_size, (int)(itr - (void *)bos)); - } - itr += cap_size; - } - result = 0; -error_bad_cap: - return result; -} - -/* - * Add information from the BOS descriptors to the device - * - * @usb_dev: referenced - * @wusb_dev: referenced and unlocked - * - * So what we do is we alloc a space for the BOS descriptor of 64 - * bytes; read the first four bytes which include the wTotalLength - * field (WUSB1.0[T7-26]) and if it fits in those 64 bytes, read the - * whole thing. If not we realloc to that size. - * - * Then we call the groking function, that will fill up - * wusb_dev->wusb_cap_descr, which is what we'll need later on. - */ -static int wusb_dev_bos_add(struct usb_device *usb_dev, - struct wusb_dev *wusb_dev) -{ - ssize_t result; - struct device *dev = &usb_dev->dev; - struct usb_bos_descriptor *bos; - size_t alloc_size = 32, desc_size = 4; - - bos = kmalloc(alloc_size, GFP_KERNEL); - if (bos == NULL) - return -ENOMEM; - result = usb_get_descriptor(usb_dev, USB_DT_BOS, 0, bos, desc_size); - if (result < 4) { - dev_err(dev, "Can't get BOS descriptor or too short: %zd\n", - result); - goto error_get_descriptor; - } - desc_size = le16_to_cpu(bos->wTotalLength); - if (desc_size >= alloc_size) { - kfree(bos); - alloc_size = desc_size; - bos = kmalloc(alloc_size, GFP_KERNEL); - if (bos == NULL) - return -ENOMEM; - } - result = usb_get_descriptor(usb_dev, USB_DT_BOS, 0, bos, desc_size); - if (result < 0 || result != desc_size) { - dev_err(dev, "Can't get BOS descriptor or too short (need " - "%zu bytes): %zd\n", desc_size, result); - goto error_get_descriptor; - } - if (result < sizeof(*bos) - || le16_to_cpu(bos->wTotalLength) != desc_size) { - dev_err(dev, "Can't get BOS descriptor or too short (need " - "%zu bytes): %zd\n", desc_size, result); - goto error_get_descriptor; - } - d_printf(2, dev, "Got BOS descriptor %zd bytes, %u capabilities\n", - result, bos->bNumDeviceCaps); - d_dump(2, dev, bos, result); - result = wusb_dev_bos_grok(usb_dev, wusb_dev, bos, result); - if (result < 0) - goto error_bad_bos; - wusb_dev->bos = bos; - return 0; - -error_bad_bos: -error_get_descriptor: - kfree(bos); - wusb_dev->wusb_cap_descr = NULL; - return result; -} - -static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev) -{ - kfree(wusb_dev->bos); - wusb_dev->wusb_cap_descr = NULL; -}; - -static struct usb_wireless_cap_descriptor wusb_cap_descr_default = { - .bLength = sizeof(wusb_cap_descr_default), - .bDescriptorType = USB_DT_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB, - - .bmAttributes = USB_WIRELESS_BEACON_NONE, - .wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53), - .bmTFITXPowerInfo = 0, - .bmFFITXPowerInfo = 0, - .bmBandGroup = cpu_to_le16(0x0001), /* WUSB1.0[7.4.1] bottom */ - .bReserved = 0 -}; - -/* - * USB stack's device addition Notifier Callback - * - * Called from drivers/usb/core/hub.c when a new device is added; we - * use this hook to perform certain WUSB specific setup work on the - * new device. As well, it is the first time we can connect the - * wusb_dev and the usb_dev. So we note it down in wusb_dev and take a - * reference that we'll drop. - * - * First we need to determine if the device is a WUSB device (else we - * ignore it). For that we use the speed setting (USB_SPEED_VARIABLE) - * [FIXME: maybe we'd need something more definitive]. If so, we track - * it's usb_busd and from there, the WUSB HC. - * - * Because all WUSB HCs are contained in a 'struct wusbhc', voila, we - * get the wusbhc for the device. - * - * We have a reference on @usb_dev (as we are called at the end of its - * enumeration). - * - * NOTE: @usb_dev locked - */ -static void wusb_dev_add_ncb(struct usb_device *usb_dev) -{ - int result = 0; - struct wusb_dev *wusb_dev; - struct wusbhc *wusbhc; - struct device *dev = &usb_dev->dev; - u8 port_idx; - - if (usb_dev->wusb == 0 || usb_dev->devnum == 1) - return; /* skip non wusb and wusb RHs */ - - d_fnstart(3, dev, "(usb_dev %p)\n", usb_dev); - - wusbhc = wusbhc_get_by_usb_dev(usb_dev); - if (wusbhc == NULL) - goto error_nodev; - mutex_lock(&wusbhc->mutex); - wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, usb_dev); - port_idx = wusb_port_no_to_idx(usb_dev->portnum); - mutex_unlock(&wusbhc->mutex); - if (wusb_dev == NULL) - goto error_nodev; - wusb_dev->usb_dev = usb_get_dev(usb_dev); - usb_dev->wusb_dev = wusb_dev_get(wusb_dev); - result = wusb_dev_sec_add(wusbhc, usb_dev, wusb_dev); - if (result < 0) { - dev_err(dev, "Cannot enable security: %d\n", result); - goto error_sec_add; - } - /* Now query the device for it's BOS and attach it to wusb_dev */ - result = wusb_dev_bos_add(usb_dev, wusb_dev); - if (result < 0) { - dev_err(dev, "Cannot get BOS descriptors: %d\n", result); - goto error_bos_add; - } - result = wusb_dev_sysfs_add(wusbhc, usb_dev, wusb_dev); - if (result < 0) - goto error_add_sysfs; -out: - wusb_dev_put(wusb_dev); - wusbhc_put(wusbhc); -error_nodev: - d_fnend(3, dev, "(usb_dev %p) = void\n", usb_dev); - return; - - wusb_dev_sysfs_rm(wusb_dev); -error_add_sysfs: - wusb_dev_bos_rm(wusb_dev); -error_bos_add: - wusb_dev_sec_rm(wusb_dev); -error_sec_add: - mutex_lock(&wusbhc->mutex); - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); - mutex_unlock(&wusbhc->mutex); - goto out; -} - -/* - * Undo all the steps done at connection by the notifier callback - * - * NOTE: @usb_dev locked - */ -static void wusb_dev_rm_ncb(struct usb_device *usb_dev) -{ - struct wusb_dev *wusb_dev = usb_dev->wusb_dev; - - if (usb_dev->wusb == 0 || usb_dev->devnum == 1) - return; /* skip non wusb and wusb RHs */ - - wusb_dev_sysfs_rm(wusb_dev); - wusb_dev_bos_rm(wusb_dev); - wusb_dev_sec_rm(wusb_dev); - wusb_dev->usb_dev = NULL; - usb_dev->wusb_dev = NULL; - wusb_dev_put(wusb_dev); - usb_put_dev(usb_dev); -} - -/* - * Handle notifications from the USB stack (notifier call back) - * - * This is called when the USB stack does a - * usb_{bus,device}_{add,remove}() so we can do WUSB specific - * handling. It is called with [for the case of - * USB_DEVICE_{ADD,REMOVE} with the usb_dev locked. - */ -int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, - void *priv) -{ - int result = NOTIFY_OK; - - switch (val) { - case USB_DEVICE_ADD: - wusb_dev_add_ncb(priv); - break; - case USB_DEVICE_REMOVE: - wusb_dev_rm_ncb(priv); - break; - case USB_BUS_ADD: - /* ignore (for now) */ - case USB_BUS_REMOVE: - break; - default: - WARN_ON(1); - result = NOTIFY_BAD; - }; - return result; -} - -/* - * Return a referenced wusb_dev given a @wusbhc and @usb_dev - */ -struct wusb_dev *__wusb_dev_get_by_usb_dev(struct wusbhc *wusbhc, - struct usb_device *usb_dev) -{ - struct wusb_dev *wusb_dev; - u8 port_idx; - - port_idx = wusb_port_no_to_idx(usb_dev->portnum); - BUG_ON(port_idx > wusbhc->ports_max); - wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; - if (wusb_dev != NULL) /* ops, device is gone */ - wusb_dev_get(wusb_dev); - return wusb_dev; -} -EXPORT_SYMBOL_GPL(__wusb_dev_get_by_usb_dev); - -void wusb_dev_destroy(struct kref *_wusb_dev) -{ - struct wusb_dev *wusb_dev - = container_of(_wusb_dev, struct wusb_dev, refcnt); - list_del_init(&wusb_dev->cack_node); - wusb_dev_free(wusb_dev); - d_fnend(1, NULL, "%s (wusb_dev %p) = void\n", __func__, wusb_dev); -} -EXPORT_SYMBOL_GPL(wusb_dev_destroy); - -/* - * Create all the device connect handling infrastructure - * - * This is basically the device info array, Connect Acknowledgement - * (cack) lists, keep-alive timers (and delayed work thread). - */ -int wusbhc_devconnect_create(struct wusbhc *wusbhc) -{ - d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc); - - wusbhc->keep_alive_ie.hdr.bIEIdentifier = WUIE_ID_KEEP_ALIVE; - wusbhc->keep_alive_ie.hdr.bLength = sizeof(wusbhc->keep_alive_ie.hdr); - INIT_DELAYED_WORK(&wusbhc->keep_alive_timer, wusbhc_keep_alive_run); - - wusbhc->cack_ie.hdr.bIEIdentifier = WUIE_ID_CONNECTACK; - wusbhc->cack_ie.hdr.bLength = sizeof(wusbhc->cack_ie.hdr); - INIT_LIST_HEAD(&wusbhc->cack_list); - - d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); - return 0; -} - -/* - * Release all resources taken by the devconnect stuff - */ -void wusbhc_devconnect_destroy(struct wusbhc *wusbhc) -{ - d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc); - d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); -} - -/* - * wusbhc_devconnect_start - start accepting device connections - * @wusbhc: the WUSB HC - * - * Sets the Host Info IE to accept all new connections. - * - * FIXME: This also enables the keep alives but this is not necessary - * until there are connected and authenticated devices. - */ -int wusbhc_devconnect_start(struct wusbhc *wusbhc, - const struct wusb_ckhdid *chid) -{ - struct device *dev = wusbhc->dev; - struct wuie_host_info *hi; - int result; - - hi = kzalloc(sizeof(*hi), GFP_KERNEL); - if (hi == NULL) - return -ENOMEM; - - hi->hdr.bLength = sizeof(*hi); - hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO; - hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL); - hi->CHID = *chid; - result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr); - if (result < 0) { - dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result); - goto error_mmcie_set; - } - wusbhc->wuie_host_info = hi; - - queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, - (wusbhc->trust_timeout*CONFIG_HZ)/1000/2); - - return 0; - -error_mmcie_set: - kfree(hi); - return result; -} - -/* - * wusbhc_devconnect_stop - stop managing connected devices - * @wusbhc: the WUSB HC - * - * Removes the Host Info IE and stops the keep alives. - * - * FIXME: should this disconnect all devices? - */ -void wusbhc_devconnect_stop(struct wusbhc *wusbhc) -{ - cancel_delayed_work_sync(&wusbhc->keep_alive_timer); - WARN_ON(!list_empty(&wusbhc->cack_list)); - - wusbhc_mmcie_rm(wusbhc, &wusbhc->wuie_host_info->hdr); - kfree(wusbhc->wuie_host_info); - wusbhc->wuie_host_info = NULL; -} - -/* - * wusb_set_dev_addr - set the WUSB device address used by the host - * @wusbhc: the WUSB HC the device is connect to - * @wusb_dev: the WUSB device - * @addr: new device address - */ -int wusb_set_dev_addr(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, u8 addr) -{ - int result; - - wusb_dev->addr = addr; - result = wusbhc->dev_info_set(wusbhc, wusb_dev); - if (result < 0) - dev_err(wusbhc->dev, "device %d: failed to set device " - "address\n", wusb_dev->port_idx); - else - dev_info(wusbhc->dev, "device %d: %s addr %u\n", - wusb_dev->port_idx, - (addr & WUSB_DEV_ADDR_UNAUTH) ? "unauth" : "auth", - wusb_dev->addr); - - return result; -} diff --git a/trunk/drivers/usb/wusbcore/mmc.c b/trunk/drivers/usb/wusbcore/mmc.c deleted file mode 100644 index cfa77a01cebd..000000000000 --- a/trunk/drivers/usb/wusbcore/mmc.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * WUSB Wire Adapter: Control/Data Streaming Interface (WUSB[8]) - * MMC (Microscheduled Management Command) handling - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * WUIEs and MMC IEs...well, they are almost the same at the end. MMC - * IEs are Wireless USB IEs that go into the MMC period...[what is - * that? look in Design-overview.txt]. - * - * - * This is a simple subsystem to keep track of which IEs are being - * sent by the host in the MMC period. - * - * For each WUIE we ask to send, we keep it in an array, so we can - * request its removal later, or replace the content. They are tracked - * by pointer, so be sure to use the same pointer if you want to - * remove it or update the contents. - * - * FIXME: - * - add timers that autoremove intervalled IEs? - */ -#include -#include "wusbhc.h" - -/* Initialize the MMCIEs handling mechanism */ -int wusbhc_mmcie_create(struct wusbhc *wusbhc) -{ - u8 mmcies = wusbhc->mmcies_max; - wusbhc->mmcie = kcalloc(mmcies, sizeof(wusbhc->mmcie[0]), GFP_KERNEL); - if (wusbhc->mmcie == NULL) - return -ENOMEM; - mutex_init(&wusbhc->mmcie_mutex); - return 0; -} - -/* Release resources used by the MMCIEs handling mechanism */ -void wusbhc_mmcie_destroy(struct wusbhc *wusbhc) -{ - kfree(wusbhc->mmcie); -} - -/* - * Add or replace an MMC Wireless USB IE. - * - * @interval: See WUSB1.0[8.5.3.1] - * @repeat_cnt: See WUSB1.0[8.5.3.1] - * @handle: See WUSB1.0[8.5.3.1] - * @wuie: Pointer to the header of the WUSB IE data to add. - * MUST BE allocated in a kmalloc buffer (no stack or - * vmalloc). - * THE CALLER ALWAYS OWNS THE POINTER (we don't free it - * on remove, we just forget about it). - * @returns: 0 if ok, < 0 errno code on error. - * - * Goes over the *whole* @wusbhc->mmcie array looking for (a) the - * first free spot and (b) if @wuie is already in the array (aka: - * transmitted in the MMCs) the spot were it is. - * - * If present, we "overwrite it" (update). - * - * - * NOTE: Need special ordering rules -- see below WUSB1.0 Table 7-38. - * The host uses the handle as the 'sort' index. We - * allocate the last one always for the WUIE_ID_HOST_INFO, and - * the rest, first come first serve in inverse order. - * - * Host software must make sure that it adds the other IEs in - * the right order... the host hardware is responsible for - * placing the WCTA IEs in the right place with the other IEs - * set by host software. - * - * NOTE: we can access wusbhc->wa_descr without locking because it is - * read only. - */ -int wusbhc_mmcie_set(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, - struct wuie_hdr *wuie) -{ - int result = -ENOBUFS; - unsigned handle, itr; - - /* Search a handle, taking into account the ordering */ - mutex_lock(&wusbhc->mmcie_mutex); - switch (wuie->bIEIdentifier) { - case WUIE_ID_HOST_INFO: - /* Always last */ - handle = wusbhc->mmcies_max - 1; - break; - case WUIE_ID_ISOCH_DISCARD: - dev_err(wusbhc->dev, "Special ordering case for WUIE ID 0x%x " - "unimplemented\n", wuie->bIEIdentifier); - result = -ENOSYS; - goto error_unlock; - default: - /* search for it or find the last empty slot */ - handle = ~0; - for (itr = 0; itr < wusbhc->mmcies_max - 1; itr++) { - if (wusbhc->mmcie[itr] == wuie) { - handle = itr; - break; - } - if (wusbhc->mmcie[itr] == NULL) - handle = itr; - } - if (handle == ~0) - goto error_unlock; - } - result = (wusbhc->mmcie_add)(wusbhc, interval, repeat_cnt, handle, - wuie); - if (result >= 0) - wusbhc->mmcie[handle] = wuie; -error_unlock: - mutex_unlock(&wusbhc->mmcie_mutex); - return result; -} -EXPORT_SYMBOL_GPL(wusbhc_mmcie_set); - -/* - * Remove an MMC IE previously added with wusbhc_mmcie_set() - * - * @wuie Pointer used to add the WUIE - */ -void wusbhc_mmcie_rm(struct wusbhc *wusbhc, struct wuie_hdr *wuie) -{ - int result; - unsigned handle, itr; - - mutex_lock(&wusbhc->mmcie_mutex); - for (itr = 0; itr < wusbhc->mmcies_max; itr++) { - if (wusbhc->mmcie[itr] == wuie) { - handle = itr; - goto found; - } - } - mutex_unlock(&wusbhc->mmcie_mutex); - return; - -found: - result = (wusbhc->mmcie_rm)(wusbhc, handle); - if (result == 0) - wusbhc->mmcie[itr] = NULL; - mutex_unlock(&wusbhc->mmcie_mutex); -} -EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm); - -/* - * wusbhc_start - start transmitting MMCs and accepting connections - * @wusbhc: the HC to start - * @chid: the CHID to use for this host - * - * Establishes a cluster reservation, enables device connections, and - * starts MMCs with appropriate DNTS parameters. - */ -int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) -{ - int result; - struct device *dev = wusbhc->dev; - - WARN_ON(wusbhc->wuie_host_info != NULL); - - result = wusbhc_rsv_establish(wusbhc); - if (result < 0) { - dev_err(dev, "cannot establish cluster reservation: %d\n", - result); - goto error_rsv_establish; - } - - result = wusbhc_devconnect_start(wusbhc, chid); - if (result < 0) { - dev_err(dev, "error enabling device connections: %d\n", result); - goto error_devconnect_start; - } - - result = wusbhc_sec_start(wusbhc); - if (result < 0) { - dev_err(dev, "error starting security in the HC: %d\n", result); - goto error_sec_start; - } - /* FIXME: the choice of the DNTS parameters is somewhat - * arbitrary */ - result = wusbhc->set_num_dnts(wusbhc, 0, 15); - if (result < 0) { - dev_err(dev, "Cannot set DNTS parameters: %d\n", result); - goto error_set_num_dnts; - } - result = wusbhc->start(wusbhc); - if (result < 0) { - dev_err(dev, "error starting wusbch: %d\n", result); - goto error_wusbhc_start; - } - wusbhc->active = 1; - return 0; - -error_wusbhc_start: - wusbhc_sec_stop(wusbhc); -error_set_num_dnts: -error_sec_start: - wusbhc_devconnect_stop(wusbhc); -error_devconnect_start: - wusbhc_rsv_terminate(wusbhc); -error_rsv_establish: - return result; -} - -/* - * Disconnect all from the WUSB Channel - * - * Send a Host Disconnect IE in the MMC, wait, don't send it any more - */ -static int __wusbhc_host_disconnect_ie(struct wusbhc *wusbhc) -{ - int result = -ENOMEM; - struct wuie_host_disconnect *host_disconnect_ie; - might_sleep(); - host_disconnect_ie = kmalloc(sizeof(*host_disconnect_ie), GFP_KERNEL); - if (host_disconnect_ie == NULL) - goto error_alloc; - host_disconnect_ie->hdr.bLength = sizeof(*host_disconnect_ie); - host_disconnect_ie->hdr.bIEIdentifier = WUIE_ID_HOST_DISCONNECT; - result = wusbhc_mmcie_set(wusbhc, 0, 0, &host_disconnect_ie->hdr); - if (result < 0) - goto error_mmcie_set; - - /* WUSB1.0[8.5.3.1 & 7.5.2] */ - msleep(100); - wusbhc_mmcie_rm(wusbhc, &host_disconnect_ie->hdr); -error_mmcie_set: - kfree(host_disconnect_ie); -error_alloc: - return result; -} - -/* - * wusbhc_stop - stop transmitting MMCs - * @wusbhc: the HC to stop - * - * Send a Host Disconnect IE, wait, remove all the MMCs (stop sending MMCs). - * - * If we can't allocate a Host Stop IE, screw it, we don't notify the - * devices we are disconnecting... - */ -void wusbhc_stop(struct wusbhc *wusbhc) -{ - if (wusbhc->active) { - wusbhc->active = 0; - wusbhc->stop(wusbhc); - wusbhc_sec_stop(wusbhc); - __wusbhc_host_disconnect_ie(wusbhc); - wusbhc_devconnect_stop(wusbhc); - wusbhc_rsv_terminate(wusbhc); - } -} -EXPORT_SYMBOL_GPL(wusbhc_stop); - -/* - * Change the CHID in a WUSB Channel - * - * If it is just a new CHID, send a Host Disconnect IE and then change - * the CHID IE. - */ -static int __wusbhc_chid_change(struct wusbhc *wusbhc, - const struct wusb_ckhdid *chid) -{ - int result = -ENOSYS; - struct device *dev = wusbhc->dev; - dev_err(dev, "%s() not implemented yet\n", __func__); - return result; - - BUG_ON(wusbhc->wuie_host_info == NULL); - __wusbhc_host_disconnect_ie(wusbhc); - wusbhc->wuie_host_info->CHID = *chid; - result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->wuie_host_info->hdr); - if (result < 0) - dev_err(dev, "Can't update Host Info WUSB IE: %d\n", result); - return result; -} - -/* - * Set/reset/update a new CHID - * - * Depending on the previous state of the MMCs, start, stop or change - * the sent MMC. This effectively switches the host controller on and - * off (radio wise). - */ -int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) -{ - int result = 0; - - if (memcmp(chid, &wusb_ckhdid_zero, sizeof(chid)) == 0) - chid = NULL; - - mutex_lock(&wusbhc->mutex); - if (wusbhc->active) { - if (chid) - result = __wusbhc_chid_change(wusbhc, chid); - else - wusbhc_stop(wusbhc); - } else { - if (chid) - wusbhc_start(wusbhc, chid); - } - mutex_unlock(&wusbhc->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wusbhc_chid_set); diff --git a/trunk/drivers/usb/wusbcore/pal.c b/trunk/drivers/usb/wusbcore/pal.c deleted file mode 100644 index 7cc51e9905cf..000000000000 --- a/trunk/drivers/usb/wusbcore/pal.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Wireless USB Host Controller - * UWB Protocol Adaptation Layer (PAL) glue. - * - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "wusbhc.h" - -/** - * wusbhc_pal_register - register the WUSB HC as a UWB PAL - * @wusbhc: the WUSB HC - */ -int wusbhc_pal_register(struct wusbhc *wusbhc) -{ - uwb_pal_init(&wusbhc->pal); - - wusbhc->pal.name = "wusbhc"; - wusbhc->pal.device = wusbhc->usb_hcd.self.controller; - - return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal); -} - -/** - * wusbhc_pal_register - unregister the WUSB HC as a UWB PAL - * @wusbhc: the WUSB HC - */ -void wusbhc_pal_unregister(struct wusbhc *wusbhc) -{ - uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal); -} diff --git a/trunk/drivers/usb/wusbcore/reservation.c b/trunk/drivers/usb/wusbcore/reservation.c deleted file mode 100644 index fc63e77ded2d..000000000000 --- a/trunk/drivers/usb/wusbcore/reservation.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * WUSB cluster reservation management - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include - -#include "wusbhc.h" - -/* - * WUSB cluster reservations are multicast reservations with the - * broadcast cluster ID (BCID) as the target DevAddr. - * - * FIXME: consider adjusting the reservation depending on what devices - * are attached. - */ - -static int wusbhc_bwa_set(struct wusbhc *wusbhc, u8 stream, - const struct uwb_mas_bm *mas) -{ - if (mas == NULL) - mas = &uwb_mas_bm_zero; - return wusbhc->bwa_set(wusbhc, stream, mas); -} - -/** - * wusbhc_rsv_complete_cb - WUSB HC reservation complete callback - * @rsv: the reservation - * - * Either set or clear the HC's view of the reservation. - * - * FIXME: when a reservation is denied the HC should be stopped. - */ -static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv) -{ - struct wusbhc *wusbhc = rsv->pal_priv; - struct device *dev = wusbhc->dev; - char buf[72]; - - switch (rsv->state) { - case UWB_RSV_STATE_O_ESTABLISHED: - bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS); - dev_dbg(dev, "established reservation: %s\n", buf); - wusbhc_bwa_set(wusbhc, rsv->stream, &rsv->mas); - break; - case UWB_RSV_STATE_NONE: - dev_dbg(dev, "removed reservation\n"); - wusbhc_bwa_set(wusbhc, 0, NULL); - wusbhc->rsv = NULL; - break; - default: - dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state); - break; - } -} - - -/** - * wusbhc_rsv_establish - establish a reservation for the cluster - * @wusbhc: the WUSB HC requesting a bandwith reservation - */ -int wusbhc_rsv_establish(struct wusbhc *wusbhc) -{ - struct uwb_rc *rc = wusbhc->uwb_rc; - struct uwb_rsv *rsv; - struct uwb_dev_addr bcid; - int ret; - - rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc); - if (rsv == NULL) - return -ENOMEM; - - bcid.data[0] = wusbhc->cluster_id; - bcid.data[1] = 0; - - rsv->owner = &rc->uwb_dev; - rsv->target.type = UWB_RSV_TARGET_DEVADDR; - rsv->target.devaddr = bcid; - rsv->type = UWB_DRP_TYPE_PRIVATE; - rsv->max_mas = 256; - rsv->min_mas = 16; /* one MAS per zone? */ - rsv->sparsity = 16; /* at least one MAS in each zone? */ - rsv->is_multicast = true; - - ret = uwb_rsv_establish(rsv); - if (ret == 0) - wusbhc->rsv = rsv; - else - uwb_rsv_destroy(rsv); - return ret; -} - - -/** - * wusbhc_rsv_terminate - terminate any cluster reservation - * @wusbhc: the WUSB host whose reservation is to be terminated - */ -void wusbhc_rsv_terminate(struct wusbhc *wusbhc) -{ - if (wusbhc->rsv) - uwb_rsv_terminate(wusbhc->rsv); -} diff --git a/trunk/drivers/usb/wusbcore/rh.c b/trunk/drivers/usb/wusbcore/rh.c deleted file mode 100644 index 267a64325106..000000000000 --- a/trunk/drivers/usb/wusbcore/rh.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Wireless USB Host Controller - * Root Hub operations - * - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * We fake a root hub that has fake ports (as many as simultaneous - * devices the Wireless USB Host Controller can deal with). For each - * port we keep an state in @wusbhc->port[index] identical to the one - * specified in the USB2.0[ch11] spec and some extra device - * information that complements the one in 'struct usb_device' (as - * this lacs a hcpriv pointer). - * - * Note this is common to WHCI and HWA host controllers. - * - * Through here we enable most of the state changes that the USB stack - * will use to connect or disconnect devices. We need to do some - * forced adaptation of Wireless USB device states vs. wired: - * - * USB: WUSB: - * - * Port Powered-off port slot n/a - * Powered-on port slot available - * Disconnected port slot available - * Connected port slot assigned device - * device sent DN_Connect - * device was authenticated - * Enabled device is authenticated, transitioned - * from unauth -> auth -> default address - * -> enabled - * Reset disconnect - * Disable disconnect - * - * This maps the standard USB port states with the WUSB device states - * so we can fake ports without having to modify the USB stack. - * - * FIXME: this process will change in the future - * - * - * ENTRY POINTS - * - * Our entry points into here are, as in hcd.c, the USB stack root hub - * ops defined in the usb_hcd struct: - * - * wusbhc_rh_status_data() Provide hub and port status data bitmap - * - * wusbhc_rh_control() Execution of all the major requests - * you can do to a hub (Set|Clear - * features, get descriptors, status, etc). - * - * wusbhc_rh_[suspend|resume]() That - * - * wusbhc_rh_start_port_reset() ??? unimplemented - */ -#include "wusbhc.h" - -#define D_LOCAL 0 -#include - -/* - * Reset a fake port - * - * This can be called to reset a port from any other state or to reset - * it when connecting. In Wireless USB they are different; when doing - * a new connect that involves going over the authentication. When - * just reseting, its a different story. - * - * The Linux USB stack resets a port twice before it considers it - * enabled, so we have to detect and ignore that. - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - * - * Supposedly we are the only thread accesing @wusbhc->port; in any - * case, maybe we should move the mutex locking from - * wusbhc_devconnect_auth() to here. - * - * @port_idx refers to the wusbhc's port index, not the USB port number - */ -static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) -{ - int result = 0; - struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); - - d_fnstart(3, wusbhc->dev, "(wusbhc %p port_idx %u)\n", - wusbhc, port_idx); - if (port->reset_count == 0) { - wusbhc_devconnect_auth(wusbhc, port_idx); - port->reset_count++; - } else if (port->reset_count == 1) - /* see header */ - d_printf(2, wusbhc->dev, "Ignoring second reset on port_idx " - "%u\n", port_idx); - else - result = wusbhc_dev_reset(wusbhc, port_idx); - d_fnend(3, wusbhc->dev, "(wusbhc %p port_idx %u) = %d\n", - wusbhc, port_idx, result); - return result; -} - -/* - * Return the hub change status bitmap - * - * The bits in the change status bitmap are cleared when a - * ClearPortFeature request is issued (USB2.0[11.12.3,11.12.4]. - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - * - * WARNING!! This gets called from atomic context; we cannot get the - * mutex--the only race condition we can find is some bit - * changing just after we copy it, which shouldn't be too - * big of a problem [and we can't make it an spinlock - * because other parts need to take it and sleep] . - * - * @usb_hcd is refcounted, so it won't dissapear under us - * and before killing a host, the polling of the root hub - * would be stopped anyway. - */ -int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - size_t cnt, size; - unsigned long *buf = (unsigned long *) _buf; - - d_fnstart(1, wusbhc->dev, "(wusbhc %p)\n", wusbhc); - /* WE DON'T LOCK, see comment */ - size = wusbhc->ports_max + 1 /* hub bit */; - size = (size + 8 - 1) / 8; /* round to bytes */ - for (cnt = 0; cnt < wusbhc->ports_max; cnt++) - if (wusb_port_by_idx(wusbhc, cnt)->change) - set_bit(cnt + 1, buf); - else - clear_bit(cnt + 1, buf); - d_fnend(1, wusbhc->dev, "(wusbhc %p) %u, buffer:\n", wusbhc, (int)size); - d_dump(1, wusbhc->dev, _buf, size); - return size; -} -EXPORT_SYMBOL_GPL(wusbhc_rh_status_data); - -/* - * Return the hub's desciptor - * - * NOTE: almost cut and paste from ehci-hub.c - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked - */ -static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue, - u16 wIndex, - struct usb_hub_descriptor *descr, - u16 wLength) -{ - u16 temp = 1 + (wusbhc->ports_max / 8); - u8 length = 7 + 2 * temp; - - if (wLength < length) - return -ENOSPC; - descr->bDescLength = 7 + 2 * temp; - descr->bDescriptorType = 0x29; /* HUB type */ - descr->bNbrPorts = wusbhc->ports_max; - descr->wHubCharacteristics = cpu_to_le16( - 0x00 /* All ports power at once */ - | 0x00 /* not part of compound device */ - | 0x10 /* No overcurrent protection */ - | 0x00 /* 8 FS think time FIXME ?? */ - | 0x00); /* No port indicators */ - descr->bPwrOn2PwrGood = 0; - descr->bHubContrCurrent = 0; - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - memset(&descr->bitmap[0], 0, temp); - memset(&descr->bitmap[temp], 0xff, temp); - return 0; -} - -/* - * Clear a hub feature - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - * - * Nothing to do, so no locking needed ;) - */ -static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature) -{ - int result; - struct device *dev = wusbhc->dev; - - d_fnstart(4, dev, "(%p, feature 0x%04u)\n", wusbhc, feature); - switch (feature) { - case C_HUB_LOCAL_POWER: - /* FIXME: maybe plug bit 0 to the power input status, - * if any? - * see wusbhc_rh_get_hub_status() */ - case C_HUB_OVER_CURRENT: - result = 0; - break; - default: - result = -EPIPE; - } - d_fnend(4, dev, "(%p, feature 0x%04u), %d\n", wusbhc, feature, result); - return result; -} - -/* - * Return hub status (it is always zero...) - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - * - * Nothing to do, so no locking needed ;) - */ -static int wusbhc_rh_get_hub_status(struct wusbhc *wusbhc, u32 *buf, - u16 wLength) -{ - /* FIXME: maybe plug bit 0 to the power input status (if any)? */ - *buf = 0; - return 0; -} - -/* - * Set a port feature - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - */ -static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature, - u8 selector, u8 port_idx) -{ - int result = -EINVAL; - struct device *dev = wusbhc->dev; - - d_fnstart(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d)\n", - feature, selector, port_idx); - - if (port_idx > wusbhc->ports_max) - goto error; - - switch (feature) { - /* According to USB2.0[11.24.2.13]p2, these features - * are not required to be implemented. */ - case USB_PORT_FEAT_C_OVER_CURRENT: - case USB_PORT_FEAT_C_ENABLE: - case USB_PORT_FEAT_C_SUSPEND: - case USB_PORT_FEAT_C_CONNECTION: - case USB_PORT_FEAT_C_RESET: - result = 0; - break; - - case USB_PORT_FEAT_POWER: - /* No such thing, but we fake it works */ - mutex_lock(&wusbhc->mutex); - wusb_port_by_idx(wusbhc, port_idx)->status |= USB_PORT_STAT_POWER; - mutex_unlock(&wusbhc->mutex); - result = 0; - break; - case USB_PORT_FEAT_RESET: - result = wusbhc_rh_port_reset(wusbhc, port_idx); - break; - case USB_PORT_FEAT_ENABLE: - case USB_PORT_FEAT_SUSPEND: - dev_err(dev, "(port_idx %d) set feat %d/%d UNIMPLEMENTED\n", - port_idx, feature, selector); - result = -ENOSYS; - break; - default: - dev_err(dev, "(port_idx %d) set feat %d/%d UNKNOWN\n", - port_idx, feature, selector); - result = -EPIPE; - break; - } -error: - d_fnend(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d) = %d\n", - feature, selector, port_idx, result); - return result; -} - -/* - * Clear a port feature... - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - */ -static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, - u8 selector, u8 port_idx) -{ - int result = -EINVAL; - struct device *dev = wusbhc->dev; - - d_fnstart(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d)\n", - wusbhc, feature, selector, port_idx); - - if (port_idx > wusbhc->ports_max) - goto error; - - mutex_lock(&wusbhc->mutex); - result = 0; - switch (feature) { - case USB_PORT_FEAT_POWER: /* fake port always on */ - /* According to USB2.0[11.24.2.7.1.4], no need to implement? */ - case USB_PORT_FEAT_C_OVER_CURRENT: - break; - case USB_PORT_FEAT_C_RESET: - wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_RESET; - break; - case USB_PORT_FEAT_C_CONNECTION: - wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_CONNECTION; - break; - case USB_PORT_FEAT_ENABLE: - __wusbhc_dev_disable(wusbhc, port_idx); - break; - case USB_PORT_FEAT_C_ENABLE: - wusb_port_by_idx(wusbhc, port_idx)->change &= ~USB_PORT_STAT_C_ENABLE; - break; - case USB_PORT_FEAT_SUSPEND: - case USB_PORT_FEAT_C_SUSPEND: - case 0xffff: /* ??? FIXME */ - dev_err(dev, "(port_idx %d) Clear feat %d/%d UNIMPLEMENTED\n", - port_idx, feature, selector); - /* dump_stack(); */ - result = -ENOSYS; - break; - default: - dev_err(dev, "(port_idx %d) Clear feat %d/%d UNKNOWN\n", - port_idx, feature, selector); - result = -EPIPE; - break; - } - mutex_unlock(&wusbhc->mutex); -error: - d_fnend(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d) = " - "%d\n", wusbhc, feature, selector, port_idx, result); - return result; -} - -/* - * Return the port's status - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - */ -static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, - u32 *_buf, u16 wLength) -{ - int result = -EINVAL; - u16 *buf = (u16 *) _buf; - - d_fnstart(1, wusbhc->dev, "(wusbhc %p port_idx %u wLength %u)\n", - wusbhc, port_idx, wLength); - if (port_idx > wusbhc->ports_max) - goto error; - mutex_lock(&wusbhc->mutex); - buf[0] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->status); - buf[1] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->change); - result = 0; - mutex_unlock(&wusbhc->mutex); -error: - d_fnend(1, wusbhc->dev, "(wusbhc %p) = %d, buffer:\n", wusbhc, result); - d_dump(1, wusbhc->dev, _buf, wLength); - return result; -} - -/* - * Entry point for Root Hub operations - * - * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. - */ -int wusbhc_rh_control(struct usb_hcd *usb_hcd, u16 reqntype, u16 wValue, - u16 wIndex, char *buf, u16 wLength) -{ - int result = -ENOSYS; - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - - switch (reqntype) { - case GetHubDescriptor: - result = wusbhc_rh_get_hub_descr( - wusbhc, wValue, wIndex, - (struct usb_hub_descriptor *) buf, wLength); - break; - case ClearHubFeature: - result = wusbhc_rh_clear_hub_feat(wusbhc, wValue); - break; - case GetHubStatus: - result = wusbhc_rh_get_hub_status(wusbhc, (u32 *)buf, wLength); - break; - - case SetPortFeature: - result = wusbhc_rh_set_port_feat(wusbhc, wValue, wIndex >> 8, - (wIndex & 0xff) - 1); - break; - case ClearPortFeature: - result = wusbhc_rh_clear_port_feat(wusbhc, wValue, wIndex >> 8, - (wIndex & 0xff) - 1); - break; - case GetPortStatus: - result = wusbhc_rh_get_port_status(wusbhc, wIndex - 1, - (u32 *)buf, wLength); - break; - - case SetHubFeature: - default: - dev_err(wusbhc->dev, "%s (%p [%p], %x, %x, %x, %p, %x) " - "UNIMPLEMENTED\n", __func__, usb_hcd, wusbhc, reqntype, - wValue, wIndex, buf, wLength); - /* dump_stack(); */ - result = -ENOSYS; - } - return result; -} -EXPORT_SYMBOL_GPL(wusbhc_rh_control); - -int wusbhc_rh_suspend(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, - usb_hcd, wusbhc); - /* dump_stack(); */ - return -ENOSYS; -} -EXPORT_SYMBOL_GPL(wusbhc_rh_suspend); - -int wusbhc_rh_resume(struct usb_hcd *usb_hcd) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, - usb_hcd, wusbhc); - /* dump_stack(); */ - return -ENOSYS; -} -EXPORT_SYMBOL_GPL(wusbhc_rh_resume); - -int wusbhc_rh_start_port_reset(struct usb_hcd *usb_hcd, unsigned port_idx) -{ - struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - dev_err(wusbhc->dev, "%s (%p [%p], port_idx %u) UNIMPLEMENTED\n", - __func__, usb_hcd, wusbhc, port_idx); - WARN_ON(1); - return -ENOSYS; -} -EXPORT_SYMBOL_GPL(wusbhc_rh_start_port_reset); - -static void wusb_port_init(struct wusb_port *port) -{ - port->status |= USB_PORT_STAT_HIGH_SPEED; -} - -/* - * Alloc fake port specific fields and status. - */ -int wusbhc_rh_create(struct wusbhc *wusbhc) -{ - int result = -ENOMEM; - size_t port_size, itr; - port_size = wusbhc->ports_max * sizeof(wusbhc->port[0]); - wusbhc->port = kzalloc(port_size, GFP_KERNEL); - if (wusbhc->port == NULL) - goto error_port_alloc; - for (itr = 0; itr < wusbhc->ports_max; itr++) - wusb_port_init(&wusbhc->port[itr]); - result = 0; -error_port_alloc: - return result; -} - -void wusbhc_rh_destroy(struct wusbhc *wusbhc) -{ - kfree(wusbhc->port); -} diff --git a/trunk/drivers/usb/wusbcore/security.c b/trunk/drivers/usb/wusbcore/security.c deleted file mode 100644 index a101cad6a8d4..000000000000 --- a/trunk/drivers/usb/wusbcore/security.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Wireless USB Host Controller - * Security support: encryption enablement, etc - * - * Copyright (C) 2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ -#include -#include -#include -#include "wusbhc.h" - -/* - * DEBUG & SECURITY WARNING!!!! - * - * If you enable this past 1, the debug code will weaken the - * cryptographic safety of the system (on purpose, for debugging). - * - * Weaken means: - * we print secret keys and intermediate values all the way, - */ -#undef D_LOCAL -#define D_LOCAL 2 -#include - -static void wusbhc_set_gtk_callback(struct urb *urb); -static void wusbhc_gtk_rekey_done_work(struct work_struct *work); - -int wusbhc_sec_create(struct wusbhc *wusbhc) -{ - wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data); - wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY; - wusbhc->gtk.descr.bReserved = 0; - - wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK, - WUSB_KEY_INDEX_ORIGINATOR_HOST); - - INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work); - - return 0; -} - - -/* Called when the HC is destroyed */ -void wusbhc_sec_destroy(struct wusbhc *wusbhc) -{ -} - - -/** - * wusbhc_next_tkid - generate a new, currently unused, TKID - * @wusbhc: the WUSB host controller - * @wusb_dev: the device whose PTK the TKID is for - * (or NULL for a TKID for a GTK) - * - * The generated TKID consist of two parts: the device's authenicated - * address (or 0 or a GTK); and an incrementing number. This ensures - * that TKIDs cannot be shared between devices and by the time the - * incrementing number wraps around the older TKIDs will no longer be - * in use (a maximum of two keys may be active at any one time). - */ -static u32 wusbhc_next_tkid(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - u32 *tkid; - u32 addr; - - if (wusb_dev == NULL) { - tkid = &wusbhc->gtk_tkid; - addr = 0; - } else { - tkid = &wusb_port_by_idx(wusbhc, wusb_dev->port_idx)->ptk_tkid; - addr = wusb_dev->addr & 0x7f; - } - - *tkid = (addr << 8) | ((*tkid + 1) & 0xff); - - return *tkid; -} - -static void wusbhc_generate_gtk(struct wusbhc *wusbhc) -{ - const size_t key_size = sizeof(wusbhc->gtk.data); - u32 tkid; - - tkid = wusbhc_next_tkid(wusbhc, NULL); - - wusbhc->gtk.descr.tTKID[0] = (tkid >> 0) & 0xff; - wusbhc->gtk.descr.tTKID[1] = (tkid >> 8) & 0xff; - wusbhc->gtk.descr.tTKID[2] = (tkid >> 16) & 0xff; - - get_random_bytes(wusbhc->gtk.descr.bKeyData, key_size); -} - -/** - * wusbhc_sec_start - start the security management process - * @wusbhc: the WUSB host controller - * - * Generate and set an initial GTK on the host controller. - * - * Called when the HC is started. - */ -int wusbhc_sec_start(struct wusbhc *wusbhc) -{ - const size_t key_size = sizeof(wusbhc->gtk.data); - int result; - - wusbhc_generate_gtk(wusbhc); - - result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, - &wusbhc->gtk.descr.bKeyData, key_size); - if (result < 0) - dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n", - result); - - return result; -} - -/** - * wusbhc_sec_stop - stop the security management process - * @wusbhc: the WUSB host controller - * - * Wait for any pending GTK rekeys to stop. - */ -void wusbhc_sec_stop(struct wusbhc *wusbhc) -{ - cancel_work_sync(&wusbhc->gtk_rekey_done_work); -} - - -/** @returns encryption type name */ -const char *wusb_et_name(u8 x) -{ - switch (x) { - case USB_ENC_TYPE_UNSECURE: return "unsecure"; - case USB_ENC_TYPE_WIRED: return "wired"; - case USB_ENC_TYPE_CCM_1: return "CCM-1"; - case USB_ENC_TYPE_RSA_1: return "RSA-1"; - default: return "unknown"; - } -} -EXPORT_SYMBOL_GPL(wusb_et_name); - -/* - * Set the device encryption method - * - * We tell the device which encryption method to use; we do this when - * setting up the device's security. - */ -static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value) -{ - int result; - struct device *dev = &usb_dev->dev; - struct wusb_dev *wusb_dev = usb_dev->wusb_dev; - - if (value) { - value = wusb_dev->ccm1_etd.bEncryptionValue; - } else { - /* FIXME: should be wusb_dev->etd[UNSECURE].bEncryptionValue */ - value = 0; - } - /* Set device's */ - result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_ENCRYPTION, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - value, 0, NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) - dev_err(dev, "Can't set device's WUSB encryption to " - "%s (value %d): %d\n", - wusb_et_name(wusb_dev->ccm1_etd.bEncryptionType), - wusb_dev->ccm1_etd.bEncryptionValue, result); - return result; -} - -/* - * Set the GTK to be used by a device. - * - * The device must be authenticated. - */ -static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) -{ - struct usb_device *usb_dev = wusb_dev->usb_dev; - - return usb_control_msg( - usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_DESCRIPTOR, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_DT_KEY << 8 | wusbhc->gtk_index, 0, - &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, - 1000); -} - - -/* FIXME: prototype for adding security */ -int wusb_dev_sec_add(struct wusbhc *wusbhc, - struct usb_device *usb_dev, struct wusb_dev *wusb_dev) -{ - int result, bytes, secd_size; - struct device *dev = &usb_dev->dev; - struct usb_security_descriptor secd; - const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; - void *secd_buf; - const void *itr, *top; - char buf[64]; - - d_fnstart(3, dev, "(usb_dev %p, wusb_dev %p)\n", usb_dev, wusb_dev); - result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, - 0, &secd, sizeof(secd)); - if (result < sizeof(secd)) { - dev_err(dev, "Can't read security descriptor or " - "not enough data: %d\n", result); - goto error_secd; - } - secd_size = le16_to_cpu(secd.wTotalLength); - d_printf(5, dev, "got %d bytes of sec descriptor, total is %d\n", - result, secd_size); - secd_buf = kmalloc(secd_size, GFP_KERNEL); - if (secd_buf == NULL) { - dev_err(dev, "Can't allocate space for security descriptors\n"); - goto error_secd_alloc; - } - result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, - 0, secd_buf, secd_size); - if (result < secd_size) { - dev_err(dev, "Can't read security descriptor or " - "not enough data: %d\n", result); - goto error_secd_all; - } - d_printf(5, dev, "got %d bytes of sec descriptors\n", result); - bytes = 0; - itr = secd_buf + sizeof(secd); - top = secd_buf + result; - while (itr < top) { - etd = itr; - if (top - itr < sizeof(*etd)) { - dev_err(dev, "BUG: bad device security descriptor; " - "not enough data (%zu vs %zu bytes left)\n", - top - itr, sizeof(*etd)); - break; - } - if (etd->bLength < sizeof(*etd)) { - dev_err(dev, "BUG: bad device encryption descriptor; " - "descriptor is too short " - "(%u vs %zu needed)\n", - etd->bLength, sizeof(*etd)); - break; - } - itr += etd->bLength; - bytes += snprintf(buf + bytes, sizeof(buf) - bytes, - "%s (0x%02x/%02x) ", - wusb_et_name(etd->bEncryptionType), - etd->bEncryptionValue, etd->bAuthKeyIndex); - if (etd->bEncryptionType == USB_ENC_TYPE_CCM_1) - ccm1_etd = etd; - } - /* This code only supports CCM1 as of now. */ - /* FIXME: user has to choose which sec mode to use? - * In theory we want CCM */ - if (ccm1_etd == NULL) { - dev_err(dev, "WUSB device doesn't support CCM1 encryption, " - "can't use!\n"); - result = -EINVAL; - goto error_no_ccm1; - } - wusb_dev->ccm1_etd = *ccm1_etd; - dev_info(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", - buf, wusb_et_name(ccm1_etd->bEncryptionType), - ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); - result = 0; - kfree(secd_buf); -out: - d_fnend(3, dev, "(usb_dev %p, wusb_dev %p) = %d\n", - usb_dev, wusb_dev, result); - return result; - - -error_no_ccm1: -error_secd_all: - kfree(secd_buf); -error_secd_alloc: -error_secd: - goto out; -} - -void wusb_dev_sec_rm(struct wusb_dev *wusb_dev) -{ - /* Nothing so far */ -} - -static void hs_printk(unsigned level, struct device *dev, - struct usb_handshake *hs) -{ - d_printf(level, dev, - " bMessageNumber: %u\n" - " bStatus: %u\n" - " tTKID: %02x %02x %02x\n" - " CDID: %02x %02x %02x %02x %02x %02x %02x %02x\n" - " %02x %02x %02x %02x %02x %02x %02x %02x\n" - " nonce: %02x %02x %02x %02x %02x %02x %02x %02x\n" - " %02x %02x %02x %02x %02x %02x %02x %02x\n" - " MIC: %02x %02x %02x %02x %02x %02x %02x %02x\n", - hs->bMessageNumber, hs->bStatus, - hs->tTKID[2], hs->tTKID[1], hs->tTKID[0], - hs->CDID[0], hs->CDID[1], hs->CDID[2], hs->CDID[3], - hs->CDID[4], hs->CDID[5], hs->CDID[6], hs->CDID[7], - hs->CDID[8], hs->CDID[9], hs->CDID[10], hs->CDID[11], - hs->CDID[12], hs->CDID[13], hs->CDID[14], hs->CDID[15], - hs->nonce[0], hs->nonce[1], hs->nonce[2], hs->nonce[3], - hs->nonce[4], hs->nonce[5], hs->nonce[6], hs->nonce[7], - hs->nonce[8], hs->nonce[9], hs->nonce[10], hs->nonce[11], - hs->nonce[12], hs->nonce[13], hs->nonce[14], hs->nonce[15], - hs->MIC[0], hs->MIC[1], hs->MIC[2], hs->MIC[3], - hs->MIC[4], hs->MIC[5], hs->MIC[6], hs->MIC[7]); -} - -/** - * Update the address of an unauthenticated WUSB device - * - * Once we have successfully authenticated, we take it to addr0 state - * and then to a normal address. - * - * Before the device's address (as known by it) was usb_dev->devnum | - * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum. - */ -static int wusb_dev_update_address(struct wusbhc *wusbhc, - struct wusb_dev *wusb_dev) -{ - int result = -ENOMEM; - struct usb_device *usb_dev = wusb_dev->usb_dev; - struct device *dev = &usb_dev->dev; - u8 new_address = wusb_dev->addr & 0x7F; - - /* Set address 0 */ - result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_ADDRESS, 0, - 0, 0, NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "auth failed: can't set address 0: %d\n", - result); - goto error_addr0; - } - result = wusb_set_dev_addr(wusbhc, wusb_dev, 0); - if (result < 0) - goto error_addr0; - usb_ep0_reinit(usb_dev); - - /* Set new (authenticated) address. */ - result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_ADDRESS, 0, - new_address, 0, NULL, 0, - 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "auth failed: can't set address %u: %d\n", - new_address, result); - goto error_addr; - } - result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address); - if (result < 0) - goto error_addr; - usb_ep0_reinit(usb_dev); - usb_dev->authenticated = 1; -error_addr: -error_addr0: - return result; -} - -/* - * - * - */ -/* FIXME: split and cleanup */ -int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, - struct wusb_ckhdid *ck) -{ - int result = -ENOMEM; - struct usb_device *usb_dev = wusb_dev->usb_dev; - struct device *dev = &usb_dev->dev; - u32 tkid; - __le32 tkid_le; - struct usb_handshake *hs; - struct aes_ccm_nonce ccm_n; - u8 mic[8]; - struct wusb_keydvt_in keydvt_in; - struct wusb_keydvt_out keydvt_out; - - hs = kzalloc(3*sizeof(hs[0]), GFP_KERNEL); - if (hs == NULL) { - dev_err(dev, "can't allocate handshake data\n"); - goto error_kzalloc; - } - - /* We need to turn encryption before beginning the 4way - * hshake (WUSB1.0[.3.2.2]) */ - result = wusb_dev_set_encryption(usb_dev, 1); - if (result < 0) - goto error_dev_set_encryption; - - tkid = wusbhc_next_tkid(wusbhc, wusb_dev); - tkid_le = cpu_to_le32(tkid); - - hs[0].bMessageNumber = 1; - hs[0].bStatus = 0; - memcpy(hs[0].tTKID, &tkid_le, sizeof(hs[0].tTKID)); - hs[0].bReserved = 0; - memcpy(hs[0].CDID, &wusb_dev->cdid, sizeof(hs[0].CDID)); - get_random_bytes(&hs[0].nonce, sizeof(hs[0].nonce)); - memset(hs[0].MIC, 0, sizeof(hs[0].MIC)); /* Per WUSB1.0[T7-22] */ - - d_printf(1, dev, "I: sending hs1:\n"); - hs_printk(2, dev, &hs[0]); - - result = usb_control_msg( - usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_HANDSHAKE, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 1, 0, &hs[0], sizeof(hs[0]), 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Handshake1: request failed: %d\n", result); - goto error_hs1; - } - - /* Handshake 2, from the device -- need to verify fields */ - result = usb_control_msg( - usb_dev, usb_rcvctrlpipe(usb_dev, 0), - USB_REQ_GET_HANDSHAKE, - USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 2, 0, &hs[1], sizeof(hs[1]), 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Handshake2: request failed: %d\n", result); - goto error_hs2; - } - d_printf(1, dev, "got HS2:\n"); - hs_printk(2, dev, &hs[1]); - - result = -EINVAL; - if (hs[1].bMessageNumber != 2) { - dev_err(dev, "Handshake2 failed: bad message number %u\n", - hs[1].bMessageNumber); - goto error_hs2; - } - if (hs[1].bStatus != 0) { - dev_err(dev, "Handshake2 failed: bad status %u\n", - hs[1].bStatus); - goto error_hs2; - } - if (memcmp(hs[0].tTKID, hs[1].tTKID, sizeof(hs[0].tTKID))) { - dev_err(dev, "Handshake2 failed: TKID mismatch " - "(#1 0x%02x%02x%02x vs #2 0x%02x%02x%02x)\n", - hs[0].tTKID[0], hs[0].tTKID[1], hs[0].tTKID[2], - hs[1].tTKID[0], hs[1].tTKID[1], hs[1].tTKID[2]); - goto error_hs2; - } - if (memcmp(hs[0].CDID, hs[1].CDID, sizeof(hs[0].CDID))) { - dev_err(dev, "Handshake2 failed: CDID mismatch\n"); - goto error_hs2; - } - - /* Setup the CCM nonce */ - memset(&ccm_n.sfn, 0, sizeof(ccm_n.sfn)); /* Per WUSB1.0[6.5.2] */ - memcpy(ccm_n.tkid, &tkid_le, sizeof(ccm_n.tkid)); - ccm_n.src_addr = wusbhc->uwb_rc->uwb_dev.dev_addr; - ccm_n.dest_addr.data[0] = wusb_dev->addr; - ccm_n.dest_addr.data[1] = 0; - - /* Derive the KCK and PTK from CK, the CCM, H and D nonces */ - memcpy(keydvt_in.hnonce, hs[0].nonce, sizeof(keydvt_in.hnonce)); - memcpy(keydvt_in.dnonce, hs[1].nonce, sizeof(keydvt_in.dnonce)); - result = wusb_key_derive(&keydvt_out, ck->data, &ccm_n, &keydvt_in); - if (result < 0) { - dev_err(dev, "Handshake2 failed: cannot derive keys: %d\n", - result); - goto error_hs2; - } - d_printf(2, dev, "KCK:\n"); - d_dump(2, dev, keydvt_out.kck, sizeof(keydvt_out.kck)); - d_printf(2, dev, "PTK:\n"); - d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk)); - - /* Compute MIC and verify it */ - result = wusb_oob_mic(mic, keydvt_out.kck, &ccm_n, &hs[1]); - if (result < 0) { - dev_err(dev, "Handshake2 failed: cannot compute MIC: %d\n", - result); - goto error_hs2; - } - - d_printf(2, dev, "MIC:\n"); - d_dump(2, dev, mic, sizeof(mic)); - if (memcmp(hs[1].MIC, mic, sizeof(hs[1].MIC))) { - dev_err(dev, "Handshake2 failed: MIC mismatch\n"); - goto error_hs2; - } - - /* Send Handshake3 */ - hs[2].bMessageNumber = 3; - hs[2].bStatus = 0; - memcpy(hs[2].tTKID, &tkid_le, sizeof(hs[2].tTKID)); - hs[2].bReserved = 0; - memcpy(hs[2].CDID, &wusb_dev->cdid, sizeof(hs[2].CDID)); - memcpy(hs[2].nonce, hs[0].nonce, sizeof(hs[2].nonce)); - result = wusb_oob_mic(hs[2].MIC, keydvt_out.kck, &ccm_n, &hs[2]); - if (result < 0) { - dev_err(dev, "Handshake3 failed: cannot compute MIC: %d\n", - result); - goto error_hs2; - } - - d_printf(1, dev, "I: sending hs3:\n"); - hs_printk(2, dev, &hs[2]); - - result = usb_control_msg( - usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_HANDSHAKE, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 3, 0, &hs[2], sizeof(hs[2]), 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "Handshake3: request failed: %d\n", result); - goto error_hs3; - } - - d_printf(1, dev, "I: turning on encryption on host for device\n"); - d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk)); - result = wusbhc->set_ptk(wusbhc, wusb_dev->port_idx, tkid, - keydvt_out.ptk, sizeof(keydvt_out.ptk)); - if (result < 0) - goto error_wusbhc_set_ptk; - - d_printf(1, dev, "I: setting a GTK\n"); - result = wusb_dev_set_gtk(wusbhc, wusb_dev); - if (result < 0) { - dev_err(dev, "Set GTK for device: request failed: %d\n", - result); - goto error_wusbhc_set_gtk; - } - - /* Update the device's address from unauth to auth */ - if (usb_dev->authenticated == 0) { - d_printf(1, dev, "I: updating addres to auth from non-auth\n"); - result = wusb_dev_update_address(wusbhc, wusb_dev); - if (result < 0) - goto error_dev_update_address; - } - result = 0; - d_printf(1, dev, "I: 4way handshke done, device authenticated\n"); - -error_dev_update_address: -error_wusbhc_set_gtk: -error_wusbhc_set_ptk: -error_hs3: -error_hs2: -error_hs1: - memset(hs, 0, 3*sizeof(hs[0])); - memset(&keydvt_out, 0, sizeof(keydvt_out)); - memset(&keydvt_in, 0, sizeof(keydvt_in)); - memset(&ccm_n, 0, sizeof(ccm_n)); - memset(mic, 0, sizeof(mic)); - if (result < 0) { - /* error path */ - wusb_dev_set_encryption(usb_dev, 0); - } -error_dev_set_encryption: - kfree(hs); -error_kzalloc: - return result; -} - -/* - * Once all connected and authenticated devices have received the new - * GTK, switch the host to using it. - */ -static void wusbhc_gtk_rekey_done_work(struct work_struct *work) -{ - struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work); - size_t key_size = sizeof(wusbhc->gtk.data); - - mutex_lock(&wusbhc->mutex); - - if (--wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); - - mutex_unlock(&wusbhc->mutex); -} - -static void wusbhc_set_gtk_callback(struct urb *urb) -{ - struct wusbhc *wusbhc = urb->context; - - queue_work(wusbd, &wusbhc->gtk_rekey_done_work); -} - -/** - * wusbhc_gtk_rekey - generate and distribute a new GTK - * @wusbhc: the WUSB host controller - * - * Generate a new GTK and distribute it to all connected and - * authenticated devices. When all devices have the new GTK, the host - * starts using it. - * - * This must be called after every device disconnect (see [WUSB] - * section 6.2.11.2). - */ -void wusbhc_gtk_rekey(struct wusbhc *wusbhc) -{ - static const size_t key_size = sizeof(wusbhc->gtk.data); - int p; - - wusbhc_generate_gtk(wusbhc); - - for (p = 0; p < wusbhc->ports_max; p++) { - struct wusb_dev *wusb_dev; - - wusb_dev = wusbhc->port[p].wusb_dev; - if (!wusb_dev || !wusb_dev->usb_dev | !wusb_dev->usb_dev->authenticated) - continue; - - usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev, - usb_sndctrlpipe(wusb_dev->usb_dev, 0), - (void *)wusb_dev->set_gtk_req, - &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, - wusbhc_set_gtk_callback, wusbhc); - if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0) - wusbhc->pending_set_gtks++; - } - if (wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); -} diff --git a/trunk/drivers/usb/wusbcore/wa-hc.c b/trunk/drivers/usb/wusbcore/wa-hc.c deleted file mode 100644 index 9d04722415bb..000000000000 --- a/trunk/drivers/usb/wusbcore/wa-hc.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Wire Adapter Host Controller Driver - * Common items to HWA and DWA based HCDs - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ -#include "wusbhc.h" -#include "wa-hc.h" - -/** - * Assumes - * - * wa->usb_dev and wa->usb_iface initialized and refcounted, - * wa->wa_descr initialized. - */ -int wa_create(struct wahc *wa, struct usb_interface *iface) -{ - int result; - struct device *dev = &iface->dev; - - result = wa_rpipes_create(wa); - if (result < 0) - goto error_rpipes_create; - /* Fill up Data Transfer EP pointers */ - wa->dti_epd = &iface->cur_altsetting->endpoint[1].desc; - wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc; - wa->xfer_result_size = le16_to_cpu(wa->dti_epd->wMaxPacketSize); - wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL); - if (wa->xfer_result == NULL) - goto error_xfer_result_alloc; - result = wa_nep_create(wa, iface); - if (result < 0) { - dev_err(dev, "WA-CDS: can't initialize notif endpoint: %d\n", - result); - goto error_nep_create; - } - return 0; - -error_nep_create: - kfree(wa->xfer_result); -error_xfer_result_alloc: - wa_rpipes_destroy(wa); -error_rpipes_create: - return result; -} -EXPORT_SYMBOL_GPL(wa_create); - - -void __wa_destroy(struct wahc *wa) -{ - if (wa->dti_urb) { - usb_kill_urb(wa->dti_urb); - usb_put_urb(wa->dti_urb); - usb_kill_urb(wa->buf_in_urb); - usb_put_urb(wa->buf_in_urb); - } - kfree(wa->xfer_result); - wa_nep_destroy(wa); - wa_rpipes_destroy(wa); -} -EXPORT_SYMBOL_GPL(__wa_destroy); - -/** - * wa_reset_all - reset the WA device - * @wa: the WA to be reset - * - * For HWAs the radio controller and all other PALs are also reset. - */ -void wa_reset_all(struct wahc *wa) -{ - /* FIXME: assuming HWA. */ - wusbhc_reset_all(wa->wusb); -} - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Wireless USB Wire Adapter core"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/wusbcore/wa-hc.h b/trunk/drivers/usb/wusbcore/wa-hc.h deleted file mode 100644 index 586d350cdb4d..000000000000 --- a/trunk/drivers/usb/wusbcore/wa-hc.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - * HWA Host Controller Driver - * Wire Adapter Control/Data Streaming Iface (WUSB1.0[8]) - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This driver implements a USB Host Controller (struct usb_hcd) for a - * Wireless USB Host Controller based on the Wireless USB 1.0 - * Host-Wire-Adapter specification (in layman terms, a USB-dongle that - * implements a Wireless USB host). - * - * Check out the Design-overview.txt file in the source documentation - * for other details on the implementation. - * - * Main blocks: - * - * driver glue with the driver API, workqueue daemon - * - * lc RC instance life cycle management (create, destroy...) - * - * hcd glue with the USB API Host Controller Interface API. - * - * nep Notification EndPoint managent: collect notifications - * and queue them with the workqueue daemon. - * - * Handle notifications as coming from the NEP. Sends them - * off others to their respective modules (eg: connect, - * disconnect and reset go to devconnect). - * - * rpipe Remote Pipe management; rpipe is what we use to write - * to an endpoint on a WUSB device that is connected to a - * HWA RC. - * - * xfer Transfer managment -- this is all the code that gets a - * buffer and pushes it to a device (or viceversa). * - * - * Some day a lot of this code will be shared between this driver and - * the drivers for DWA (xfer, rpipe). - * - * All starts at driver.c:hwahc_probe(), when one of this guys is - * connected. hwahc_disconnect() stops it. - * - * During operation, the main driver is devices connecting or - * disconnecting. They cause the HWA RC to send notifications into - * nep.c:hwahc_nep_cb() that will dispatch them to - * notif.c:wa_notif_dispatch(). From there they will fan to cause - * device connects, disconnects, etc. - * - * Note much of the activity is difficult to follow. For example a - * device connect goes to devconnect, which will cause the "fake" root - * hub port to show a connect and stop there. Then khubd will notice - * and call into the rh.c:hwahc_rc_port_reset() code to authenticate - * the device (and this might require user intervention) and enable - * the port. - * - * We also have a timer workqueue going from devconnect.c that - * schedules in hwahc_devconnect_create(). - * - * The rest of the traffic is in the usual entry points of a USB HCD, - * which are hooked up in driver.c:hwahc_rc_driver, and defined in - * hcd.c. - */ - -#ifndef __HWAHC_INTERNAL_H__ -#define __HWAHC_INTERNAL_H__ - -#include -#include -#include -#include -#include -#include -#include - -struct wusbhc; -struct wahc; -extern void wa_urb_enqueue_run(struct work_struct *ws); - -/** - * RPipe instance - * - * @descr's fields are kept in LE, as we need to send it back and - * forth. - * - * @wa is referenced when set - * - * @segs_available is the number of requests segments that still can - * be submitted to the controller without overloading - * it. It is initialized to descr->wRequests when - * aiming. - * - * A rpipe supports a max of descr->wRequests at the same time; before - * submitting seg_lock has to be taken. If segs_avail > 0, then we can - * submit; if not, we have to queue them. - */ -struct wa_rpipe { - struct kref refcnt; - struct usb_rpipe_descriptor descr; - struct usb_host_endpoint *ep; - struct wahc *wa; - spinlock_t seg_lock; - struct list_head seg_list; - atomic_t segs_available; - u8 buffer[1]; /* For reads/writes on USB */ -}; - - -/** - * Instance of a HWA Host Controller - * - * Except where a more specific lock/mutex applies or atomic, all - * fields protected by @mutex. - * - * @wa_descr Can be accessed without locking because it is in - * the same area where the device descriptors were - * read, so it is guaranteed to exist umodified while - * the device exists. - * - * Endianess has been converted to CPU's. - * - * @nep_* can be accessed without locking as its processing is - * serialized; we submit a NEP URB and it comes to - * hwahc_nep_cb(), which won't issue another URB until it is - * done processing it. - * - * @xfer_list: - * - * List of active transfers to verify existence from a xfer id - * gotten from the xfer result message. Can't use urb->list because - * it goes by endpoint, and we don't know the endpoint at the time - * when we get the xfer result message. We can't really rely on the - * pointer (will have to change for 64 bits) as the xfer id is 32 bits. - * - * @xfer_delayed_list: List of transfers that need to be started - * (with a workqueue, because they were - * submitted from an atomic context). - * - * FIXME: this needs to be layered up: a wusbhc layer (for sharing - * comonalities with WHCI), a wa layer (for sharing - * comonalities with DWA-RC). - */ -struct wahc { - struct usb_device *usb_dev; - struct usb_interface *usb_iface; - - /* HC to deliver notifications */ - union { - struct wusbhc *wusb; - struct dwahc *dwa; - }; - - const struct usb_endpoint_descriptor *dto_epd, *dti_epd; - const struct usb_wa_descriptor *wa_descr; - - struct urb *nep_urb; /* Notification EndPoint [lockless] */ - struct edc nep_edc; - void *nep_buffer; - size_t nep_buffer_size; - - atomic_t notifs_queued; - - u16 rpipes; - unsigned long *rpipe_bm; /* rpipe usage bitmap */ - spinlock_t rpipe_bm_lock; /* protect rpipe_bm */ - struct mutex rpipe_mutex; /* assigning resources to endpoints */ - - struct urb *dti_urb; /* URB for reading xfer results */ - struct urb *buf_in_urb; /* URB for reading data in */ - struct edc dti_edc; /* DTI error density counter */ - struct wa_xfer_result *xfer_result; /* real size = dti_ep maxpktsize */ - size_t xfer_result_size; - - s32 status; /* For reading status */ - - struct list_head xfer_list; - struct list_head xfer_delayed_list; - spinlock_t xfer_list_lock; - struct work_struct xfer_work; - atomic_t xfer_id_count; -}; - - -extern int wa_create(struct wahc *wa, struct usb_interface *iface); -extern void __wa_destroy(struct wahc *wa); -void wa_reset_all(struct wahc *wa); - - -/* Miscellaneous constants */ -enum { - /** Max number of EPROTO errors we tolerate on the NEP in a - * period of time */ - HWAHC_EPROTO_MAX = 16, - /** Period of time for EPROTO errors (in jiffies) */ - HWAHC_EPROTO_PERIOD = 4 * HZ, -}; - - -/* Notification endpoint handling */ -extern int wa_nep_create(struct wahc *, struct usb_interface *); -extern void wa_nep_destroy(struct wahc *); - -static inline int wa_nep_arm(struct wahc *wa, gfp_t gfp_mask) -{ - struct urb *urb = wa->nep_urb; - urb->transfer_buffer = wa->nep_buffer; - urb->transfer_buffer_length = wa->nep_buffer_size; - return usb_submit_urb(urb, gfp_mask); -} - -static inline void wa_nep_disarm(struct wahc *wa) -{ - usb_kill_urb(wa->nep_urb); -} - - -/* RPipes */ -static inline void wa_rpipe_init(struct wahc *wa) -{ - spin_lock_init(&wa->rpipe_bm_lock); - mutex_init(&wa->rpipe_mutex); -} - -static inline void wa_init(struct wahc *wa) -{ - edc_init(&wa->nep_edc); - atomic_set(&wa->notifs_queued, 0); - wa_rpipe_init(wa); - edc_init(&wa->dti_edc); - INIT_LIST_HEAD(&wa->xfer_list); - INIT_LIST_HEAD(&wa->xfer_delayed_list); - spin_lock_init(&wa->xfer_list_lock); - INIT_WORK(&wa->xfer_work, wa_urb_enqueue_run); - atomic_set(&wa->xfer_id_count, 1); -} - -/** - * Destroy a pipe (when refcount drops to zero) - * - * Assumes it has been moved to the "QUIESCING" state. - */ -struct wa_xfer; -extern void rpipe_destroy(struct kref *_rpipe); -static inline -void __rpipe_get(struct wa_rpipe *rpipe) -{ - kref_get(&rpipe->refcnt); -} -extern int rpipe_get_by_ep(struct wahc *, struct usb_host_endpoint *, - struct urb *, gfp_t); -static inline void rpipe_put(struct wa_rpipe *rpipe) -{ - kref_put(&rpipe->refcnt, rpipe_destroy); - -} -extern void rpipe_ep_disable(struct wahc *, struct usb_host_endpoint *); -extern int wa_rpipes_create(struct wahc *); -extern void wa_rpipes_destroy(struct wahc *); -static inline void rpipe_avail_dec(struct wa_rpipe *rpipe) -{ - atomic_dec(&rpipe->segs_available); -} - -/** - * Returns true if the rpipe is ready to submit more segments. - */ -static inline int rpipe_avail_inc(struct wa_rpipe *rpipe) -{ - return atomic_inc_return(&rpipe->segs_available) > 0 - && !list_empty(&rpipe->seg_list); -} - - -/* Transferring data */ -extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *, - struct urb *, gfp_t); -extern int wa_urb_dequeue(struct wahc *, struct urb *); -extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *); - - -/* Misc - * - * FIXME: Refcounting for the actual @hwahc object is not correct; I - * mean, this should be refcounting on the HCD underneath, but - * it is not. In any case, the semantics for HCD refcounting - * are *weird*...on refcount reaching zero it just frees - * it...no RC specific function is called...unless I miss - * something. - * - * FIXME: has to go away in favour of an 'struct' hcd based sollution - */ -static inline struct wahc *wa_get(struct wahc *wa) -{ - usb_get_intf(wa->usb_iface); - return wa; -} - -static inline void wa_put(struct wahc *wa) -{ - usb_put_intf(wa->usb_iface); -} - - -static inline int __wa_feature(struct wahc *wa, unsigned op, u16 feature) -{ - return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - op ? USB_REQ_SET_FEATURE : USB_REQ_CLEAR_FEATURE, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - feature, - wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 1000 /* FIXME: arbitrary */); -} - - -static inline int __wa_set_feature(struct wahc *wa, u16 feature) -{ - return __wa_feature(wa, 1, feature); -} - - -static inline int __wa_clear_feature(struct wahc *wa, u16 feature) -{ - return __wa_feature(wa, 0, feature); -} - - -/** - * Return the status of a Wire Adapter - * - * @wa: Wire Adapter instance - * @returns < 0 errno code on error, or status bitmap as described - * in WUSB1.0[8.3.1.6]. - * - * NOTE: need malloc, some arches don't take USB from the stack - */ -static inline -s32 __wa_get_status(struct wahc *wa) -{ - s32 result; - result = usb_control_msg( - wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, - &wa->status, sizeof(wa->status), - 1000 /* FIXME: arbitrary */); - if (result >= 0) - result = wa->status; - return result; -} - - -/** - * Waits until the Wire Adapter's status matches @mask/@value - * - * @wa: Wire Adapter instance. - * @returns < 0 errno code on error, otherwise status. - * - * Loop until the WAs status matches the mask and value (status & mask - * == value). Timeout if it doesn't happen. - * - * FIXME: is there an official specification on how long status - * changes can take? - */ -static inline s32 __wa_wait_status(struct wahc *wa, u32 mask, u32 value) -{ - s32 result; - unsigned loops = 10; - do { - msleep(50); - result = __wa_get_status(wa); - if ((result & mask) == value) - break; - if (loops-- == 0) { - result = -ETIMEDOUT; - break; - } - } while (result >= 0); - return result; -} - - -/** Command @hwahc to stop, @returns 0 if ok, < 0 errno code on error */ -static inline int __wa_stop(struct wahc *wa) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - - result = __wa_clear_feature(wa, WA_ENABLE); - if (result < 0 && result != -ENODEV) { - dev_err(dev, "error commanding HC to stop: %d\n", result); - goto out; - } - result = __wa_wait_status(wa, WA_ENABLE, 0); - if (result < 0 && result != -ENODEV) - dev_err(dev, "error waiting for HC to stop: %d\n", result); -out: - return 0; -} - - -#endif /* #ifndef __HWAHC_INTERNAL_H__ */ diff --git a/trunk/drivers/usb/wusbcore/wa-nep.c b/trunk/drivers/usb/wusbcore/wa-nep.c deleted file mode 100644 index 3f542990c73f..000000000000 --- a/trunk/drivers/usb/wusbcore/wa-nep.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * WUSB Wire Adapter: Control/Data Streaming Interface (WUSB[8]) - * Notification EndPoint support - * - * Copyright (C) 2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This part takes care of getting the notification from the hw - * only and dispatching through wusbwad into - * wa_notif_dispatch. Handling is done there. - * - * WA notifications are limited in size; most of them are three or - * four bytes long, and the longest is the HWA Device Notification, - * which would not exceed 38 bytes (DNs are limited in payload to 32 - * bytes plus 3 bytes header (WUSB1.0[7.6p2]), plus 3 bytes HWA - * header (WUSB1.0[8.5.4.2]). - * - * It is not clear if more than one Device Notification can be packed - * in a HWA Notification, I assume no because of the wording in - * WUSB1.0[8.5.4.2]. In any case, the bigger any notification could - * get is 256 bytes (as the bLength field is a byte). - * - * So what we do is we have this buffer and read into it; when a - * notification arrives we schedule work to a specific, single thread - * workqueue (so notifications are serialized) and copy the - * notification data. After scheduling the work, we rearm the read from - * the notification endpoint. - * - * Entry points here are: - * - * wa_nep_[create|destroy]() To initialize/release this subsystem - * - * wa_nep_cb() Callback for the notification - * endpoint; when data is ready, this - * does the dispatching. - */ -#include -#include -#include -#include "wa-hc.h" -#include "wusbhc.h" - -/* Structure for queueing notifications to the workqueue */ -struct wa_notif_work { - struct work_struct work; - struct wahc *wa; - size_t size; - u8 data[]; -}; - -/* - * Process incoming notifications from the WA's Notification EndPoint - * [the wuswad daemon, basically] - * - * @_nw: Pointer to a descriptor which has the pointer to the - * @wa, the size of the buffer and the work queue - * structure (so we can free all when done). - * @returns 0 if ok, < 0 errno code on error. - * - * All notifications follow the same format; they need to start with a - * 'struct wa_notif_hdr' header, so it is easy to parse through - * them. We just break the buffer in individual notifications (the - * standard doesn't say if it can be done or is forbidden, so we are - * cautious) and dispatch each. - * - * So the handling layers are is: - * - * WA specific notification (from NEP) - * Device Notification Received -> wa_handle_notif_dn() - * WUSB Device notification generic handling - * BPST Adjustment -> wa_handle_notif_bpst_adj() - * ... -> ... - * - * @wa has to be referenced - */ -static void wa_notif_dispatch(struct work_struct *ws) -{ - void *itr; - u8 missing = 0; - struct wa_notif_work *nw = container_of(ws, struct wa_notif_work, work); - struct wahc *wa = nw->wa; - struct wa_notif_hdr *notif_hdr; - size_t size; - - struct device *dev = &wa->usb_iface->dev; - -#if 0 - /* FIXME: need to check for this??? */ - if (usb_hcd->state == HC_STATE_QUIESCING) /* Going down? */ - goto out; /* screw it */ -#endif - atomic_dec(&wa->notifs_queued); /* Throttling ctl */ - dev = &wa->usb_iface->dev; - size = nw->size; - itr = nw->data; - - while (size) { - if (size < sizeof(*notif_hdr)) { - missing = sizeof(*notif_hdr) - size; - goto exhausted_buffer; - } - notif_hdr = itr; - if (size < notif_hdr->bLength) - goto exhausted_buffer; - itr += notif_hdr->bLength; - size -= notif_hdr->bLength; - /* Dispatch the notification [don't use itr or size!] */ - switch (notif_hdr->bNotifyType) { - case HWA_NOTIF_DN: { - struct hwa_notif_dn *hwa_dn; - hwa_dn = container_of(notif_hdr, struct hwa_notif_dn, - hdr); - wusbhc_handle_dn(wa->wusb, hwa_dn->bSourceDeviceAddr, - hwa_dn->dndata, - notif_hdr->bLength - sizeof(*hwa_dn)); - break; - } - case WA_NOTIF_TRANSFER: - wa_handle_notif_xfer(wa, notif_hdr); - break; - case DWA_NOTIF_RWAKE: - case DWA_NOTIF_PORTSTATUS: - case HWA_NOTIF_BPST_ADJ: - /* FIXME: unimplemented WA NOTIFs */ - /* fallthru */ - default: - if (printk_ratelimit()) { - dev_err(dev, "HWA: unknown notification 0x%x, " - "%zu bytes; discarding\n", - notif_hdr->bNotifyType, - (size_t)notif_hdr->bLength); - dump_bytes(dev, notif_hdr, 16); - } - break; - } - } -out: - wa_put(wa); - kfree(nw); - return; - - /* THIS SHOULD NOT HAPPEN - * - * Buffer exahusted with partial data remaining; just warn and - * discard the data, as this should not happen. - */ -exhausted_buffer: - if (!printk_ratelimit()) - goto out; - dev_warn(dev, "HWA: device sent short notification, " - "%d bytes missing; discarding %d bytes.\n", - missing, (int)size); - dump_bytes(dev, itr, size); - goto out; -} - -/* - * Deliver incoming WA notifications to the wusbwa workqueue - * - * @wa: Pointer the Wire Adapter Controller Data Streaming - * instance (part of an 'struct usb_hcd'). - * @size: Size of the received buffer - * @returns 0 if ok, < 0 errno code on error. - * - * The input buffer is @wa->nep_buffer, with @size bytes - * (guaranteed to fit in the allocated space, - * @wa->nep_buffer_size). - */ -static int wa_nep_queue(struct wahc *wa, size_t size) -{ - int result = 0; - struct device *dev = &wa->usb_iface->dev; - struct wa_notif_work *nw; - - /* dev_fnstart(dev, "(wa %p, size %zu)\n", wa, size); */ - BUG_ON(size > wa->nep_buffer_size); - if (size == 0) - goto out; - if (atomic_read(&wa->notifs_queued) > 200) { - if (printk_ratelimit()) - dev_err(dev, "Too many notifications queued, " - "throttling back\n"); - goto out; - } - nw = kzalloc(sizeof(*nw) + size, GFP_ATOMIC); - if (nw == NULL) { - if (printk_ratelimit()) - dev_err(dev, "No memory to queue notification\n"); - goto out; - } - INIT_WORK(&nw->work, wa_notif_dispatch); - nw->wa = wa_get(wa); - nw->size = size; - memcpy(nw->data, wa->nep_buffer, size); - atomic_inc(&wa->notifs_queued); /* Throttling ctl */ - queue_work(wusbd, &nw->work); -out: - /* dev_fnend(dev, "(wa %p, size %zu) = result\n", wa, size, result); */ - return result; -} - -/* - * Callback for the notification event endpoint - * - * Check's that everything is fine and then passes the data to be - * queued to the workqueue. - */ -static void wa_nep_cb(struct urb *urb) -{ - int result; - struct wahc *wa = urb->context; - struct device *dev = &wa->usb_iface->dev; - - switch (result = urb->status) { - case 0: - result = wa_nep_queue(wa, urb->actual_length); - if (result < 0) - dev_err(dev, "NEP: unable to process notification(s): " - "%d\n", result); - break; - case -ECONNRESET: /* Not an error, but a controlled situation; */ - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - case -ESHUTDOWN: - dev_dbg(dev, "NEP: going down %d\n", urb->status); - goto out; - default: /* On general errors, we retry unless it gets ugly */ - if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "NEP: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - goto out; - } - dev_err(dev, "NEP: URB error %d\n", urb->status); - } - result = wa_nep_arm(wa, GFP_ATOMIC); - if (result < 0) { - dev_err(dev, "NEP: cannot submit URB: %d\n", result); - wa_reset_all(wa); - } -out: - return; -} - -/* - * Initialize @wa's notification and event's endpoint stuff - * - * This includes the allocating the read buffer, the context ID - * allocation bitmap, the URB and submitting the URB. - */ -int wa_nep_create(struct wahc *wa, struct usb_interface *iface) -{ - int result; - struct usb_endpoint_descriptor *epd; - struct usb_device *usb_dev = interface_to_usbdev(iface); - struct device *dev = &iface->dev; - - edc_init(&wa->nep_edc); - epd = &iface->cur_altsetting->endpoint[0].desc; - wa->nep_buffer_size = 1024; - wa->nep_buffer = kmalloc(wa->nep_buffer_size, GFP_KERNEL); - if (wa->nep_buffer == NULL) { - dev_err(dev, "Unable to allocate notification's read buffer\n"); - goto error_nep_buffer; - } - wa->nep_urb = usb_alloc_urb(0, GFP_KERNEL); - if (wa->nep_urb == NULL) { - dev_err(dev, "Unable to allocate notification URB\n"); - goto error_urb_alloc; - } - usb_fill_int_urb(wa->nep_urb, usb_dev, - usb_rcvintpipe(usb_dev, epd->bEndpointAddress), - wa->nep_buffer, wa->nep_buffer_size, - wa_nep_cb, wa, epd->bInterval); - result = wa_nep_arm(wa, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "Cannot submit notification URB: %d\n", result); - goto error_nep_arm; - } - return 0; - -error_nep_arm: - usb_free_urb(wa->nep_urb); -error_urb_alloc: - kfree(wa->nep_buffer); -error_nep_buffer: - return -ENOMEM; -} - -void wa_nep_destroy(struct wahc *wa) -{ - wa_nep_disarm(wa); - usb_free_urb(wa->nep_urb); - kfree(wa->nep_buffer); -} diff --git a/trunk/drivers/usb/wusbcore/wa-rpipe.c b/trunk/drivers/usb/wusbcore/wa-rpipe.c deleted file mode 100644 index f18e4aae66e9..000000000000 --- a/trunk/drivers/usb/wusbcore/wa-rpipe.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * WUSB Wire Adapter - * rpipe management - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * RPIPE - * - * Targetted at different downstream endpoints - * - * Descriptor: use to config the remote pipe. - * - * The number of blocks could be dynamic (wBlocks in descriptor is - * 0)--need to schedule them then. - * - * Each bit in wa->rpipe_bm represents if an rpipe is being used or - * not. Rpipes are represented with a 'struct wa_rpipe' that is - * attached to the hcpriv member of a 'struct usb_host_endpoint'. - * - * When you need to xfer data to an endpoint, you get an rpipe for it - * with wa_ep_rpipe_get(), which gives you a reference to the rpipe - * and keeps a single one (the first one) with the endpoint. When you - * are done transferring, you drop that reference. At the end the - * rpipe is always allocated and bound to the endpoint. There it might - * be recycled when not used. - * - * Addresses: - * - * We use a 1:1 mapping mechanism between port address (0 based - * index, actually) and the address. The USB stack knows about this. - * - * USB Stack port number 4 (1 based) - * WUSB code port index 3 (0 based) - * USB Addresss 5 (2 based -- 0 is for default, 1 for root hub) - * - * Now, because we don't use the concept as default address exactly - * like the (wired) USB code does, we need to kind of skip it. So we - * never take addresses from the urb->pipe, but from the - * urb->dev->devnum, to make sure that we always have the right - * destination address. - */ -#include -#include -#include -#include "wusbhc.h" -#include "wa-hc.h" - -#define D_LOCAL 0 -#include - - -static int __rpipe_get_descr(struct wahc *wa, - struct usb_rpipe_descriptor *descr, u16 index) -{ - ssize_t result; - struct device *dev = &wa->usb_iface->dev; - - /* Get the RPIPE descriptor -- we cannot use the usb_get_descriptor() - * function because the arguments are different. - */ - d_printf(1, dev, "rpipe %u: get descr\n", index); - result = usb_control_msg( - wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), - USB_REQ_GET_DESCRIPTOR, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_RPIPE, - USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - 1000 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(dev, "rpipe %u: get descriptor failed: %d\n", - index, (int)result); - goto error; - } - if (result < sizeof(*descr)) { - dev_err(dev, "rpipe %u: got short descriptor " - "(%zd vs %zd bytes needed)\n", - index, result, sizeof(*descr)); - result = -EINVAL; - goto error; - } - result = 0; - -error: - return result; -} - -/* - * - * The descriptor is assumed to be properly initialized (ie: you got - * it through __rpipe_get_descr()). - */ -static int __rpipe_set_descr(struct wahc *wa, - struct usb_rpipe_descriptor *descr, u16 index) -{ - ssize_t result; - struct device *dev = &wa->usb_iface->dev; - - /* we cannot use the usb_get_descriptor() function because the - * arguments are different. - */ - d_printf(1, dev, "rpipe %u: set descr\n", index); - result = usb_control_msg( - wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - USB_REQ_SET_DESCRIPTOR, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - HZ / 10); - if (result < 0) { - dev_err(dev, "rpipe %u: set descriptor failed: %d\n", - index, (int)result); - goto error; - } - if (result < sizeof(*descr)) { - dev_err(dev, "rpipe %u: sent short descriptor " - "(%zd vs %zd bytes required)\n", - index, result, sizeof(*descr)); - result = -EINVAL; - goto error; - } - result = 0; - -error: - return result; - -} - -static void rpipe_init(struct wa_rpipe *rpipe) -{ - kref_init(&rpipe->refcnt); - spin_lock_init(&rpipe->seg_lock); - INIT_LIST_HEAD(&rpipe->seg_list); -} - -static unsigned rpipe_get_idx(struct wahc *wa, unsigned rpipe_idx) -{ - unsigned long flags; - - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); - rpipe_idx = find_next_zero_bit(wa->rpipe_bm, wa->rpipes, rpipe_idx); - if (rpipe_idx < wa->rpipes) - set_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); - - return rpipe_idx; -} - -static void rpipe_put_idx(struct wahc *wa, unsigned rpipe_idx) -{ - unsigned long flags; - - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); - clear_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); -} - -void rpipe_destroy(struct kref *_rpipe) -{ - struct wa_rpipe *rpipe = container_of(_rpipe, struct wa_rpipe, refcnt); - u8 index = le16_to_cpu(rpipe->descr.wRPipeIndex); - d_fnstart(1, NULL, "(rpipe %p %u)\n", rpipe, index); - if (rpipe->ep) - rpipe->ep->hcpriv = NULL; - rpipe_put_idx(rpipe->wa, index); - wa_put(rpipe->wa); - kfree(rpipe); - d_fnend(1, NULL, "(rpipe %p %u)\n", rpipe, index); -} -EXPORT_SYMBOL_GPL(rpipe_destroy); - -/* - * Locate an idle rpipe, create an structure for it and return it - * - * @wa is referenced and unlocked - * @crs enum rpipe_attr, required endpoint characteristics - * - * The rpipe can be used only sequentially (not in parallel). - * - * The rpipe is moved into the "ready" state. - */ -static int rpipe_get_idle(struct wa_rpipe **prpipe, struct wahc *wa, u8 crs, - gfp_t gfp) -{ - int result; - unsigned rpipe_idx; - struct wa_rpipe *rpipe; - struct device *dev = &wa->usb_iface->dev; - - d_fnstart(3, dev, "(wa %p crs 0x%02x)\n", wa, crs); - rpipe = kzalloc(sizeof(*rpipe), gfp); - if (rpipe == NULL) - return -ENOMEM; - rpipe_init(rpipe); - - /* Look for an idle pipe */ - for (rpipe_idx = 0; rpipe_idx < wa->rpipes; rpipe_idx++) { - rpipe_idx = rpipe_get_idx(wa, rpipe_idx); - if (rpipe_idx >= wa->rpipes) /* no more pipes :( */ - break; - result = __rpipe_get_descr(wa, &rpipe->descr, rpipe_idx); - if (result < 0) - dev_err(dev, "Can't get descriptor for rpipe %u: %d\n", - rpipe_idx, result); - else if ((rpipe->descr.bmCharacteristics & crs) != 0) - goto found; - rpipe_put_idx(wa, rpipe_idx); - } - *prpipe = NULL; - kfree(rpipe); - d_fnend(3, dev, "(wa %p crs 0x%02x) = -ENXIO\n", wa, crs); - return -ENXIO; - -found: - set_bit(rpipe_idx, wa->rpipe_bm); - rpipe->wa = wa_get(wa); - *prpipe = rpipe; - d_fnstart(3, dev, "(wa %p crs 0x%02x) = 0\n", wa, crs); - return 0; -} - -static int __rpipe_reset(struct wahc *wa, unsigned index) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - - d_printf(1, dev, "rpipe %u: reset\n", index); - result = usb_control_msg( - wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), - USB_REQ_RPIPE_RESET, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0) - dev_err(dev, "rpipe %u: reset failed: %d\n", - index, result); - return result; -} - -/* - * Fake companion descriptor for ep0 - * - * See WUSB1.0[7.4.4], most of this is zero for bulk/int/ctl - */ -static struct usb_wireless_ep_comp_descriptor epc0 = { - .bLength = sizeof(epc0), - .bDescriptorType = USB_DT_WIRELESS_ENDPOINT_COMP, -/* .bMaxBurst = 1, */ - .bMaxSequence = 31, -}; - -/* - * Look for EP companion descriptor - * - * Get there, look for Inara in the endpoint's extra descriptors - */ -static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find( - struct device *dev, struct usb_host_endpoint *ep) -{ - void *itr; - size_t itr_size; - struct usb_descriptor_header *hdr; - struct usb_wireless_ep_comp_descriptor *epcd; - - d_fnstart(3, dev, "(ep %p)\n", ep); - if (ep->desc.bEndpointAddress == 0) { - epcd = &epc0; - goto out; - } - itr = ep->extra; - itr_size = ep->extralen; - epcd = NULL; - while (itr_size > 0) { - if (itr_size < sizeof(*hdr)) { - dev_err(dev, "HW Bug? ep 0x%02x: extra descriptors " - "at offset %zu: only %zu bytes left\n", - ep->desc.bEndpointAddress, - itr - (void *) ep->extra, itr_size); - break; - } - hdr = itr; - if (hdr->bDescriptorType == USB_DT_WIRELESS_ENDPOINT_COMP) { - epcd = itr; - break; - } - if (hdr->bLength > itr_size) { - dev_err(dev, "HW Bug? ep 0x%02x: extra descriptor " - "at offset %zu (type 0x%02x) " - "length %d but only %zu bytes left\n", - ep->desc.bEndpointAddress, - itr - (void *) ep->extra, hdr->bDescriptorType, - hdr->bLength, itr_size); - break; - } - itr += hdr->bLength; - itr_size -= hdr->bDescriptorType; - } -out: - d_fnend(3, dev, "(ep %p) = %p\n", ep, epcd); - return epcd; -} - -/* - * Aim an rpipe to its device & endpoint destination - * - * Make sure we change the address to unauthenticathed if the device - * is WUSB and it is not authenticated. - */ -static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, - struct usb_host_endpoint *ep, struct urb *urb, gfp_t gfp) -{ - int result = -ENOMSG; /* better code for lack of companion? */ - struct device *dev = &wa->usb_iface->dev; - struct usb_device *usb_dev = urb->dev; - struct usb_wireless_ep_comp_descriptor *epcd; - u8 unauth; - - d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n", - rpipe, wa, ep, urb); - epcd = rpipe_epc_find(dev, ep); - if (epcd == NULL) { - dev_err(dev, "ep 0x%02x: can't find companion descriptor\n", - ep->desc.bEndpointAddress); - goto error; - } - unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0; - __rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex)); - atomic_set(&rpipe->segs_available, le16_to_cpu(rpipe->descr.wRequests)); - /* FIXME: block allocation system; request with queuing and timeout */ - /* FIXME: compute so seg_size > ep->maxpktsize */ - rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ - /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ - rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize); - rpipe->descr.bHSHubAddress = 0; /* reserved: zero */ - rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum); - /* FIXME: use maximum speed as supported or recommended by device */ - rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? - UWB_PHY_RATE_53 : UWB_PHY_RATE_200; - d_printf(2, dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n", - urb->dev->devnum, urb->dev->devnum | unauth, - le16_to_cpu(rpipe->descr.wRPipeIndex), - usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); - /* see security.c:wusb_update_address() */ - if (unlikely(urb->dev->devnum == 0x80)) - rpipe->descr.bDeviceAddress = 0; - else - rpipe->descr.bDeviceAddress = urb->dev->devnum | unauth; - rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; - /* FIXME: bDataSequence */ - rpipe->descr.bDataSequence = 0; - /* FIXME: dwCurrentWindow */ - rpipe->descr.dwCurrentWindow = cpu_to_le32(1); - /* FIXME: bMaxDataSequence */ - rpipe->descr.bMaxDataSequence = epcd->bMaxSequence - 1; - rpipe->descr.bInterval = ep->desc.bInterval; - /* FIXME: bOverTheAirInterval */ - rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ - /* FIXME: xmit power & preamble blah blah */ - rpipe->descr.bmAttribute = ep->desc.bmAttributes & 0x03; - /* rpipe->descr.bmCharacteristics RO */ - /* FIXME: bmRetryOptions */ - rpipe->descr.bmRetryOptions = 15; - /* FIXME: use for assessing link quality? */ - rpipe->descr.wNumTransactionErrors = 0; - result = __rpipe_set_descr(wa, &rpipe->descr, - le16_to_cpu(rpipe->descr.wRPipeIndex)); - if (result < 0) { - dev_err(dev, "Cannot aim rpipe: %d\n", result); - goto error; - } - result = 0; -error: - d_fnend(3, dev, "(rpipe %p wa %p ep %p urb %p) = %d\n", - rpipe, wa, ep, urb, result); - return result; -} - -/* - * Check an aimed rpipe to make sure it points to where we want - * - * We use bit 19 of the Linux USB pipe bitmap for unauth vs auth - * space; when it is like that, we or 0x80 to make an unauth address. - */ -static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, - const struct usb_host_endpoint *ep, - const struct urb *urb, gfp_t gfp) -{ - int result = 0; /* better code for lack of companion? */ - struct device *dev = &wa->usb_iface->dev; - struct usb_device *usb_dev = urb->dev; - u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; - u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); - - d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n", - rpipe, wa, ep, urb); -#define AIM_CHECK(rdf, val, text) \ - do { \ - if (rpipe->descr.rdf != (val)) { \ - dev_err(dev, \ - "rpipe aim discrepancy: " #rdf " " text "\n", \ - rpipe->descr.rdf, (val)); \ - result = -EINVAL; \ - WARN_ON(1); \ - } \ - } while (0) - AIM_CHECK(wMaxPacketSize, cpu_to_le16(ep->desc.wMaxPacketSize), - "(%u vs %u)"); - AIM_CHECK(bHSHubPort, portnum, "(%u vs %u)"); - AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? - UWB_PHY_RATE_53 : UWB_PHY_RATE_200, - "(%u vs %u)"); - AIM_CHECK(bDeviceAddress, urb->dev->devnum | unauth, "(%u vs %u)"); - AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); - AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); - AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); -#undef AIM_CHECK - return result; -} - -#ifndef CONFIG_BUG -#define CONFIG_BUG 0 -#endif - -/* - * Make sure there is an rpipe allocated for an endpoint - * - * If already allocated, we just refcount it; if not, we get an - * idle one, aim it to the right location and take it. - * - * Attaches to ep->hcpriv and rpipe->ep to ep. - */ -int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep, - struct urb *urb, gfp_t gfp) -{ - int result = 0; - struct device *dev = &wa->usb_iface->dev; - struct wa_rpipe *rpipe; - u8 eptype; - - d_fnstart(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb, - gfp); - mutex_lock(&wa->rpipe_mutex); - rpipe = ep->hcpriv; - if (rpipe != NULL) { - if (CONFIG_BUG == 1) { - result = rpipe_check_aim(rpipe, wa, ep, urb, gfp); - if (result < 0) - goto error; - } - __rpipe_get(rpipe); - d_printf(2, dev, "ep 0x%02x: reusing rpipe %u\n", - ep->desc.bEndpointAddress, - le16_to_cpu(rpipe->descr.wRPipeIndex)); - } else { - /* hmm, assign idle rpipe, aim it */ - result = -ENOBUFS; - eptype = ep->desc.bmAttributes & 0x03; - result = rpipe_get_idle(&rpipe, wa, 1 << eptype, gfp); - if (result < 0) - goto error; - result = rpipe_aim(rpipe, wa, ep, urb, gfp); - if (result < 0) { - rpipe_put(rpipe); - goto error; - } - ep->hcpriv = rpipe; - rpipe->ep = ep; - __rpipe_get(rpipe); /* for caching into ep->hcpriv */ - d_printf(2, dev, "ep 0x%02x: using rpipe %u\n", - ep->desc.bEndpointAddress, - le16_to_cpu(rpipe->descr.wRPipeIndex)); - } - d_dump(4, dev, &rpipe->descr, sizeof(rpipe->descr)); -error: - mutex_unlock(&wa->rpipe_mutex); - d_fnend(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb, gfp); - return result; -} - -/* - * Allocate the bitmap for each rpipe. - */ -int wa_rpipes_create(struct wahc *wa) -{ - wa->rpipes = wa->wa_descr->wNumRPipes; - wa->rpipe_bm = kzalloc(BITS_TO_LONGS(wa->rpipes)*sizeof(unsigned long), - GFP_KERNEL); - if (wa->rpipe_bm == NULL) - return -ENOMEM; - return 0; -} - -void wa_rpipes_destroy(struct wahc *wa) -{ - struct device *dev = &wa->usb_iface->dev; - d_fnstart(3, dev, "(wa %p)\n", wa); - if (!bitmap_empty(wa->rpipe_bm, wa->rpipes)) { - char buf[256]; - WARN_ON(1); - bitmap_scnprintf(buf, sizeof(buf), wa->rpipe_bm, wa->rpipes); - dev_err(dev, "BUG: pipes not released on exit: %s\n", buf); - } - kfree(wa->rpipe_bm); - d_fnend(3, dev, "(wa %p)\n", wa); -} - -/* - * Release resources allocated for an endpoint - * - * If there is an associated rpipe to this endpoint, Abort any pending - * transfers and put it. If the rpipe ends up being destroyed, - * __rpipe_destroy() will cleanup ep->hcpriv. - * - * This is called before calling hcd->stop(), so you don't need to do - * anything else in there. - */ -void rpipe_ep_disable(struct wahc *wa, struct usb_host_endpoint *ep) -{ - struct device *dev = &wa->usb_iface->dev; - struct wa_rpipe *rpipe; - d_fnstart(2, dev, "(wa %p ep %p)\n", wa, ep); - mutex_lock(&wa->rpipe_mutex); - rpipe = ep->hcpriv; - if (rpipe != NULL) { - unsigned rc = atomic_read(&rpipe->refcnt.refcount); - int result; - u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex); - - if (rc != 1) - d_printf(1, dev, "(wa %p ep %p) rpipe %p refcnt %u\n", - wa, ep, rpipe, rc); - - d_printf(1, dev, "rpipe %u: abort\n", index); - result = usb_control_msg( - wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), - USB_REQ_RPIPE_ABORT, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); - if (result < 0 && result != -ENODEV /* dev is gone */) - d_printf(1, dev, "(wa %p rpipe %u): abort failed: %d\n", - wa, index, result); - rpipe_put(rpipe); - } - mutex_unlock(&wa->rpipe_mutex); - d_fnend(2, dev, "(wa %p ep %p)\n", wa, ep); - return; -} -EXPORT_SYMBOL_GPL(rpipe_ep_disable); diff --git a/trunk/drivers/usb/wusbcore/wa-xfer.c b/trunk/drivers/usb/wusbcore/wa-xfer.c deleted file mode 100644 index c038635d1c64..000000000000 --- a/trunk/drivers/usb/wusbcore/wa-xfer.c +++ /dev/null @@ -1,1709 +0,0 @@ -/* - * WUSB Wire Adapter - * Data transfer and URB enqueing - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * How transfers work: get a buffer, break it up in segments (segment - * size is a multiple of the maxpacket size). For each segment issue a - * segment request (struct wa_xfer_*), then send the data buffer if - * out or nothing if in (all over the DTO endpoint). - * - * For each submitted segment request, a notification will come over - * the NEP endpoint and a transfer result (struct xfer_result) will - * arrive in the DTI URB. Read it, get the xfer ID, see if there is - * data coming (inbound transfer), schedule a read and handle it. - * - * Sounds simple, it is a pain to implement. - * - * - * ENTRY POINTS - * - * FIXME - * - * LIFE CYCLE / STATE DIAGRAM - * - * FIXME - * - * THIS CODE IS DISGUSTING - * - * Warned you are; it's my second try and still not happy with it. - * - * NOTES: - * - * - No iso - * - * - Supports DMA xfers, control, bulk and maybe interrupt - * - * - Does not recycle unused rpipes - * - * An rpipe is assigned to an endpoint the first time it is used, - * and then it's there, assigned, until the endpoint is disabled - * (destroyed [{h,d}wahc_op_ep_disable()]. The assignment of the - * rpipe to the endpoint is done under the wa->rpipe_sem semaphore - * (should be a mutex). - * - * Two methods it could be done: - * - * (a) set up a timer everytime an rpipe's use count drops to 1 - * (which means unused) or when a transfer ends. Reset the - * timer when a xfer is queued. If the timer expires, release - * the rpipe [see rpipe_ep_disable()]. - * - * (b) when looking for free rpipes to attach [rpipe_get_by_ep()], - * when none are found go over the list, check their endpoint - * and their activity record (if no last-xfer-done-ts in the - * last x seconds) take it - * - * However, due to the fact that we have a set of limited - * resources (max-segments-at-the-same-time per xfer, - * xfers-per-ripe, blocks-per-rpipe, rpipes-per-host), at the end - * we are going to have to rebuild all this based on an scheduler, - * to where we have a list of transactions to do and based on the - * availability of the different requried components (blocks, - * rpipes, segment slots, etc), we go scheduling them. Painful. - */ -#include -#include -#include -#include "wa-hc.h" -#include "wusbhc.h" - -#undef D_LOCAL -#define D_LOCAL 0 /* 0 disabled, > 0 different levels... */ -#include - -enum { - WA_SEGS_MAX = 255, -}; - -enum wa_seg_status { - WA_SEG_NOTREADY, - WA_SEG_READY, - WA_SEG_DELAYED, - WA_SEG_SUBMITTED, - WA_SEG_PENDING, - WA_SEG_DTI_PENDING, - WA_SEG_DONE, - WA_SEG_ERROR, - WA_SEG_ABORTED, -}; - -static void wa_xfer_delayed_run(struct wa_rpipe *); - -/* - * Life cycle governed by 'struct urb' (the refcount of the struct is - * that of the 'struct urb' and usb_free_urb() would free the whole - * struct). - */ -struct wa_seg { - struct urb urb; - struct urb *dto_urb; /* for data output? */ - struct list_head list_node; /* for rpipe->req_list */ - struct wa_xfer *xfer; /* out xfer */ - u8 index; /* which segment we are */ - enum wa_seg_status status; - ssize_t result; /* bytes xfered or error */ - struct wa_xfer_hdr xfer_hdr; - u8 xfer_extra[]; /* xtra space for xfer_hdr_ctl */ -}; - -static void wa_seg_init(struct wa_seg *seg) -{ - /* usb_init_urb() repeats a lot of work, so we do it here */ - kref_init(&seg->urb.kref); -} - -/* - * Protected by xfer->lock - * - */ -struct wa_xfer { - struct kref refcnt; - struct list_head list_node; - spinlock_t lock; - u32 id; - - struct wahc *wa; /* Wire adapter we are plugged to */ - struct usb_host_endpoint *ep; - struct urb *urb; /* URB we are transfering for */ - struct wa_seg **seg; /* transfer segments */ - u8 segs, segs_submitted, segs_done; - unsigned is_inbound:1; - unsigned is_dma:1; - size_t seg_size; - int result; - - gfp_t gfp; /* allocation mask */ - - struct wusb_dev *wusb_dev; /* for activity timestamps */ -}; - -static inline void wa_xfer_init(struct wa_xfer *xfer) -{ - kref_init(&xfer->refcnt); - INIT_LIST_HEAD(&xfer->list_node); - spin_lock_init(&xfer->lock); -} - -/* - * Destory a transfer structure - * - * Note that the xfer->seg[index] thingies follow the URB life cycle, - * so we need to put them, not free them. - */ -static void wa_xfer_destroy(struct kref *_xfer) -{ - struct wa_xfer *xfer = container_of(_xfer, struct wa_xfer, refcnt); - if (xfer->seg) { - unsigned cnt; - for (cnt = 0; cnt < xfer->segs; cnt++) { - if (xfer->is_inbound) - usb_put_urb(xfer->seg[cnt]->dto_urb); - usb_put_urb(&xfer->seg[cnt]->urb); - } - } - kfree(xfer); - d_printf(2, NULL, "xfer %p destroyed\n", xfer); -} - -static void wa_xfer_get(struct wa_xfer *xfer) -{ - kref_get(&xfer->refcnt); -} - -static void wa_xfer_put(struct wa_xfer *xfer) -{ - d_fnstart(3, NULL, "(xfer %p) -- ref count bef put %d\n", - xfer, atomic_read(&xfer->refcnt.refcount)); - kref_put(&xfer->refcnt, wa_xfer_destroy); - d_fnend(3, NULL, "(xfer %p) = void\n", xfer); -} - -/* - * xfer is referenced - * - * xfer->lock has to be unlocked - * - * We take xfer->lock for setting the result; this is a barrier - * against drivers/usb/core/hcd.c:unlink1() being called after we call - * usb_hcd_giveback_urb() and wa_urb_dequeue() trying to get a - * reference to the transfer. - */ -static void wa_xfer_giveback(struct wa_xfer *xfer) -{ - unsigned long flags; - d_fnstart(3, NULL, "(xfer %p)\n", xfer); - spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags); - list_del_init(&xfer->list_node); - spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags); - /* FIXME: segmentation broken -- kills DWA */ - wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result); - wa_put(xfer->wa); - wa_xfer_put(xfer); - d_fnend(3, NULL, "(xfer %p) = void\n", xfer); -} - -/* - * xfer is referenced - * - * xfer->lock has to be unlocked - */ -static void wa_xfer_completion(struct wa_xfer *xfer) -{ - d_fnstart(3, NULL, "(xfer %p)\n", xfer); - if (xfer->wusb_dev) - wusb_dev_put(xfer->wusb_dev); - rpipe_put(xfer->ep->hcpriv); - wa_xfer_giveback(xfer); - d_fnend(3, NULL, "(xfer %p) = void\n", xfer); - return; -} - -/* - * If transfer is done, wrap it up and return true - * - * xfer->lock has to be locked - */ -static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) -{ - unsigned result, cnt; - struct wa_seg *seg; - struct urb *urb = xfer->urb; - unsigned found_short = 0; - - d_fnstart(3, NULL, "(xfer %p)\n", xfer); - result = xfer->segs_done == xfer->segs_submitted; - if (result == 0) - goto out; - urb->actual_length = 0; - for (cnt = 0; cnt < xfer->segs; cnt++) { - seg = xfer->seg[cnt]; - switch (seg->status) { - case WA_SEG_DONE: - if (found_short && seg->result > 0) { - if (printk_ratelimit()) - printk(KERN_ERR "xfer %p#%u: bad short " - "segments (%zu)\n", xfer, cnt, - seg->result); - urb->status = -EINVAL; - goto out; - } - urb->actual_length += seg->result; - if (seg->result < xfer->seg_size - && cnt != xfer->segs-1) - found_short = 1; - d_printf(2, NULL, "xfer %p#%u: DONE short %d " - "result %zu urb->actual_length %d\n", - xfer, seg->index, found_short, seg->result, - urb->actual_length); - break; - case WA_SEG_ERROR: - xfer->result = seg->result; - d_printf(2, NULL, "xfer %p#%u: ERROR result %zu\n", - xfer, seg->index, seg->result); - goto out; - case WA_SEG_ABORTED: - WARN_ON(urb->status != -ECONNRESET - && urb->status != -ENOENT); - d_printf(2, NULL, "xfer %p#%u ABORTED: result %d\n", - xfer, seg->index, urb->status); - xfer->result = urb->status; - goto out; - default: - /* if (printk_ratelimit()) */ - printk(KERN_ERR "xfer %p#%u: " - "is_done bad state %d\n", - xfer, cnt, seg->status); - xfer->result = -EINVAL; - WARN_ON(1); - goto out; - } - } - xfer->result = 0; -out: - d_fnend(3, NULL, "(xfer %p) = void\n", xfer); - return result; -} - -/* - * Initialize a transfer's ID - * - * We need to use a sequential number; if we use the pointer or the - * hash of the pointer, it can repeat over sequential transfers and - * then it will confuse the HWA....wonder why in hell they put a 32 - * bit handle in there then. - */ -static void wa_xfer_id_init(struct wa_xfer *xfer) -{ - xfer->id = atomic_add_return(1, &xfer->wa->xfer_id_count); -} - -/* - * Return the xfer's ID associated with xfer - * - * Need to generate a - */ -static u32 wa_xfer_id(struct wa_xfer *xfer) -{ - return xfer->id; -} - -/* - * Search for a transfer list ID on the HCD's URB list - * - * For 32 bit architectures, we use the pointer itself; for 64 bits, a - * 32-bit hash of the pointer. - * - * @returns NULL if not found. - */ -static struct wa_xfer *wa_xfer_get_by_id(struct wahc *wa, u32 id) -{ - unsigned long flags; - struct wa_xfer *xfer_itr; - spin_lock_irqsave(&wa->xfer_list_lock, flags); - list_for_each_entry(xfer_itr, &wa->xfer_list, list_node) { - if (id == xfer_itr->id) { - wa_xfer_get(xfer_itr); - goto out; - } - } - xfer_itr = NULL; -out: - spin_unlock_irqrestore(&wa->xfer_list_lock, flags); - return xfer_itr; -} - -struct wa_xfer_abort_buffer { - struct urb urb; - struct wa_xfer_abort cmd; -}; - -static void __wa_xfer_abort_cb(struct urb *urb) -{ - struct wa_xfer_abort_buffer *b = urb->context; - usb_put_urb(&b->urb); -} - -/* - * Aborts an ongoing transaction - * - * Assumes the transfer is referenced and locked and in a submitted - * state (mainly that there is an endpoint/rpipe assigned). - * - * The callback (see above) does nothing but freeing up the data by - * putting the URB. Because the URB is allocated at the head of the - * struct, the whole space we allocated is kfreed. - * - * We'll get an 'aborted transaction' xfer result on DTI, that'll - * politely ignore because at this point the transaction has been - * marked as aborted already. - */ -static void __wa_xfer_abort(struct wa_xfer *xfer) -{ - int result; - struct device *dev = &xfer->wa->usb_iface->dev; - struct wa_xfer_abort_buffer *b; - struct wa_rpipe *rpipe = xfer->ep->hcpriv; - - b = kmalloc(sizeof(*b), GFP_ATOMIC); - if (b == NULL) - goto error_kmalloc; - b->cmd.bLength = sizeof(b->cmd); - b->cmd.bRequestType = WA_XFER_ABORT; - b->cmd.wRPipe = rpipe->descr.wRPipeIndex; - b->cmd.dwTransferID = wa_xfer_id(xfer); - - usb_init_urb(&b->urb); - usb_fill_bulk_urb(&b->urb, xfer->wa->usb_dev, - usb_sndbulkpipe(xfer->wa->usb_dev, - xfer->wa->dto_epd->bEndpointAddress), - &b->cmd, sizeof(b->cmd), __wa_xfer_abort_cb, b); - result = usb_submit_urb(&b->urb, GFP_ATOMIC); - if (result < 0) - goto error_submit; - return; /* callback frees! */ - - -error_submit: - if (printk_ratelimit()) - dev_err(dev, "xfer %p: Can't submit abort request: %d\n", - xfer, result); - kfree(b); -error_kmalloc: - return; - -} - -/* - * - * @returns < 0 on error, transfer segment request size if ok - */ -static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, - enum wa_xfer_type *pxfer_type) -{ - ssize_t result; - struct device *dev = &xfer->wa->usb_iface->dev; - size_t maxpktsize; - struct urb *urb = xfer->urb; - struct wa_rpipe *rpipe = xfer->ep->hcpriv; - - d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n", - xfer, rpipe, urb); - switch (rpipe->descr.bmAttribute & 0x3) { - case USB_ENDPOINT_XFER_CONTROL: - *pxfer_type = WA_XFER_TYPE_CTL; - result = sizeof(struct wa_xfer_ctl); - break; - case USB_ENDPOINT_XFER_INT: - case USB_ENDPOINT_XFER_BULK: - *pxfer_type = WA_XFER_TYPE_BI; - result = sizeof(struct wa_xfer_bi); - break; - case USB_ENDPOINT_XFER_ISOC: - dev_err(dev, "FIXME: ISOC not implemented\n"); - result = -ENOSYS; - goto error; - default: - /* never happens */ - BUG(); - result = -EINVAL; /* shut gcc up */ - }; - xfer->is_inbound = urb->pipe & USB_DIR_IN ? 1 : 0; - xfer->is_dma = urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? 1 : 0; - xfer->seg_size = le16_to_cpu(rpipe->descr.wBlocks) - * 1 << (xfer->wa->wa_descr->bRPipeBlockSize - 1); - /* Compute the segment size and make sure it is a multiple of - * the maxpktsize (WUSB1.0[8.3.3.1])...not really too much of - * a check (FIXME) */ - maxpktsize = le16_to_cpu(rpipe->descr.wMaxPacketSize); - if (xfer->seg_size < maxpktsize) { - dev_err(dev, "HW BUG? seg_size %zu smaller than maxpktsize " - "%zu\n", xfer->seg_size, maxpktsize); - result = -EINVAL; - goto error; - } - xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; - xfer->segs = (urb->transfer_buffer_length + xfer->seg_size - 1) - / xfer->seg_size; - if (xfer->segs >= WA_SEGS_MAX) { - dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n", - (int)(urb->transfer_buffer_length / xfer->seg_size), - WA_SEGS_MAX); - result = -EINVAL; - goto error; - } - if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL) - xfer->segs = 1; -error: - d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n", - xfer, rpipe, urb, (int)result); - return result; -} - -/** Fill in the common request header and xfer-type specific data. */ -static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, - struct wa_xfer_hdr *xfer_hdr0, - enum wa_xfer_type xfer_type, - size_t xfer_hdr_size) -{ - struct wa_rpipe *rpipe = xfer->ep->hcpriv; - - xfer_hdr0 = &xfer->seg[0]->xfer_hdr; - xfer_hdr0->bLength = xfer_hdr_size; - xfer_hdr0->bRequestType = xfer_type; - xfer_hdr0->wRPipe = rpipe->descr.wRPipeIndex; - xfer_hdr0->dwTransferID = wa_xfer_id(xfer); - xfer_hdr0->bTransferSegment = 0; - switch (xfer_type) { - case WA_XFER_TYPE_CTL: { - struct wa_xfer_ctl *xfer_ctl = - container_of(xfer_hdr0, struct wa_xfer_ctl, hdr); - xfer_ctl->bmAttribute = xfer->is_inbound ? 1 : 0; - BUG_ON(xfer->urb->transfer_flags & URB_NO_SETUP_DMA_MAP - && xfer->urb->setup_packet == NULL); - memcpy(&xfer_ctl->baSetupData, xfer->urb->setup_packet, - sizeof(xfer_ctl->baSetupData)); - break; - } - case WA_XFER_TYPE_BI: - break; - case WA_XFER_TYPE_ISO: - printk(KERN_ERR "FIXME: ISOC not implemented\n"); - default: - BUG(); - }; -} - -/* - * Callback for the OUT data phase of the segment request - * - * Check wa_seg_cb(); most comments also apply here because this - * function does almost the same thing and they work closely - * together. - * - * If the seg request has failed but this DTO phase has suceeded, - * wa_seg_cb() has already failed the segment and moved the - * status to WA_SEG_ERROR, so this will go through 'case 0' and - * effectively do nothing. - */ -static void wa_seg_dto_cb(struct urb *urb) -{ - struct wa_seg *seg = urb->context; - struct wa_xfer *xfer = seg->xfer; - struct wahc *wa; - struct device *dev; - struct wa_rpipe *rpipe; - unsigned long flags; - unsigned rpipe_ready = 0; - u8 done = 0; - - d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); - switch (urb->status) { - case 0: - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - d_printf(2, dev, "xfer %p#%u: data out done (%d bytes)\n", - xfer, seg->index, urb->actual_length); - if (seg->status < WA_SEG_PENDING) - seg->status = WA_SEG_PENDING; - seg->result = urb->actual_length; - spin_unlock_irqrestore(&xfer->lock, flags); - break; - case -ECONNRESET: /* URB unlinked; no need to do anything */ - case -ENOENT: /* as it was done by the who unlinked us */ - break; - default: /* Other errors ... */ - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - rpipe = xfer->ep->hcpriv; - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: data out error %d\n", - xfer, seg->index, urb->status); - if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)){ - dev_err(dev, "DTO: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - } - if (seg->status != WA_SEG_ERROR) { - seg->status = WA_SEG_ERROR; - seg->result = urb->status; - xfer->segs_done++; - __wa_xfer_abort(xfer); - rpipe_ready = rpipe_avail_inc(rpipe); - done = __wa_xfer_is_done(xfer); - } - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - } - d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); -} - -/* - * Callback for the segment request - * - * If succesful transition state (unless already transitioned or - * outbound transfer); otherwise, take a note of the error, mark this - * segment done and try completion. - * - * Note we don't access until we are sure that the transfer hasn't - * been cancelled (ECONNRESET, ENOENT), which could mean that - * seg->xfer could be already gone. - * - * We have to check before setting the status to WA_SEG_PENDING - * because sometimes the xfer result callback arrives before this - * callback (geeeeeeze), so it might happen that we are already in - * another state. As well, we don't set it if the transfer is inbound, - * as in that case, wa_seg_dto_cb will do it when the OUT data phase - * finishes. - */ -static void wa_seg_cb(struct urb *urb) -{ - struct wa_seg *seg = urb->context; - struct wa_xfer *xfer = seg->xfer; - struct wahc *wa; - struct device *dev; - struct wa_rpipe *rpipe; - unsigned long flags; - unsigned rpipe_ready; - u8 done = 0; - - d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); - switch (urb->status) { - case 0: - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - d_printf(2, dev, "xfer %p#%u: request done\n", - xfer, seg->index); - if (xfer->is_inbound && seg->status < WA_SEG_PENDING) - seg->status = WA_SEG_PENDING; - spin_unlock_irqrestore(&xfer->lock, flags); - break; - case -ECONNRESET: /* URB unlinked; no need to do anything */ - case -ENOENT: /* as it was done by the who unlinked us */ - break; - default: /* Other errors ... */ - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - rpipe = xfer->ep->hcpriv; - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: request error %d\n", - xfer, seg->index, urb->status); - if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)){ - dev_err(dev, "DTO: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - } - usb_unlink_urb(seg->dto_urb); - seg->status = WA_SEG_ERROR; - seg->result = urb->status; - xfer->segs_done++; - __wa_xfer_abort(xfer); - rpipe_ready = rpipe_avail_inc(rpipe); - done = __wa_xfer_is_done(xfer); - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - } - d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); -} - -/* - * Allocate the segs array and initialize each of them - * - * The segments are freed by wa_xfer_destroy() when the xfer use count - * drops to zero; however, because each segment is given the same life - * cycle as the USB URB it contains, it is actually freed by - * usb_put_urb() on the contained USB URB (twisted, eh?). - */ -static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) -{ - int result, cnt; - size_t alloc_size = sizeof(*xfer->seg[0]) - - sizeof(xfer->seg[0]->xfer_hdr) + xfer_hdr_size; - struct usb_device *usb_dev = xfer->wa->usb_dev; - const struct usb_endpoint_descriptor *dto_epd = xfer->wa->dto_epd; - struct wa_seg *seg; - size_t buf_itr, buf_size, buf_itr_size; - - result = -ENOMEM; - xfer->seg = kcalloc(xfer->segs, sizeof(xfer->seg[0]), GFP_ATOMIC); - if (xfer->seg == NULL) - goto error_segs_kzalloc; - buf_itr = 0; - buf_size = xfer->urb->transfer_buffer_length; - for (cnt = 0; cnt < xfer->segs; cnt++) { - seg = xfer->seg[cnt] = kzalloc(alloc_size, GFP_ATOMIC); - if (seg == NULL) - goto error_seg_kzalloc; - wa_seg_init(seg); - seg->xfer = xfer; - seg->index = cnt; - usb_fill_bulk_urb(&seg->urb, usb_dev, - usb_sndbulkpipe(usb_dev, - dto_epd->bEndpointAddress), - &seg->xfer_hdr, xfer_hdr_size, - wa_seg_cb, seg); - buf_itr_size = buf_size > xfer->seg_size ? - xfer->seg_size : buf_size; - if (xfer->is_inbound == 0 && buf_size > 0) { - seg->dto_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (seg->dto_urb == NULL) - goto error_dto_alloc; - usb_fill_bulk_urb( - seg->dto_urb, usb_dev, - usb_sndbulkpipe(usb_dev, - dto_epd->bEndpointAddress), - NULL, 0, wa_seg_dto_cb, seg); - if (xfer->is_dma) { - seg->dto_urb->transfer_dma = - xfer->urb->transfer_dma + buf_itr; - seg->dto_urb->transfer_flags |= - URB_NO_TRANSFER_DMA_MAP; - } else - seg->dto_urb->transfer_buffer = - xfer->urb->transfer_buffer + buf_itr; - seg->dto_urb->transfer_buffer_length = buf_itr_size; - } - seg->status = WA_SEG_READY; - buf_itr += buf_itr_size; - buf_size -= buf_itr_size; - } - return 0; - -error_dto_alloc: - kfree(xfer->seg[cnt]); - cnt--; -error_seg_kzalloc: - /* use the fact that cnt is left at were it failed */ - for (; cnt > 0; cnt--) { - if (xfer->is_inbound == 0) - kfree(xfer->seg[cnt]->dto_urb); - kfree(xfer->seg[cnt]); - } -error_segs_kzalloc: - return result; -} - -/* - * Allocates all the stuff needed to submit a transfer - * - * Breaks the whole data buffer in a list of segments, each one has a - * structure allocated to it and linked in xfer->seg[index] - * - * FIXME: merge setup_segs() and the last part of this function, no - * need to do two for loops when we could run everything in a - * single one - */ -static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) -{ - int result; - struct device *dev = &xfer->wa->usb_iface->dev; - enum wa_xfer_type xfer_type = 0; /* shut up GCC */ - size_t xfer_hdr_size, cnt, transfer_size; - struct wa_xfer_hdr *xfer_hdr0, *xfer_hdr; - - d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n", - xfer, xfer->ep->hcpriv, urb); - - result = __wa_xfer_setup_sizes(xfer, &xfer_type); - if (result < 0) - goto error_setup_sizes; - xfer_hdr_size = result; - result = __wa_xfer_setup_segs(xfer, xfer_hdr_size); - if (result < 0) { - dev_err(dev, "xfer %p: Failed to allocate %d segments: %d\n", - xfer, xfer->segs, result); - goto error_setup_segs; - } - /* Fill the first header */ - xfer_hdr0 = &xfer->seg[0]->xfer_hdr; - wa_xfer_id_init(xfer); - __wa_xfer_setup_hdr0(xfer, xfer_hdr0, xfer_type, xfer_hdr_size); - - /* Fill remainig headers */ - xfer_hdr = xfer_hdr0; - transfer_size = urb->transfer_buffer_length; - xfer_hdr0->dwTransferLength = transfer_size > xfer->seg_size ? - xfer->seg_size : transfer_size; - transfer_size -= xfer->seg_size; - for (cnt = 1; cnt < xfer->segs; cnt++) { - xfer_hdr = &xfer->seg[cnt]->xfer_hdr; - memcpy(xfer_hdr, xfer_hdr0, xfer_hdr_size); - xfer_hdr->bTransferSegment = cnt; - xfer_hdr->dwTransferLength = transfer_size > xfer->seg_size ? - cpu_to_le32(xfer->seg_size) - : cpu_to_le32(transfer_size); - xfer->seg[cnt]->status = WA_SEG_READY; - transfer_size -= xfer->seg_size; - } - xfer_hdr->bTransferSegment |= 0x80; /* this is the last segment */ - result = 0; -error_setup_segs: -error_setup_sizes: - d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n", - xfer, xfer->ep->hcpriv, urb, result); - return result; -} - -/* - * - * - * rpipe->seg_lock is held! - */ -static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer, - struct wa_seg *seg) -{ - int result; - result = usb_submit_urb(&seg->urb, GFP_ATOMIC); - if (result < 0) { - printk(KERN_ERR "xfer %p#%u: REQ submit failed: %d\n", - xfer, seg->index, result); - goto error_seg_submit; - } - if (seg->dto_urb) { - result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC); - if (result < 0) { - printk(KERN_ERR "xfer %p#%u: DTO submit failed: %d\n", - xfer, seg->index, result); - goto error_dto_submit; - } - } - seg->status = WA_SEG_SUBMITTED; - rpipe_avail_dec(rpipe); - return 0; - -error_dto_submit: - usb_unlink_urb(&seg->urb); -error_seg_submit: - seg->status = WA_SEG_ERROR; - seg->result = result; - return result; -} - -/* - * Execute more queued request segments until the maximum concurrent allowed - * - * The ugly unlock/lock sequence on the error path is needed as the - * xfer->lock normally nests the seg_lock and not viceversa. - * - */ -static void wa_xfer_delayed_run(struct wa_rpipe *rpipe) -{ - int result; - struct device *dev = &rpipe->wa->usb_iface->dev; - struct wa_seg *seg; - struct wa_xfer *xfer; - unsigned long flags; - - d_fnstart(1, dev, "(rpipe #%d) %d segments available\n", - le16_to_cpu(rpipe->descr.wRPipeIndex), - atomic_read(&rpipe->segs_available)); - spin_lock_irqsave(&rpipe->seg_lock, flags); - while (atomic_read(&rpipe->segs_available) > 0 - && !list_empty(&rpipe->seg_list)) { - seg = list_entry(rpipe->seg_list.next, struct wa_seg, - list_node); - list_del(&seg->list_node); - xfer = seg->xfer; - result = __wa_seg_submit(rpipe, xfer, seg); - d_printf(1, dev, "xfer %p#%u submitted from delayed " - "[%d segments available] %d\n", - xfer, seg->index, - atomic_read(&rpipe->segs_available), result); - if (unlikely(result < 0)) { - spin_unlock_irqrestore(&rpipe->seg_lock, flags); - spin_lock_irqsave(&xfer->lock, flags); - __wa_xfer_abort(xfer); - xfer->segs_done++; - spin_unlock_irqrestore(&xfer->lock, flags); - spin_lock_irqsave(&rpipe->seg_lock, flags); - } - } - spin_unlock_irqrestore(&rpipe->seg_lock, flags); - d_fnend(1, dev, "(rpipe #%d) = void, %d segments available\n", - le16_to_cpu(rpipe->descr.wRPipeIndex), - atomic_read(&rpipe->segs_available)); - -} - -/* - * - * xfer->lock is taken - * - * On failure submitting we just stop submitting and return error; - * wa_urb_enqueue_b() will execute the completion path - */ -static int __wa_xfer_submit(struct wa_xfer *xfer) -{ - int result; - struct wahc *wa = xfer->wa; - struct device *dev = &wa->usb_iface->dev; - unsigned cnt; - struct wa_seg *seg; - unsigned long flags; - struct wa_rpipe *rpipe = xfer->ep->hcpriv; - size_t maxrequests = le16_to_cpu(rpipe->descr.wRequests); - u8 available; - u8 empty; - - d_fnstart(3, dev, "(xfer %p [rpipe %p])\n", - xfer, xfer->ep->hcpriv); - - spin_lock_irqsave(&wa->xfer_list_lock, flags); - list_add_tail(&xfer->list_node, &wa->xfer_list); - spin_unlock_irqrestore(&wa->xfer_list_lock, flags); - - BUG_ON(atomic_read(&rpipe->segs_available) > maxrequests); - result = 0; - spin_lock_irqsave(&rpipe->seg_lock, flags); - for (cnt = 0; cnt < xfer->segs; cnt++) { - available = atomic_read(&rpipe->segs_available); - empty = list_empty(&rpipe->seg_list); - seg = xfer->seg[cnt]; - d_printf(2, dev, "xfer %p#%u: available %u empty %u (%s)\n", - xfer, cnt, available, empty, - available == 0 || !empty ? "delayed" : "submitted"); - if (available == 0 || !empty) { - d_printf(1, dev, "xfer %p#%u: delayed\n", xfer, cnt); - seg->status = WA_SEG_DELAYED; - list_add_tail(&seg->list_node, &rpipe->seg_list); - } else { - result = __wa_seg_submit(rpipe, xfer, seg); - if (result < 0) - goto error_seg_submit; - } - xfer->segs_submitted++; - } - spin_unlock_irqrestore(&rpipe->seg_lock, flags); - d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer, - xfer->ep->hcpriv); - return result; - -error_seg_submit: - __wa_xfer_abort(xfer); - spin_unlock_irqrestore(&rpipe->seg_lock, flags); - d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer, - xfer->ep->hcpriv); - return result; -} - -/* - * Second part of a URB/transfer enqueuement - * - * Assumes this comes from wa_urb_enqueue() [maybe through - * wa_urb_enqueue_run()]. At this point: - * - * xfer->wa filled and refcounted - * xfer->ep filled with rpipe refcounted if - * delayed == 0 - * xfer->urb filled and refcounted (this is the case when called - * from wa_urb_enqueue() as we come from usb_submit_urb() - * and when called by wa_urb_enqueue_run(), as we took an - * extra ref dropped by _run() after we return). - * xfer->gfp filled - * - * If we fail at __wa_xfer_submit(), then we just check if we are done - * and if so, we run the completion procedure. However, if we are not - * yet done, we do nothing and wait for the completion handlers from - * the submitted URBs or from the xfer-result path to kick in. If xfer - * result never kicks in, the xfer will timeout from the USB code and - * dequeue() will be called. - */ -static void wa_urb_enqueue_b(struct wa_xfer *xfer) -{ - int result; - unsigned long flags; - struct urb *urb = xfer->urb; - struct wahc *wa = xfer->wa; - struct wusbhc *wusbhc = wa->wusb; - struct device *dev = &wa->usb_iface->dev; - struct wusb_dev *wusb_dev; - unsigned done; - - d_fnstart(3, dev, "(wa %p urb %p)\n", wa, urb); - result = rpipe_get_by_ep(wa, xfer->ep, urb, xfer->gfp); - if (result < 0) - goto error_rpipe_get; - result = -ENODEV; - /* FIXME: segmentation broken -- kills DWA */ - mutex_lock(&wusbhc->mutex); /* get a WUSB dev */ - if (urb->dev == NULL) - goto error_dev_gone; - wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); - if (wusb_dev == NULL) { - mutex_unlock(&wusbhc->mutex); - goto error_dev_gone; - } - mutex_unlock(&wusbhc->mutex); - - spin_lock_irqsave(&xfer->lock, flags); - xfer->wusb_dev = wusb_dev; - result = urb->status; - if (urb->status != -EINPROGRESS) - goto error_dequeued; - - result = __wa_xfer_setup(xfer, urb); - if (result < 0) - goto error_xfer_setup; - result = __wa_xfer_submit(xfer); - if (result < 0) - goto error_xfer_submit; - spin_unlock_irqrestore(&xfer->lock, flags); - d_fnend(3, dev, "(wa %p urb %p) = void\n", wa, urb); - return; - - /* this is basically wa_xfer_completion() broken up wa_xfer_giveback() - * does a wa_xfer_put() that will call wa_xfer_destroy() and clean - * upundo setup(). - */ -error_xfer_setup: -error_dequeued: - spin_unlock_irqrestore(&xfer->lock, flags); - /* FIXME: segmentation broken, kills DWA */ - if (wusb_dev) - wusb_dev_put(wusb_dev); -error_dev_gone: - rpipe_put(xfer->ep->hcpriv); -error_rpipe_get: - xfer->result = result; - wa_xfer_giveback(xfer); - d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result); - return; - -error_xfer_submit: - done = __wa_xfer_is_done(xfer); - xfer->result = result; - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result); - return; -} - -/* - * Execute the delayed transfers in the Wire Adapter @wa - * - * We need to be careful here, as dequeue() could be called in the - * middle. That's why we do the whole thing under the - * wa->xfer_list_lock. If dequeue() jumps in, it first locks urb->lock - * and then checks the list -- so as we would be acquiring in inverse - * order, we just drop the lock once we have the xfer and reacquire it - * later. - */ -void wa_urb_enqueue_run(struct work_struct *ws) -{ - struct wahc *wa = container_of(ws, struct wahc, xfer_work); - struct device *dev = &wa->usb_iface->dev; - struct wa_xfer *xfer, *next; - struct urb *urb; - - d_fnstart(3, dev, "(wa %p)\n", wa); - spin_lock_irq(&wa->xfer_list_lock); - list_for_each_entry_safe(xfer, next, &wa->xfer_delayed_list, - list_node) { - list_del_init(&xfer->list_node); - spin_unlock_irq(&wa->xfer_list_lock); - - urb = xfer->urb; - wa_urb_enqueue_b(xfer); - usb_put_urb(urb); /* taken when queuing */ - - spin_lock_irq(&wa->xfer_list_lock); - } - spin_unlock_irq(&wa->xfer_list_lock); - d_fnend(3, dev, "(wa %p) = void\n", wa); -} -EXPORT_SYMBOL_GPL(wa_urb_enqueue_run); - -/* - * Submit a transfer to the Wire Adapter in a delayed way - * - * The process of enqueuing involves possible sleeps() [see - * enqueue_b(), for the rpipe_get() and the mutex_lock()]. If we are - * in an atomic section, we defer the enqueue_b() call--else we call direct. - * - * @urb: We own a reference to it done by the HCI Linux USB stack that - * will be given up by calling usb_hcd_giveback_urb() or by - * returning error from this function -> ergo we don't have to - * refcount it. - */ -int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, - struct urb *urb, gfp_t gfp) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - struct wa_xfer *xfer; - unsigned long my_flags; - unsigned cant_sleep = irqs_disabled() | in_atomic(); - - d_fnstart(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x)\n", - wa, ep, urb, urb->transfer_buffer_length, gfp); - - if (urb->transfer_buffer == NULL - && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) - && urb->transfer_buffer_length != 0) { - dev_err(dev, "BUG? urb %p: NULL xfer buffer & NODMA\n", urb); - dump_stack(); - } - - result = -ENOMEM; - xfer = kzalloc(sizeof(*xfer), gfp); - if (xfer == NULL) - goto error_kmalloc; - - result = -ENOENT; - if (urb->status != -EINPROGRESS) /* cancelled */ - goto error_dequeued; /* before starting? */ - wa_xfer_init(xfer); - xfer->wa = wa_get(wa); - xfer->urb = urb; - xfer->gfp = gfp; - xfer->ep = ep; - urb->hcpriv = xfer; - d_printf(2, dev, "xfer %p urb %p pipe 0x%02x [%d bytes] %s %s %s\n", - xfer, urb, urb->pipe, urb->transfer_buffer_length, - urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? "dma" : "nodma", - urb->pipe & USB_DIR_IN ? "inbound" : "outbound", - cant_sleep ? "deferred" : "inline"); - if (cant_sleep) { - usb_get_urb(urb); - spin_lock_irqsave(&wa->xfer_list_lock, my_flags); - list_add_tail(&xfer->list_node, &wa->xfer_delayed_list); - spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags); - queue_work(wusbd, &wa->xfer_work); - } else { - wa_urb_enqueue_b(xfer); - } - d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = 0\n", - wa, ep, urb, urb->transfer_buffer_length, gfp); - return 0; - -error_dequeued: - kfree(xfer); -error_kmalloc: - d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = %d\n", - wa, ep, urb, urb->transfer_buffer_length, gfp, result); - return result; -} -EXPORT_SYMBOL_GPL(wa_urb_enqueue); - -/* - * Dequeue a URB and make sure uwb_hcd_giveback_urb() [completion - * handler] is called. - * - * Until a transfer goes successfully through wa_urb_enqueue() it - * needs to be dequeued with completion calling; when stuck in delayed - * or before wa_xfer_setup() is called, we need to do completion. - * - * not setup If there is no hcpriv yet, that means that that enqueue - * still had no time to set the xfer up. Because - * urb->status should be other than -EINPROGRESS, - * enqueue() will catch that and bail out. - * - * If the transfer has gone through setup, we just need to clean it - * up. If it has gone through submit(), we have to abort it [with an - * asynch request] and then make sure we cancel each segment. - * - */ -int wa_urb_dequeue(struct wahc *wa, struct urb *urb) -{ - struct device *dev = &wa->usb_iface->dev; - unsigned long flags, flags2; - struct wa_xfer *xfer; - struct wa_seg *seg; - struct wa_rpipe *rpipe; - unsigned cnt; - unsigned rpipe_ready = 0; - - d_fnstart(3, dev, "(wa %p, urb %p)\n", wa, urb); - - d_printf(1, dev, "xfer %p urb %p: aborting\n", urb->hcpriv, urb); - xfer = urb->hcpriv; - if (xfer == NULL) { - /* NOthing setup yet enqueue will see urb->status != - * -EINPROGRESS (by hcd layer) and bail out with - * error, no need to do completion - */ - BUG_ON(urb->status == -EINPROGRESS); - goto out; - } - spin_lock_irqsave(&xfer->lock, flags); - rpipe = xfer->ep->hcpriv; - /* Check the delayed list -> if there, release and complete */ - spin_lock_irqsave(&wa->xfer_list_lock, flags2); - if (!list_empty(&xfer->list_node) && xfer->seg == NULL) - goto dequeue_delayed; - spin_unlock_irqrestore(&wa->xfer_list_lock, flags2); - if (xfer->seg == NULL) /* still hasn't reached */ - goto out_unlock; /* setup(), enqueue_b() completes */ - /* Ok, the xfer is in flight already, it's been setup and submitted.*/ - __wa_xfer_abort(xfer); - for (cnt = 0; cnt < xfer->segs; cnt++) { - seg = xfer->seg[cnt]; - switch (seg->status) { - case WA_SEG_NOTREADY: - case WA_SEG_READY: - printk(KERN_ERR "xfer %p#%u: dequeue bad state %u\n", - xfer, cnt, seg->status); - WARN_ON(1); - break; - case WA_SEG_DELAYED: - seg->status = WA_SEG_ABORTED; - spin_lock_irqsave(&rpipe->seg_lock, flags2); - list_del(&seg->list_node); - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - spin_unlock_irqrestore(&rpipe->seg_lock, flags2); - break; - case WA_SEG_SUBMITTED: - seg->status = WA_SEG_ABORTED; - usb_unlink_urb(&seg->urb); - if (xfer->is_inbound == 0) - usb_unlink_urb(seg->dto_urb); - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - break; - case WA_SEG_PENDING: - seg->status = WA_SEG_ABORTED; - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - break; - case WA_SEG_DTI_PENDING: - usb_unlink_urb(wa->dti_urb); - seg->status = WA_SEG_ABORTED; - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - break; - case WA_SEG_DONE: - case WA_SEG_ERROR: - case WA_SEG_ABORTED: - break; - } - } - xfer->result = urb->status; /* -ENOENT or -ECONNRESET */ - __wa_xfer_is_done(xfer); - spin_unlock_irqrestore(&xfer->lock, flags); - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); - return 0; - -out_unlock: - spin_unlock_irqrestore(&xfer->lock, flags); -out: - d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); - return 0; - -dequeue_delayed: - list_del_init(&xfer->list_node); - spin_unlock_irqrestore(&wa->xfer_list_lock, flags2); - xfer->result = urb->status; - spin_unlock_irqrestore(&xfer->lock, flags); - wa_xfer_giveback(xfer); - usb_put_urb(urb); /* we got a ref in enqueue() */ - d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); - return 0; -} -EXPORT_SYMBOL_GPL(wa_urb_dequeue); - -/* - * Translation from WA status codes (WUSB1.0 Table 8.15) to errno - * codes - * - * Positive errno values are internal inconsistencies and should be - * flagged louder. Negative are to be passed up to the user in the - * normal way. - * - * @status: USB WA status code -- high two bits are stripped. - */ -static int wa_xfer_status_to_errno(u8 status) -{ - int errno; - u8 real_status = status; - static int xlat[] = { - [WA_XFER_STATUS_SUCCESS] = 0, - [WA_XFER_STATUS_HALTED] = -EPIPE, - [WA_XFER_STATUS_DATA_BUFFER_ERROR] = -ENOBUFS, - [WA_XFER_STATUS_BABBLE] = -EOVERFLOW, - [WA_XFER_RESERVED] = EINVAL, - [WA_XFER_STATUS_NOT_FOUND] = 0, - [WA_XFER_STATUS_INSUFFICIENT_RESOURCE] = -ENOMEM, - [WA_XFER_STATUS_TRANSACTION_ERROR] = -EILSEQ, - [WA_XFER_STATUS_ABORTED] = -EINTR, - [WA_XFER_STATUS_RPIPE_NOT_READY] = EINVAL, - [WA_XFER_INVALID_FORMAT] = EINVAL, - [WA_XFER_UNEXPECTED_SEGMENT_NUMBER] = EINVAL, - [WA_XFER_STATUS_RPIPE_TYPE_MISMATCH] = EINVAL, - }; - status &= 0x3f; - - if (status == 0) - return 0; - if (status >= ARRAY_SIZE(xlat)) { - if (printk_ratelimit()) - printk(KERN_ERR "%s(): BUG? " - "Unknown WA transfer status 0x%02x\n", - __func__, real_status); - return -EINVAL; - } - errno = xlat[status]; - if (unlikely(errno > 0)) { - if (printk_ratelimit()) - printk(KERN_ERR "%s(): BUG? " - "Inconsistent WA status: 0x%02x\n", - __func__, real_status); - errno = -errno; - } - return errno; -} - -/* - * Process a xfer result completion message - * - * inbound transfers: need to schedule a DTI read - * - * FIXME: this functio needs to be broken up in parts - */ -static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - unsigned long flags; - u8 seg_idx; - struct wa_seg *seg; - struct wa_rpipe *rpipe; - struct wa_xfer_result *xfer_result = wa->xfer_result; - u8 done = 0; - u8 usb_status; - unsigned rpipe_ready = 0; - - d_fnstart(3, dev, "(wa %p xfer %p)\n", wa, xfer); - spin_lock_irqsave(&xfer->lock, flags); - seg_idx = xfer_result->bTransferSegment & 0x7f; - if (unlikely(seg_idx >= xfer->segs)) - goto error_bad_seg; - seg = xfer->seg[seg_idx]; - rpipe = xfer->ep->hcpriv; - usb_status = xfer_result->bTransferStatus; - d_printf(2, dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n", - xfer, seg_idx, usb_status, seg->status); - if (seg->status == WA_SEG_ABORTED - || seg->status == WA_SEG_ERROR) /* already handled */ - goto segment_aborted; - if (seg->status == WA_SEG_SUBMITTED) /* ops, got here */ - seg->status = WA_SEG_PENDING; /* before wa_seg{_dto}_cb() */ - if (seg->status != WA_SEG_PENDING) { - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: Bad segment state %u\n", - xfer, seg_idx, seg->status); - seg->status = WA_SEG_PENDING; /* workaround/"fix" it */ - } - if (usb_status & 0x80) { - seg->result = wa_xfer_status_to_errno(usb_status); - dev_err(dev, "DTI: xfer %p#%u failed (0x%02x)\n", - xfer, seg->index, usb_status); - goto error_complete; - } - /* FIXME: we ignore warnings, tally them for stats */ - if (usb_status & 0x40) /* Warning?... */ - usb_status = 0; /* ... pass */ - if (xfer->is_inbound) { /* IN data phase: read to buffer */ - seg->status = WA_SEG_DTI_PENDING; - BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); - if (xfer->is_dma) { - wa->buf_in_urb->transfer_dma = - xfer->urb->transfer_dma - + seg_idx * xfer->seg_size; - wa->buf_in_urb->transfer_flags - |= URB_NO_TRANSFER_DMA_MAP; - } else { - wa->buf_in_urb->transfer_buffer = - xfer->urb->transfer_buffer - + seg_idx * xfer->seg_size; - wa->buf_in_urb->transfer_flags - &= ~URB_NO_TRANSFER_DMA_MAP; - } - wa->buf_in_urb->transfer_buffer_length = - le32_to_cpu(xfer_result->dwTransferLength); - wa->buf_in_urb->context = seg; - result = usb_submit_urb(wa->buf_in_urb, GFP_ATOMIC); - if (result < 0) - goto error_submit_buf_in; - } else { - /* OUT data phase, complete it -- */ - seg->status = WA_SEG_DONE; - seg->result = le32_to_cpu(xfer_result->dwTransferLength); - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - done = __wa_xfer_is_done(xfer); - } - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - d_fnend(3, dev, "(wa %p xfer %p) = void\n", wa, xfer); - return; - - -error_submit_buf_in: - if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "DTI: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - } - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n", - xfer, seg_idx, result); - seg->result = result; -error_complete: - seg->status = WA_SEG_ERROR; - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - __wa_xfer_abort(xfer); - done = __wa_xfer_is_done(xfer); - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - d_fnend(3, dev, "(wa %p xfer %p) = void [segment/DTI-submit error]\n", - wa, xfer); - return; - - -error_bad_seg: - spin_unlock_irqrestore(&xfer->lock, flags); - wa_urb_dequeue(wa, xfer->urb); - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: bad segment\n", xfer, seg_idx); - if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "DTI: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - } - d_fnend(3, dev, "(wa %p xfer %p) = void [bad seg]\n", wa, xfer); - return; - - -segment_aborted: - /* nothing to do, as the aborter did the completion */ - spin_unlock_irqrestore(&xfer->lock, flags); - d_fnend(3, dev, "(wa %p xfer %p) = void [segment aborted]\n", - wa, xfer); - return; - -} - -/* - * Callback for the IN data phase - * - * If succesful transition state; otherwise, take a note of the - * error, mark this segment done and try completion. - * - * Note we don't access until we are sure that the transfer hasn't - * been cancelled (ECONNRESET, ENOENT), which could mean that - * seg->xfer could be already gone. - */ -static void wa_buf_in_cb(struct urb *urb) -{ - struct wa_seg *seg = urb->context; - struct wa_xfer *xfer = seg->xfer; - struct wahc *wa; - struct device *dev; - struct wa_rpipe *rpipe; - unsigned rpipe_ready; - unsigned long flags; - u8 done = 0; - - d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); - switch (urb->status) { - case 0: - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - rpipe = xfer->ep->hcpriv; - d_printf(2, dev, "xfer %p#%u: data in done (%zu bytes)\n", - xfer, seg->index, (size_t)urb->actual_length); - seg->status = WA_SEG_DONE; - seg->result = urb->actual_length; - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - done = __wa_xfer_is_done(xfer); - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - break; - case -ECONNRESET: /* URB unlinked; no need to do anything */ - case -ENOENT: /* as it was done by the who unlinked us */ - break; - default: /* Other errors ... */ - spin_lock_irqsave(&xfer->lock, flags); - wa = xfer->wa; - dev = &wa->usb_iface->dev; - rpipe = xfer->ep->hcpriv; - if (printk_ratelimit()) - dev_err(dev, "xfer %p#%u: data in error %d\n", - xfer, seg->index, urb->status); - if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)){ - dev_err(dev, "DTO: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - } - seg->status = WA_SEG_ERROR; - seg->result = urb->status; - xfer->segs_done++; - rpipe_ready = rpipe_avail_inc(rpipe); - __wa_xfer_abort(xfer); - done = __wa_xfer_is_done(xfer); - spin_unlock_irqrestore(&xfer->lock, flags); - if (done) - wa_xfer_completion(xfer); - if (rpipe_ready) - wa_xfer_delayed_run(rpipe); - } - d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); -} - -/* - * Handle an incoming transfer result buffer - * - * Given a transfer result buffer, it completes the transfer (possibly - * scheduling and buffer in read) and then resubmits the DTI URB for a - * new transfer result read. - * - * - * The xfer_result DTI URB state machine - * - * States: OFF | RXR (Read-Xfer-Result) | RBI (Read-Buffer-In) - * - * We start in OFF mode, the first xfer_result notification [through - * wa_handle_notif_xfer()] moves us to RXR by posting the DTI-URB to - * read. - * - * We receive a buffer -- if it is not a xfer_result, we complain and - * repost the DTI-URB. If it is a xfer_result then do the xfer seg - * request accounting. If it is an IN segment, we move to RBI and post - * a BUF-IN-URB to the right buffer. The BUF-IN-URB callback will - * repost the DTI-URB and move to RXR state. if there was no IN - * segment, it will repost the DTI-URB. - * - * We go back to OFF when we detect a ENOENT or ESHUTDOWN (or too many - * errors) in the URBs. - */ -static void wa_xfer_result_cb(struct urb *urb) -{ - int result; - struct wahc *wa = urb->context; - struct device *dev = &wa->usb_iface->dev; - struct wa_xfer_result *xfer_result; - u32 xfer_id; - struct wa_xfer *xfer; - u8 usb_status; - - d_fnstart(3, dev, "(%p)\n", wa); - BUG_ON(wa->dti_urb != urb); - switch (wa->dti_urb->status) { - case 0: - /* We have a xfer result buffer; check it */ - d_printf(2, dev, "DTI: xfer result %d bytes at %p\n", - urb->actual_length, urb->transfer_buffer); - d_dump(3, dev, urb->transfer_buffer, urb->actual_length); - if (wa->dti_urb->actual_length != sizeof(*xfer_result)) { - dev_err(dev, "DTI Error: xfer result--bad size " - "xfer result (%d bytes vs %zu needed)\n", - urb->actual_length, sizeof(*xfer_result)); - break; - } - xfer_result = wa->xfer_result; - if (xfer_result->hdr.bLength != sizeof(*xfer_result)) { - dev_err(dev, "DTI Error: xfer result--" - "bad header length %u\n", - xfer_result->hdr.bLength); - break; - } - if (xfer_result->hdr.bNotifyType != WA_XFER_RESULT) { - dev_err(dev, "DTI Error: xfer result--" - "bad header type 0x%02x\n", - xfer_result->hdr.bNotifyType); - break; - } - usb_status = xfer_result->bTransferStatus & 0x3f; - if (usb_status == WA_XFER_STATUS_ABORTED - || usb_status == WA_XFER_STATUS_NOT_FOUND) - /* taken care of already */ - break; - xfer_id = xfer_result->dwTransferID; - xfer = wa_xfer_get_by_id(wa, xfer_id); - if (xfer == NULL) { - /* FIXME: transaction might have been cancelled */ - dev_err(dev, "DTI Error: xfer result--" - "unknown xfer 0x%08x (status 0x%02x)\n", - xfer_id, usb_status); - break; - } - wa_xfer_result_chew(wa, xfer); - wa_xfer_put(xfer); - break; - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - case -ESHUTDOWN: /* going away! */ - dev_dbg(dev, "DTI: going down! %d\n", urb->status); - goto out; - default: - /* Unknown error */ - if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "DTI: URB max acceptable errors " - "exceeded, resetting device\n"); - wa_reset_all(wa); - goto out; - } - if (printk_ratelimit()) - dev_err(dev, "DTI: URB error %d\n", urb->status); - break; - } - /* Resubmit the DTI URB */ - result = usb_submit_urb(wa->dti_urb, GFP_ATOMIC); - if (result < 0) { - dev_err(dev, "DTI Error: Could not submit DTI URB (%d), " - "resetting\n", result); - wa_reset_all(wa); - } -out: - d_fnend(3, dev, "(%p) = void\n", wa); - return; -} - -/* - * Transfer complete notification - * - * Called from the notif.c code. We get a notification on EP2 saying - * that some endpoint has some transfer result data available. We are - * about to read it. - * - * To speed up things, we always have a URB reading the DTI URB; we - * don't really set it up and start it until the first xfer complete - * notification arrives, which is what we do here. - * - * Follow up in wa_xfer_result_cb(), as that's where the whole state - * machine starts. - * - * So here we just initialize the DTI URB for reading transfer result - * notifications and also the buffer-in URB, for reading buffers. Then - * we just submit the DTI URB. - * - * @wa shall be referenced - */ -void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) -{ - int result; - struct device *dev = &wa->usb_iface->dev; - struct wa_notif_xfer *notif_xfer; - const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; - - d_fnstart(4, dev, "(%p, %p)\n", wa, notif_hdr); - notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr); - BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER); - - if ((0x80 | notif_xfer->bEndpoint) != dti_epd->bEndpointAddress) { - /* FIXME: hardcoded limitation, adapt */ - dev_err(dev, "BUG: DTI ep is %u, not %u (hack me)\n", - notif_xfer->bEndpoint, dti_epd->bEndpointAddress); - goto error; - } - if (wa->dti_urb != NULL) /* DTI URB already started */ - goto out; - - wa->dti_urb = usb_alloc_urb(0, GFP_KERNEL); - if (wa->dti_urb == NULL) { - dev_err(dev, "Can't allocate DTI URB\n"); - goto error_dti_urb_alloc; - } - usb_fill_bulk_urb( - wa->dti_urb, wa->usb_dev, - usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint), - wa->xfer_result, wa->xfer_result_size, - wa_xfer_result_cb, wa); - - wa->buf_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (wa->buf_in_urb == NULL) { - dev_err(dev, "Can't allocate BUF-IN URB\n"); - goto error_buf_in_urb_alloc; - } - usb_fill_bulk_urb( - wa->buf_in_urb, wa->usb_dev, - usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint), - NULL, 0, wa_buf_in_cb, wa); - result = usb_submit_urb(wa->dti_urb, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "DTI Error: Could not submit DTI URB (%d), " - "resetting\n", result); - goto error_dti_urb_submit; - } -out: - d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr); - return; - -error_dti_urb_submit: - usb_put_urb(wa->buf_in_urb); -error_buf_in_urb_alloc: - usb_put_urb(wa->dti_urb); - wa->dti_urb = NULL; -error_dti_urb_alloc: -error: - wa_reset_all(wa); - d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr); - return; -} diff --git a/trunk/drivers/usb/wusbcore/wusbhc.c b/trunk/drivers/usb/wusbcore/wusbhc.c deleted file mode 100644 index 07c63a31c799..000000000000 --- a/trunk/drivers/usb/wusbcore/wusbhc.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Wireless USB Host Controller - * sysfs glue, wusbcore module support and life cycle management - * - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Creation/destruction of wusbhc is split in two parts; that that - * doesn't require the HCD to be added (wusbhc_{create,destroy}) and - * the one that requires (phase B, wusbhc_b_{create,destroy}). - * - * This is so because usb_add_hcd() will start the HC, and thus, all - * the HC specific stuff has to be already initialiazed (like sysfs - * thingies). - */ -#include -#include -#include "wusbhc.h" - -/** - * Extract the wusbhc that corresponds to a USB Host Controller class device - * - * WARNING! Apply only if @dev is that of a - * wusbhc.usb_hcd.self->class_dev; otherwise, you loose. - */ -static struct wusbhc *usbhc_dev_to_wusbhc(struct device *dev) -{ - struct usb_bus *usb_bus = dev_get_drvdata(dev); - struct usb_hcd *usb_hcd = bus_to_hcd(usb_bus); - return usb_hcd_to_wusbhc(usb_hcd); -} - -/* - * Show & store the current WUSB trust timeout - * - * We don't do locking--it is an 'atomic' value. - * - * The units that we store/show are always MILLISECONDS. However, the - * value of trust_timeout is jiffies. - */ -static ssize_t wusb_trust_timeout_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); - - return scnprintf(buf, PAGE_SIZE, "%u\n", wusbhc->trust_timeout); -} - -static ssize_t wusb_trust_timeout_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); - ssize_t result = -ENOSYS; - unsigned trust_timeout; - - result = sscanf(buf, "%u", &trust_timeout); - if (result != 1) { - result = -EINVAL; - goto out; - } - /* FIXME: maybe we should check for range validity? */ - wusbhc->trust_timeout = trust_timeout; - cancel_delayed_work(&wusbhc->keep_alive_timer); - flush_workqueue(wusbd); - queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, - (trust_timeout * CONFIG_HZ)/1000/2); -out: - return result < 0 ? result : size; -} -static DEVICE_ATTR(wusb_trust_timeout, 0644, wusb_trust_timeout_show, - wusb_trust_timeout_store); - -/* - * Show & store the current WUSB CHID - */ -static ssize_t wusb_chid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); - ssize_t result = 0; - - if (wusbhc->wuie_host_info != NULL) - result += ckhdid_printf(buf, PAGE_SIZE, - &wusbhc->wuie_host_info->CHID); - return result; -} - -/* - * Store a new CHID - * - * This will (FIXME) trigger many changes. - * - * - Send an all zeros CHID and it will stop the controller - * - Send a non-zero CHID and it will start it - * (unless it was started, it will just change the CHID, - * diconnecting all devices first). - * - * So first we scan the MMC we are sent and then we act on it. We - * read it in the same format as we print it, an ASCII string of 16 - * hex bytes. - * - * See wusbhc_chid_set() for more info. - */ -static ssize_t wusb_chid_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); - struct wusb_ckhdid chid; - ssize_t result; - - result = sscanf(buf, - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx\n", - &chid.data[0] , &chid.data[1] , - &chid.data[2] , &chid.data[3] , - &chid.data[4] , &chid.data[5] , - &chid.data[6] , &chid.data[7] , - &chid.data[8] , &chid.data[9] , - &chid.data[10], &chid.data[11], - &chid.data[12], &chid.data[13], - &chid.data[14], &chid.data[15]); - if (result != 16) { - dev_err(dev, "Unrecognized CHID (need 16 8-bit hex digits): " - "%d\n", (int)result); - return -EINVAL; - } - result = wusbhc_chid_set(wusbhc, &chid); - return result < 0 ? result : size; -} -static DEVICE_ATTR(wusb_chid, 0644, wusb_chid_show, wusb_chid_store); - -/* Group all the WUSBHC attributes */ -static struct attribute *wusbhc_attrs[] = { - &dev_attr_wusb_trust_timeout.attr, - &dev_attr_wusb_chid.attr, - NULL, -}; - -static struct attribute_group wusbhc_attr_group = { - .name = NULL, /* we want them in the same directory */ - .attrs = wusbhc_attrs, -}; - -/* - * Create a wusbhc instance - * - * NOTEs: - * - * - assumes *wusbhc has been zeroed and wusbhc->usb_hcd has been - * initialized but not added. - * - * - fill out ports_max, mmcies_max and mmcie_{add,rm} before calling. - * - * - fill out wusbhc->uwb_rc and refcount it before calling - * - fill out the wusbhc->sec_modes array - */ -int wusbhc_create(struct wusbhc *wusbhc) -{ - int result = 0; - - wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS; - mutex_init(&wusbhc->mutex); - result = wusbhc_mmcie_create(wusbhc); - if (result < 0) - goto error_mmcie_create; - result = wusbhc_devconnect_create(wusbhc); - if (result < 0) - goto error_devconnect_create; - result = wusbhc_rh_create(wusbhc); - if (result < 0) - goto error_rh_create; - result = wusbhc_sec_create(wusbhc); - if (result < 0) - goto error_sec_create; - return 0; - -error_sec_create: - wusbhc_rh_destroy(wusbhc); -error_rh_create: - wusbhc_devconnect_destroy(wusbhc); -error_devconnect_create: - wusbhc_mmcie_destroy(wusbhc); -error_mmcie_create: - return result; -} -EXPORT_SYMBOL_GPL(wusbhc_create); - -static inline struct kobject *wusbhc_kobj(struct wusbhc *wusbhc) -{ - return &wusbhc->usb_hcd.self.controller->kobj; -} - -/* - * Phase B of a wusbhc instance creation - * - * Creates fields that depend on wusbhc->usb_hcd having been - * added. This is where we create the sysfs files in - * /sys/class/usb_host/usb_hostX/. - * - * NOTE: Assumes wusbhc->usb_hcd has been already added by the upper - * layer (hwahc or whci) - */ -int wusbhc_b_create(struct wusbhc *wusbhc) -{ - int result = 0; - struct device *dev = wusbhc->usb_hcd.self.controller; - - result = sysfs_create_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group); - if (result < 0) { - dev_err(dev, "Cannot register WUSBHC attributes: %d\n", result); - goto error_create_attr_group; - } - - result = wusbhc_pal_register(wusbhc); - if (result < 0) - goto error_pal_register; - return 0; - -error_pal_register: - sysfs_remove_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group); -error_create_attr_group: - return result; -} -EXPORT_SYMBOL_GPL(wusbhc_b_create); - -void wusbhc_b_destroy(struct wusbhc *wusbhc) -{ - wusbhc_pal_unregister(wusbhc); - sysfs_remove_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group); -} -EXPORT_SYMBOL_GPL(wusbhc_b_destroy); - -void wusbhc_destroy(struct wusbhc *wusbhc) -{ - wusbhc_sec_destroy(wusbhc); - wusbhc_rh_destroy(wusbhc); - wusbhc_devconnect_destroy(wusbhc); - wusbhc_mmcie_destroy(wusbhc); -} -EXPORT_SYMBOL_GPL(wusbhc_destroy); - -struct workqueue_struct *wusbd; -EXPORT_SYMBOL_GPL(wusbd); - -/* - * WUSB Cluster ID allocation map - * - * Each WUSB bus in a channel is identified with a Cluster Id in the - * unauth address pace (WUSB1.0[4.3]). We take the range 0xe0 to 0xff - * (that's space for 31 WUSB controllers, as 0xff can't be taken). We - * start taking from 0xff, 0xfe, 0xfd... (hence the += or -= 0xff). - * - * For each one we taken, we pin it in the bitap - */ -#define CLUSTER_IDS 32 -static DECLARE_BITMAP(wusb_cluster_id_table, CLUSTER_IDS); -static DEFINE_SPINLOCK(wusb_cluster_ids_lock); - -/* - * Get a WUSB Cluster ID - * - * Need to release with wusb_cluster_id_put() when done w/ it. - */ -/* FIXME: coordinate with the choose_addres() from the USB stack */ -/* we want to leave the top of the 128 range for cluster addresses and - * the bottom for device addresses (as we map them one on one with - * ports). */ -u8 wusb_cluster_id_get(void) -{ - u8 id; - spin_lock(&wusb_cluster_ids_lock); - id = find_first_zero_bit(wusb_cluster_id_table, CLUSTER_IDS); - if (id > CLUSTER_IDS) { - id = 0; - goto out; - } - set_bit(id, wusb_cluster_id_table); - id = (u8) 0xff - id; -out: - spin_unlock(&wusb_cluster_ids_lock); - return id; - -} -EXPORT_SYMBOL_GPL(wusb_cluster_id_get); - -/* - * Release a WUSB Cluster ID - * - * Obtained it with wusb_cluster_id_get() - */ -void wusb_cluster_id_put(u8 id) -{ - id = 0xff - id; - BUG_ON(id >= CLUSTER_IDS); - spin_lock(&wusb_cluster_ids_lock); - WARN_ON(!test_bit(id, wusb_cluster_id_table)); - clear_bit(id, wusb_cluster_id_table); - spin_unlock(&wusb_cluster_ids_lock); -} -EXPORT_SYMBOL_GPL(wusb_cluster_id_put); - -/** - * wusbhc_giveback_urb - return an URB to the USB core - * @wusbhc: the host controller the URB is from. - * @urb: the URB. - * @status: the URB's status. - * - * Return an URB to the USB core doing some additional WUSB specific - * processing. - * - * - After a successful transfer, update the trust timeout timestamp - * for the WUSB device. - * - * - [WUSB] sections 4.13 and 7.5.1 specifies the stop retrasmittion - * condition for the WCONNECTACK_IE is that the host has observed - * the associated device responding to a control transfer. - */ -void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status) -{ - struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); - - if (status == 0) { - wusb_dev->entry_ts = jiffies; - - /* wusbhc_devconnect_acked() can't be called from from - atomic context so defer it to a work queue. */ - if (!list_empty(&wusb_dev->cack_node)) - queue_work(wusbd, &wusb_dev->devconnect_acked_work); - } - - usb_hcd_giveback_urb(&wusbhc->usb_hcd, urb, status); -} -EXPORT_SYMBOL_GPL(wusbhc_giveback_urb); - -/** - * wusbhc_reset_all - reset the HC hardware - * @wusbhc: the host controller to reset. - * - * Request a full hardware reset of the chip. This will also reset - * the radio controller and any other PALs. - */ -void wusbhc_reset_all(struct wusbhc *wusbhc) -{ - uwb_rc_reset_all(wusbhc->uwb_rc); -} -EXPORT_SYMBOL_GPL(wusbhc_reset_all); - -static struct notifier_block wusb_usb_notifier = { - .notifier_call = wusb_usb_ncb, - .priority = INT_MAX /* Need to be called first of all */ -}; - -static int __init wusbcore_init(void) -{ - int result; - result = wusb_crypto_init(); - if (result < 0) - goto error_crypto_init; - /* WQ is singlethread because we need to serialize notifications */ - wusbd = create_singlethread_workqueue("wusbd"); - if (wusbd == NULL) { - result = -ENOMEM; - printk(KERN_ERR "WUSB-core: Cannot create wusbd workqueue\n"); - goto error_wusbd_create; - } - usb_register_notify(&wusb_usb_notifier); - bitmap_zero(wusb_cluster_id_table, CLUSTER_IDS); - set_bit(0, wusb_cluster_id_table); /* reserve Cluster ID 0xff */ - return 0; - -error_wusbd_create: - wusb_crypto_exit(); -error_crypto_init: - return result; - -} -module_init(wusbcore_init); - -static void __exit wusbcore_exit(void) -{ - clear_bit(0, wusb_cluster_id_table); - if (!bitmap_empty(wusb_cluster_id_table, CLUSTER_IDS)) { - char buf[256]; - bitmap_scnprintf(buf, sizeof(buf), wusb_cluster_id_table, - CLUSTER_IDS); - printk(KERN_ERR "BUG: WUSB Cluster IDs not released " - "on exit: %s\n", buf); - WARN_ON(1); - } - usb_unregister_notify(&wusb_usb_notifier); - destroy_workqueue(wusbd); - wusb_crypto_exit(); -} -module_exit(wusbcore_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Wireless USB core"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/wusbcore/wusbhc.h b/trunk/drivers/usb/wusbcore/wusbhc.h deleted file mode 100644 index d0c132434f1b..000000000000 --- a/trunk/drivers/usb/wusbcore/wusbhc.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Wireless USB Host Controller - * Common infrastructure for WHCI and HWA WUSB-HC drivers - * - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This driver implements parts common to all Wireless USB Host - * Controllers (struct wusbhc, embedding a struct usb_hcd) and is used - * by: - * - * - hwahc: HWA, USB-dongle that implements a Wireless USB host - * controller, (Wireless USB 1.0 Host-Wire-Adapter specification). - * - * - whci: WHCI, a PCI card with a wireless host controller - * (Wireless Host Controller Interface 1.0 specification). - * - * Check out the Design-overview.txt file in the source documentation - * for other details on the implementation. - * - * Main blocks: - * - * rh Root Hub emulation (part of the HCD glue) - * - * devconnect Handle all the issues related to device connection, - * authentication, disconnection, timeout, reseting, - * keepalives, etc. - * - * mmc MMC IE broadcasting handling - * - * A host controller driver just initializes its stuff and as part of - * that, creates a 'struct wusbhc' instance that handles all the - * common WUSB mechanisms. Links in the function ops that are specific - * to it and then registers the host controller. Ready to run. - */ - -#ifndef __WUSBHC_H__ -#define __WUSBHC_H__ - -#include -#include -#include -#include -#include -/* FIXME: Yes, I know: BAD--it's not my fault the USB HC iface is not - * public */ -#include -#include -#include - - -/** - * Wireless USB device - * - * Describe a WUSB device connected to the cluster. This struct - * belongs to the 'struct wusb_port' it is attached to and it is - * responsible for putting and clearing the pointer to it. - * - * Note this "complements" the 'struct usb_device' that the usb_hcd - * keeps for each connected USB device. However, it extends some - * information that is not available (there is no hcpriv ptr in it!) - * *and* most importantly, it's life cycle is different. It is created - * as soon as we get a DN_Connect (connect request notification) from - * the device through the WUSB host controller; the USB stack doesn't - * create the device until we authenticate it. FIXME: this will - * change. - * - * @bos: This is allocated when the BOS descriptors are read from - * the device and freed upon the wusb_dev struct dying. - * @wusb_cap_descr: points into @bos, and has been verified to be size - * safe. - */ -struct wusb_dev { - struct kref refcnt; - struct wusbhc *wusbhc; - struct list_head cack_node; /* Connect-Ack list */ - u8 port_idx; - u8 addr; - u8 beacon_type:4; - struct usb_encryption_descriptor ccm1_etd; - struct wusb_ckhdid cdid; - unsigned long entry_ts; - struct usb_bos_descriptor *bos; - struct usb_wireless_cap_descriptor *wusb_cap_descr; - struct uwb_mas_bm availability; - struct work_struct devconnect_acked_work; - struct urb *set_gtk_urb; - struct usb_ctrlrequest *set_gtk_req; - struct usb_device *usb_dev; -}; - -#define WUSB_DEV_ADDR_UNAUTH 0x80 - -static inline void wusb_dev_init(struct wusb_dev *wusb_dev) -{ - kref_init(&wusb_dev->refcnt); - /* no need to init the cack_node */ -} - -extern void wusb_dev_destroy(struct kref *_wusb_dev); - -static inline struct wusb_dev *wusb_dev_get(struct wusb_dev *wusb_dev) -{ - kref_get(&wusb_dev->refcnt); - return wusb_dev; -} - -static inline void wusb_dev_put(struct wusb_dev *wusb_dev) -{ - kref_put(&wusb_dev->refcnt, wusb_dev_destroy); -} - -/** - * Wireless USB Host Controlller root hub "fake" ports - * (state and device information) - * - * Wireless USB is wireless, so there are no ports; but we - * fake'em. Each RC can connect a max of devices at the same time - * (given in the Wireless Adapter descriptor, bNumPorts or WHCI's - * caps), referred to in wusbhc->ports_max. - * - * See rh.c for more information. - * - * The @status and @change use the same bits as in USB2.0[11.24.2.7], - * so we don't have to do much when getting the port's status. - * - * WUSB1.0[7.1], USB2.0[11.24.2.7.1,fig 11-10], - * include/linux/usb_ch9.h (#define USB_PORT_STAT_*) - */ -struct wusb_port { - u16 status; - u16 change; - struct wusb_dev *wusb_dev; /* connected device's info */ - unsigned reset_count; - u32 ptk_tkid; -}; - -/** - * WUSB Host Controller specifics - * - * All fields that are common to all Wireless USB controller types - * (HWA and WHCI) are grouped here. Host Controller - * functions/operations that only deal with general Wireless USB HC - * issues use this data type to refer to the host. - * - * @usb_hcd Instantiation of a USB host controller - * (initialized by upper layer [HWA=HC or WHCI]. - * - * @dev Device that implements this; initialized by the - * upper layer (HWA-HC, WHCI...); this device should - * have a refcount. - * - * @trust_timeout After this time without hearing for device - * activity, we consider the device gone and we have to - * re-authenticate. - * - * Can be accessed w/o locking--however, read to a - * local variable then use. - * - * @chid WUSB Cluster Host ID: this is supposed to be a - * unique value that doesn't change across reboots (so - * that your devices do not require re-association). - * - * Read/Write protected by @mutex - * - * @dev_info This array has ports_max elements. It is used to - * give the HC information about the WUSB devices (see - * 'struct wusb_dev_info'). - * - * For HWA we need to allocate it in heap; for WHCI it - * needs to be permanently mapped, so we keep it for - * both and make it easy. Call wusbhc->dev_info_set() - * to update an entry. - * - * @ports_max Number of simultaneous device connections (fake - * ports) this HC will take. Read-only. - * - * @port Array of port status for each fake root port. Guaranteed to - * always be the same lenght during device existence - * [this allows for some unlocked but referenced reading]. - * - * @mmcies_max Max number of Information Elements this HC can send - * in its MMC. Read-only. - * - * @mmcie_add HC specific operation (WHCI or HWA) for adding an - * MMCIE. - * - * @mmcie_rm HC specific operation (WHCI or HWA) for removing an - * MMCIE. - * - * @enc_types Array which describes the encryptions methods - * supported by the host as described in WUSB1.0 -- - * one entry per supported method. As of WUSB1.0 there - * is only four methods, we make space for eight just in - * case they decide to add some more (and pray they do - * it in sequential order). if 'enc_types[enc_method] - * != 0', then it is supported by the host. enc_method - * is USB_ENC_TYPE*. - * - * @set_ptk: Set the PTK and enable encryption for a device. Or, if - * the supplied key is NULL, disable encryption for that - * device. - * - * @set_gtk: Set the GTK to be used for all future broadcast packets - * (i.e., MMCs). With some hardware, setting the GTK may start - * MMC transmission. - * - * NOTE: - * - * - If wusb_dev->usb_dev is not NULL, then usb_dev is valid - * (wusb_dev has a refcount on it). Likewise, if usb_dev->wusb_dev - * is not NULL, usb_dev->wusb_dev is valid (usb_dev keeps a - * refcount on it). - * - * Most of the times when you need to use it, it will be non-NULL, - * so there is no real need to check for it (wusb_dev will - * dissapear before usb_dev). - * - * - The following fields need to be filled out before calling - * wusbhc_create(): ports_max, mmcies_max, mmcie_{add,rm}. - * - * - there is no wusbhc_init() method, we do everything in - * wusbhc_create(). - * - * - Creation is done in two phases, wusbhc_create() and - * wusbhc_create_b(); b are the parts that need to be called after - * calling usb_hcd_add(&wusbhc->usb_hcd). - */ -struct wusbhc { - struct usb_hcd usb_hcd; /* HAS TO BE 1st */ - struct device *dev; - struct uwb_rc *uwb_rc; - struct uwb_pal pal; - - unsigned trust_timeout; /* in jiffies */ - struct wuie_host_info *wuie_host_info; /* Includes CHID */ - - struct mutex mutex; /* locks everything else */ - u16 cluster_id; /* Wireless USB Cluster ID */ - struct wusb_port *port; /* Fake port status handling */ - struct wusb_dev_info *dev_info; /* for Set Device Info mgmt */ - u8 ports_max; - unsigned active:1; /* currently xmit'ing MMCs */ - struct wuie_keep_alive keep_alive_ie; /* protected by mutex */ - struct delayed_work keep_alive_timer; - struct list_head cack_list; /* Connect acknowledging */ - size_t cack_count; /* protected by 'mutex' */ - struct wuie_connect_ack cack_ie; - struct uwb_rsv *rsv; /* cluster bandwidth reservation */ - - struct mutex mmcie_mutex; /* MMC WUIE handling */ - struct wuie_hdr **mmcie; /* WUIE array */ - u8 mmcies_max; - /* FIXME: make wusbhc_ops? */ - int (*start)(struct wusbhc *wusbhc); - void (*stop)(struct wusbhc *wusbhc); - int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, - u8 handle, struct wuie_hdr *wuie); - int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle); - int (*dev_info_set)(struct wusbhc *, struct wusb_dev *wusb_dev); - int (*bwa_set)(struct wusbhc *wusbhc, s8 stream_index, - const struct uwb_mas_bm *); - int (*set_ptk)(struct wusbhc *wusbhc, u8 port_idx, - u32 tkid, const void *key, size_t key_size); - int (*set_gtk)(struct wusbhc *wusbhc, - u32 tkid, const void *key, size_t key_size); - int (*set_num_dnts)(struct wusbhc *wusbhc, u8 interval, u8 slots); - - struct { - struct usb_key_descriptor descr; - u8 data[16]; /* GTK key data */ - } __attribute__((packed)) gtk; - u8 gtk_index; - u32 gtk_tkid; - struct work_struct gtk_rekey_done_work; - int pending_set_gtks; - - struct usb_encryption_descriptor *ccm1_etd; -}; - -#define usb_hcd_to_wusbhc(u) container_of((u), struct wusbhc, usb_hcd) - - -extern int wusbhc_create(struct wusbhc *); -extern int wusbhc_b_create(struct wusbhc *); -extern void wusbhc_b_destroy(struct wusbhc *); -extern void wusbhc_destroy(struct wusbhc *); -extern int wusb_dev_sysfs_add(struct wusbhc *, struct usb_device *, - struct wusb_dev *); -extern void wusb_dev_sysfs_rm(struct wusb_dev *); -extern int wusbhc_sec_create(struct wusbhc *); -extern int wusbhc_sec_start(struct wusbhc *); -extern void wusbhc_sec_stop(struct wusbhc *); -extern void wusbhc_sec_destroy(struct wusbhc *); -extern void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, - int status); -void wusbhc_reset_all(struct wusbhc *wusbhc); - -int wusbhc_pal_register(struct wusbhc *wusbhc); -void wusbhc_pal_unregister(struct wusbhc *wusbhc); - -/* - * Return @usb_dev's @usb_hcd (properly referenced) or NULL if gone - * - * @usb_dev: USB device, UNLOCKED and referenced (or otherwise, safe ptr) - * - * This is a safe assumption as @usb_dev->bus is referenced all the - * time during the @usb_dev life cycle. - */ -static inline struct usb_hcd *usb_hcd_get_by_usb_dev(struct usb_device *usb_dev) -{ - struct usb_hcd *usb_hcd; - usb_hcd = container_of(usb_dev->bus, struct usb_hcd, self); - return usb_get_hcd(usb_hcd); -} - -/* - * Increment the reference count on a wusbhc. - * - * @wusbhc's life cycle is identical to that of the underlying usb_hcd. - */ -static inline struct wusbhc *wusbhc_get(struct wusbhc *wusbhc) -{ - return usb_get_hcd(&wusbhc->usb_hcd) ? wusbhc : NULL; -} - -/* - * Return the wusbhc associated to a @usb_dev - * - * @usb_dev: USB device, UNLOCKED and referenced (or otherwise, safe ptr) - * - * @returns: wusbhc for @usb_dev; NULL if the @usb_dev is being torn down. - * WARNING: referenced at the usb_hcd level, unlocked - * - * FIXME: move offline - */ -static inline struct wusbhc *wusbhc_get_by_usb_dev(struct usb_device *usb_dev) -{ - struct wusbhc *wusbhc = NULL; - struct usb_hcd *usb_hcd; - if (usb_dev->devnum > 1 && !usb_dev->wusb) { - /* but root hubs */ - dev_err(&usb_dev->dev, "devnum %d wusb %d\n", usb_dev->devnum, - usb_dev->wusb); - BUG_ON(usb_dev->devnum > 1 && !usb_dev->wusb); - } - usb_hcd = usb_hcd_get_by_usb_dev(usb_dev); - if (usb_hcd == NULL) - return NULL; - BUG_ON(usb_hcd->wireless == 0); - return wusbhc = usb_hcd_to_wusbhc(usb_hcd); -} - - -static inline void wusbhc_put(struct wusbhc *wusbhc) -{ - usb_put_hcd(&wusbhc->usb_hcd); -} - -int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid); -void wusbhc_stop(struct wusbhc *wusbhc); -extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); - -/* Device connect handling */ -extern int wusbhc_devconnect_create(struct wusbhc *); -extern void wusbhc_devconnect_destroy(struct wusbhc *); -extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, - const struct wusb_ckhdid *chid); -extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); -extern int wusbhc_devconnect_auth(struct wusbhc *, u8); -extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, - struct wusb_dn_hdr *dn_hdr, size_t size); -extern int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port); -extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port); -extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, - void *priv); -extern int wusb_set_dev_addr(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, - u8 addr); - -/* Wireless USB fake Root Hub methods */ -extern int wusbhc_rh_create(struct wusbhc *); -extern void wusbhc_rh_destroy(struct wusbhc *); - -extern int wusbhc_rh_status_data(struct usb_hcd *, char *); -extern int wusbhc_rh_control(struct usb_hcd *, u16, u16, u16, char *, u16); -extern int wusbhc_rh_suspend(struct usb_hcd *); -extern int wusbhc_rh_resume(struct usb_hcd *); -extern int wusbhc_rh_start_port_reset(struct usb_hcd *, unsigned); - -/* MMC handling */ -extern int wusbhc_mmcie_create(struct wusbhc *); -extern void wusbhc_mmcie_destroy(struct wusbhc *); -extern int wusbhc_mmcie_set(struct wusbhc *, u8 interval, u8 repeat_cnt, - struct wuie_hdr *); -extern void wusbhc_mmcie_rm(struct wusbhc *, struct wuie_hdr *); - -/* Bandwidth reservation */ -int wusbhc_rsv_establish(struct wusbhc *wusbhc); -void wusbhc_rsv_terminate(struct wusbhc *wusbhc); - -/* - * I've always said - * I wanted a wedding in a church... - * - * but lately I've been thinking about - * the Botanical Gardens. - * - * We could do it by the tulips. - * It'll be beautiful - * - * --Security! - */ -extern int wusb_dev_sec_add(struct wusbhc *, struct usb_device *, - struct wusb_dev *); -extern void wusb_dev_sec_rm(struct wusb_dev *) ; -extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *, - struct wusb_ckhdid *ck); -void wusbhc_gtk_rekey(struct wusbhc *wusbhc); - - -/* WUSB Cluster ID handling */ -extern u8 wusb_cluster_id_get(void); -extern void wusb_cluster_id_put(u8); - -/* - * wusb_port_by_idx - return the port associated to a zero-based port index - * - * NOTE: valid without locking as long as wusbhc is referenced (as the - * number of ports doesn't change). The data pointed to has to - * be verified though :) - */ -static inline struct wusb_port *wusb_port_by_idx(struct wusbhc *wusbhc, - u8 port_idx) -{ - return &wusbhc->port[port_idx]; -} - -/* - * wusb_port_no_to_idx - Convert port number (per usb_dev->portnum) to - * a port_idx. - * - * USB stack USB ports are 1 based!! - * - * NOTE: only valid for WUSB devices!!! - */ -static inline u8 wusb_port_no_to_idx(u8 port_no) -{ - return port_no - 1; -} - -extern struct wusb_dev *__wusb_dev_get_by_usb_dev(struct wusbhc *, - struct usb_device *); - -/* - * Return a referenced wusb_dev given a @usb_dev - * - * Returns NULL if the usb_dev is being torn down. - * - * FIXME: move offline - */ -static inline -struct wusb_dev *wusb_dev_get_by_usb_dev(struct usb_device *usb_dev) -{ - struct wusbhc *wusbhc; - struct wusb_dev *wusb_dev; - wusbhc = wusbhc_get_by_usb_dev(usb_dev); - if (wusbhc == NULL) - return NULL; - mutex_lock(&wusbhc->mutex); - wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, usb_dev); - mutex_unlock(&wusbhc->mutex); - wusbhc_put(wusbhc); - return wusb_dev; -} - -/* Misc */ - -extern struct workqueue_struct *wusbd; -#endif /* #ifndef __WUSBHC_H__ */ diff --git a/trunk/drivers/uwb/Kconfig b/trunk/drivers/uwb/Kconfig deleted file mode 100644 index ca783127af36..000000000000 --- a/trunk/drivers/uwb/Kconfig +++ /dev/null @@ -1,90 +0,0 @@ -# -# UWB device configuration -# - -menuconfig UWB - tristate "Ultra Wideband devices (EXPERIMENTAL)" - depends on EXPERIMENTAL - depends on PCI - default n - help - UWB is a high-bandwidth, low-power, point-to-point radio - technology using a wide spectrum (3.1-10.6GHz). It is - optimized for in-room use (480Mbps at 2 meters, 110Mbps at - 10m). It serves as the transport layer for other protocols, - such as Wireless USB (WUSB), IP (WLP) and upcoming - Bluetooth and 1394 - - The topology is peer to peer; however, higher level - protocols (such as WUSB) might impose a master/slave - relationship. - - Say Y here if your computer has UWB radio controllers (USB or PCI) - based. You will need to enable the radio controllers - below. It is ok to select all of them, no harm done. - - For more help check the UWB and WUSB related files in - . - - To compile the UWB stack as a module, choose M here. - -if UWB - -config UWB_HWA - tristate "UWB Radio Control driver for WUSB-compliant USB dongles (HWA)" - depends on USB - help - This driver enables the radio controller for HWA USB - devices. HWA stands for Host Wire Adapter, and it is a UWB - Radio Controller connected to your system via USB. Most of - them come with a Wireless USB host controller also. - - To compile this driver select Y (built in) or M (module). It - is safe to select any even if you do not have the hardware. - -config UWB_WHCI - tristate "UWB Radio Control driver for WHCI-compliant cards" - depends on PCI - help - This driver enables the radio controller for WHCI cards. - - WHCI is an specification developed by Intel - (http://www.intel.com/technology/comms/wusb/whci.htm) much - in the spirit of USB's EHCI, but for UWB and Wireless USB - radio/host controllers connected via memmory mapping (eg: - PCI). Most of these cards come also with a Wireless USB host - controller. - - To compile this driver select Y (built in) or M (module). It - is safe to select any even if you do not have the hardware. - -config UWB_WLP - tristate "Support WiMedia Link Protocol (Ethernet/IP over UWB)" - depends on UWB && NET - help - This is a common library for drivers that implement - networking over UWB. - -config UWB_I1480U - tristate "Support for Intel Wireless UWB Link 1480 HWA" - depends on UWB_HWA - select FW_LOADER - help - This driver enables support for the i1480 when connected via - USB. It consists of a firmware uploader that will enable it - to behave as an HWA device. - - To compile this driver select Y (built in) or M (module). It - is safe to select any even if you do not have the hardware. - -config UWB_I1480U_WLP - tristate "Support for Intel Wireless UWB Link 1480 HWA's WLP interface" - depends on UWB_I1480U && UWB_WLP && NET - help - This driver enables WLP support for the i1480 when connected via - USB. WLP is the WiMedia Link Protocol, or IP over UWB. - - To compile this driver select Y (built in) or M (module). It - is safe to select any even if you don't have the hardware. - -endif # UWB diff --git a/trunk/drivers/uwb/Makefile b/trunk/drivers/uwb/Makefile deleted file mode 100644 index 257e6908304c..000000000000 --- a/trunk/drivers/uwb/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -obj-$(CONFIG_UWB) += uwb.o -obj-$(CONFIG_UWB_WLP) += wlp/ -obj-$(CONFIG_UWB_WHCI) += umc.o whci.o whc-rc.o -obj-$(CONFIG_UWB_HWA) += hwa-rc.o -obj-$(CONFIG_UWB_I1480U) += i1480/ - -uwb-objs := \ - address.o \ - beacon.o \ - driver.o \ - drp.o \ - drp-avail.o \ - drp-ie.o \ - est.o \ - ie.o \ - lc-dev.o \ - lc-rc.o \ - neh.o \ - pal.o \ - reset.o \ - rsv.o \ - scan.o \ - uwb-debug.o \ - uwbd.o - -umc-objs := \ - umc-bus.o \ - umc-dev.o \ - umc-drv.o diff --git a/trunk/drivers/uwb/address.c b/trunk/drivers/uwb/address.c deleted file mode 100644 index 1664ae5f1706..000000000000 --- a/trunk/drivers/uwb/address.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Ultra Wide Band - * Address management - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#include -#include -#include -#include -#include -#include "uwb-internal.h" - - -/** Device Address Management command */ -struct uwb_rc_cmd_dev_addr_mgmt { - struct uwb_rccb rccb; - u8 bmOperationType; - u8 baAddr[6]; -} __attribute__((packed)); - - -/** - * Low level command for setting/getting UWB radio's addresses - * - * @hwarc: HWA Radio Control interface instance - * @bmOperationType: - * Set/get, MAC/DEV (see WUSB1.0[8.6.2.2]) - * @baAddr: address buffer--assumed to have enough data to hold - * the address type requested. - * @reply: Pointer to reply buffer (can be stack allocated) - * @returns: 0 if ok, < 0 errno code on error. - * - * @cmd has to be allocated because USB cannot grok USB or vmalloc - * buffers depending on your combination of host architecture. - */ -static -int uwb_rc_dev_addr_mgmt(struct uwb_rc *rc, - u8 bmOperationType, const u8 *baAddr, - struct uwb_rc_evt_dev_addr_mgmt *reply) -{ - int result; - struct uwb_rc_cmd_dev_addr_mgmt *cmd; - - result = -ENOMEM; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - goto error_kzalloc; - cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; - cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_DEV_ADDR_MGMT); - cmd->bmOperationType = bmOperationType; - if (baAddr) { - size_t size = 0; - switch (bmOperationType >> 1) { - case 0: size = 2; break; - case 1: size = 6; break; - default: BUG(); - } - memcpy(cmd->baAddr, baAddr, size); - } - reply->rceb.bEventType = UWB_RC_CET_GENERAL; - reply->rceb.wEvent = UWB_RC_CMD_DEV_ADDR_MGMT; - result = uwb_rc_cmd(rc, "DEV-ADDR-MGMT", - &cmd->rccb, sizeof(*cmd), - &reply->rceb, sizeof(*reply)); - if (result < 0) - goto error_cmd; - if (result < sizeof(*reply)) { - dev_err(&rc->uwb_dev.dev, - "DEV-ADDR-MGMT: not enough data replied: " - "%d vs %zu bytes needed\n", result, sizeof(*reply)); - result = -ENOMSG; - } else if (reply->bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, - "DEV-ADDR-MGMT: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply->bResultCode), - reply->bResultCode); - result = -EIO; - } else - result = 0; -error_cmd: - kfree(cmd); -error_kzalloc: - return result; -} - - -/** - * Set the UWB RC MAC or device address. - * - * @rc: UWB Radio Controller - * @_addr: Pointer to address to write [assumed to be either a - * 'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *']. - * @type: Type of address to set (UWB_ADDR_DEV or UWB_ADDR_MAC). - * @returns: 0 if ok, < 0 errno code on error. - * - * Some anal retentivity here: even if both 'struct - * uwb_{dev,mac}_addr' have the actual byte array in the same offset - * and I could just pass _addr to hwarc_cmd_dev_addr_mgmt(), I prefer - * to use some syntatic sugar in case someday we decide to change the - * format of the structs. The compiler will optimize it out anyway. - */ -static int uwb_rc_addr_set(struct uwb_rc *rc, - const void *_addr, enum uwb_addr_type type) -{ - int result; - u8 bmOperationType = 0x1; /* Set address */ - const struct uwb_dev_addr *dev_addr = _addr; - const struct uwb_mac_addr *mac_addr = _addr; - struct uwb_rc_evt_dev_addr_mgmt reply; - const u8 *baAddr; - - result = -EINVAL; - switch (type) { - case UWB_ADDR_DEV: - baAddr = dev_addr->data; - break; - case UWB_ADDR_MAC: - baAddr = mac_addr->data; - bmOperationType |= 0x2; - break; - default: - return result; - } - return uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &reply); -} - - -/** - * Get the UWB radio's MAC or device address. - * - * @rc: UWB Radio Controller - * @_addr: Where to write the address data [assumed to be either a - * 'struct uwb_mac_addr *' or a 'struct uwb_dev_addr *']. - * @type: Type of address to get (UWB_ADDR_DEV or UWB_ADDR_MAC). - * @returns: 0 if ok (and *_addr set), < 0 errno code on error. - * - * See comment in uwb_rc_addr_set() about anal retentivity in the - * type handling of the address variables. - */ -static int uwb_rc_addr_get(struct uwb_rc *rc, - void *_addr, enum uwb_addr_type type) -{ - int result; - u8 bmOperationType = 0x0; /* Get address */ - struct uwb_rc_evt_dev_addr_mgmt evt; - struct uwb_dev_addr *dev_addr = _addr; - struct uwb_mac_addr *mac_addr = _addr; - u8 *baAddr; - - result = -EINVAL; - switch (type) { - case UWB_ADDR_DEV: - baAddr = dev_addr->data; - break; - case UWB_ADDR_MAC: - bmOperationType |= 0x2; - baAddr = mac_addr->data; - break; - default: - return result; - } - result = uwb_rc_dev_addr_mgmt(rc, bmOperationType, baAddr, &evt); - if (result == 0) - switch (type) { - case UWB_ADDR_DEV: - memcpy(&dev_addr->data, evt.baAddr, - sizeof(dev_addr->data)); - break; - case UWB_ADDR_MAC: - memcpy(&mac_addr->data, evt.baAddr, - sizeof(mac_addr->data)); - break; - default: /* shut gcc up */ - BUG(); - } - return result; -} - - -/** Get @rc's MAC address to @addr */ -int uwb_rc_mac_addr_get(struct uwb_rc *rc, - struct uwb_mac_addr *addr) { - return uwb_rc_addr_get(rc, addr, UWB_ADDR_MAC); -} -EXPORT_SYMBOL_GPL(uwb_rc_mac_addr_get); - - -/** Get @rc's device address to @addr */ -int uwb_rc_dev_addr_get(struct uwb_rc *rc, - struct uwb_dev_addr *addr) { - return uwb_rc_addr_get(rc, addr, UWB_ADDR_DEV); -} -EXPORT_SYMBOL_GPL(uwb_rc_dev_addr_get); - - -/** Set @rc's address to @addr */ -int uwb_rc_mac_addr_set(struct uwb_rc *rc, - const struct uwb_mac_addr *addr) -{ - int result = -EINVAL; - mutex_lock(&rc->uwb_dev.mutex); - result = uwb_rc_addr_set(rc, addr, UWB_ADDR_MAC); - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - - -/** Set @rc's address to @addr */ -int uwb_rc_dev_addr_set(struct uwb_rc *rc, - const struct uwb_dev_addr *addr) -{ - int result = -EINVAL; - mutex_lock(&rc->uwb_dev.mutex); - result = uwb_rc_addr_set(rc, addr, UWB_ADDR_DEV); - rc->uwb_dev.dev_addr = *addr; - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -/* Returns !0 if given address is already assigned to device. */ -int __uwb_mac_addr_assigned_check(struct device *dev, void *_addr) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_mac_addr *addr = _addr; - - if (!uwb_mac_addr_cmp(addr, &uwb_dev->mac_addr)) - return !0; - return 0; -} - -/* Returns !0 if given address is already assigned to device. */ -int __uwb_dev_addr_assigned_check(struct device *dev, void *_addr) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_dev_addr *addr = _addr; - if (!uwb_dev_addr_cmp(addr, &uwb_dev->dev_addr)) - return !0; - return 0; -} - -/** - * uwb_dev_addr_assign - assigned a generated DevAddr to a radio controller - * @rc: the (local) radio controller device requiring a new DevAddr - * - * A new DevAddr is required when: - * - first setting up a radio controller - * - if the hardware reports a DevAddr conflict - * - * The DevAddr is randomly generated in the generated DevAddr range - * [0x100, 0xfeff]. The number of devices in a beacon group is limited - * by mMaxBPLength (96) so this address space will never be exhausted. - * - * [ECMA-368] 17.1.1, 17.16. - */ -int uwb_rc_dev_addr_assign(struct uwb_rc *rc) -{ - struct uwb_dev_addr new_addr; - - do { - get_random_bytes(new_addr.data, sizeof(new_addr.data)); - } while (new_addr.data[0] == 0x00 || new_addr.data[0] == 0xff - || __uwb_dev_addr_assigned(rc, &new_addr)); - - return uwb_rc_dev_addr_set(rc, &new_addr); -} - -/** - * uwbd_evt_handle_rc_dev_addr_conflict - handle a DEV_ADDR_CONFLICT event - * @evt: the DEV_ADDR_CONFLICT notification from the radio controller - * - * A new (non-conflicting) DevAddr is assigned to the radio controller. - * - * [ECMA-368] 17.1.1.1. - */ -int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt) -{ - struct uwb_rc *rc = evt->rc; - - return uwb_rc_dev_addr_assign(rc); -} - -/* - * Print the 48-bit EUI MAC address of the radio controller when - * reading /sys/class/uwb_rc/XX/mac_address - */ -static ssize_t uwb_rc_mac_addr_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - struct uwb_mac_addr addr; - ssize_t result; - - mutex_lock(&rc->uwb_dev.mutex); - result = uwb_rc_addr_get(rc, &addr, UWB_ADDR_MAC); - mutex_unlock(&rc->uwb_dev.mutex); - if (result >= 0) { - result = uwb_mac_addr_print(buf, UWB_ADDR_STRSIZE, &addr); - buf[result++] = '\n'; - } - return result; -} - -/* - * Parse a 48 bit address written to /sys/class/uwb_rc/XX/mac_address - * and if correct, set it. - */ -static ssize_t uwb_rc_mac_addr_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - struct uwb_mac_addr addr; - ssize_t result; - - result = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n", - &addr.data[0], &addr.data[1], &addr.data[2], - &addr.data[3], &addr.data[4], &addr.data[5]); - if (result != 6) { - result = -EINVAL; - goto out; - } - if (is_multicast_ether_addr(addr.data)) { - dev_err(&rc->uwb_dev.dev, "refusing to set multicast " - "MAC address %s\n", buf); - result = -EINVAL; - goto out; - } - result = uwb_rc_mac_addr_set(rc, &addr); - if (result == 0) - rc->uwb_dev.mac_addr = addr; -out: - return result < 0 ? result : size; -} -DEVICE_ATTR(mac_address, S_IRUGO | S_IWUSR, uwb_rc_mac_addr_show, uwb_rc_mac_addr_store); - -/** Print @addr to @buf, @return bytes written */ -size_t __uwb_addr_print(char *buf, size_t buf_size, const unsigned char *addr, - int type) -{ - size_t result; - if (type) - result = scnprintf(buf, buf_size, - "%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], - addr[3], addr[4], addr[5]); - else - result = scnprintf(buf, buf_size, "%02x:%02x", - addr[1], addr[0]); - return result; -} -EXPORT_SYMBOL_GPL(__uwb_addr_print); diff --git a/trunk/drivers/uwb/beacon.c b/trunk/drivers/uwb/beacon.c deleted file mode 100644 index 46b18eec5026..000000000000 --- a/trunk/drivers/uwb/beacon.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Ultra Wide Band - * Beacon management - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#include -#include -#include -#include -#include -#include "uwb-internal.h" - -#define D_LOCAL 0 -#include - -/** Start Beaconing command structure */ -struct uwb_rc_cmd_start_beacon { - struct uwb_rccb rccb; - __le16 wBPSTOffset; - u8 bChannelNumber; -} __attribute__((packed)); - - -static int uwb_rc_start_beacon(struct uwb_rc *rc, u16 bpst_offset, u8 channel) -{ - int result; - struct uwb_rc_cmd_start_beacon *cmd; - struct uwb_rc_evt_confirm reply; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; - cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_START_BEACON); - cmd->wBPSTOffset = cpu_to_le16(bpst_offset); - cmd->bChannelNumber = channel; - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_START_BEACON; - result = uwb_rc_cmd(rc, "START-BEACON", &cmd->rccb, sizeof(*cmd), - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, - "START-BEACON: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply.bResultCode), reply.bResultCode); - result = -EIO; - } -error_cmd: - kfree(cmd); - return result; -} - -static int uwb_rc_stop_beacon(struct uwb_rc *rc) -{ - int result; - struct uwb_rccb *cmd; - struct uwb_rc_evt_confirm reply; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - cmd->bCommandType = UWB_RC_CET_GENERAL; - cmd->wCommand = cpu_to_le16(UWB_RC_CMD_STOP_BEACON); - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_STOP_BEACON; - result = uwb_rc_cmd(rc, "STOP-BEACON", cmd, sizeof(*cmd), - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, - "STOP-BEACON: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply.bResultCode), reply.bResultCode); - result = -EIO; - } -error_cmd: - kfree(cmd); - return result; -} - -/* - * Start/stop beacons - * - * @rc: UWB Radio Controller to operate on - * @channel: UWB channel on which to beacon (WUSB[table - * 5-12]). If -1, stop beaconing. - * @bpst_offset: Beacon Period Start Time offset; FIXME-do zero - * - * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB - * of a SET IE command after the device sent the first beacon that includes - * the IEs specified in the SET IE command. So, after we start beaconing we - * check if there is anything in the IE cache and call the SET IE command - * if needed. - */ -int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - - mutex_lock(&rc->uwb_dev.mutex); - if (channel < 0) - channel = -1; - if (channel == -1) - result = uwb_rc_stop_beacon(rc); - else { - /* channel >= 0...dah */ - result = uwb_rc_start_beacon(rc, bpst_offset, channel); - if (result < 0) - goto out_up; - if (le16_to_cpu(rc->ies->wIELength) > 0) { - result = uwb_rc_set_ie(rc, rc->ies); - if (result < 0) { - dev_err(dev, "Cannot set new IE on device: " - "%d\n", result); - result = uwb_rc_stop_beacon(rc); - channel = -1; - bpst_offset = 0; - } else - result = 0; - } - } - - if (result < 0) - goto out_up; - rc->beaconing = channel; - - uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE); - -out_up: - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -/* - * Beacon cache - * - * The purpose of this is to speed up the lookup of becon information - * when a new beacon arrives. The UWB Daemon uses it also to keep a - * tab of which devices are in radio distance and which not. When a - * device's beacon stays present for more than a certain amount of - * time, it is considered a new, usable device. When a beacon ceases - * to be received for a certain amount of time, it is considered that - * the device is gone. - * - * FIXME: use an allocator for the entries - * FIXME: use something faster for search than a list - */ - -struct uwb_beca uwb_beca = { - .list = LIST_HEAD_INIT(uwb_beca.list), - .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex) -}; - - -void uwb_bce_kfree(struct kref *_bce) -{ - struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); - - kfree(bce->be); - kfree(bce); -} - - -/* Find a beacon by dev addr in the cache */ -static -struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) -{ - struct uwb_beca_e *bce, *next; - list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { - d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", - dev_addr->data[0], dev_addr->data[1], - bce->dev_addr.data[0], bce->dev_addr.data[1]); - if (!memcmp(&bce->dev_addr, dev_addr, sizeof(bce->dev_addr))) - goto out; - } - bce = NULL; -out: - return bce; -} - -/* Find a beacon by dev addr in the cache */ -static -struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) -{ - struct uwb_beca_e *bce, *next; - list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { - if (!memcmp(bce->mac_addr, mac_addr->data, - sizeof(struct uwb_mac_addr))) - goto out; - } - bce = NULL; -out: - return bce; -} - -/** - * uwb_dev_get_by_devaddr - get a UWB device with a specific DevAddr - * @rc: the radio controller that saw the device - * @devaddr: DevAddr of the UWB device to find - * - * There may be more than one matching device (in the case of a - * DevAddr conflict), but only the first one is returned. - */ -struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, - const struct uwb_dev_addr *devaddr) -{ - struct uwb_dev *found = NULL; - struct uwb_beca_e *bce; - - mutex_lock(&uwb_beca.mutex); - bce = __uwb_beca_find_bydev(devaddr); - if (bce) - found = uwb_dev_try_get(rc, bce->uwb_dev); - mutex_unlock(&uwb_beca.mutex); - - return found; -} - -/** - * uwb_dev_get_by_macaddr - get a UWB device with a specific EUI-48 - * @rc: the radio controller that saw the device - * @devaddr: EUI-48 of the UWB device to find - */ -struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, - const struct uwb_mac_addr *macaddr) -{ - struct uwb_dev *found = NULL; - struct uwb_beca_e *bce; - - mutex_lock(&uwb_beca.mutex); - bce = __uwb_beca_find_bymac(macaddr); - if (bce) - found = uwb_dev_try_get(rc, bce->uwb_dev); - mutex_unlock(&uwb_beca.mutex); - - return found; -} - -/* Initialize a beacon cache entry */ -static void uwb_beca_e_init(struct uwb_beca_e *bce) -{ - mutex_init(&bce->mutex); - kref_init(&bce->refcnt); - stats_init(&bce->lqe_stats); - stats_init(&bce->rssi_stats); -} - -/* - * Add a beacon to the cache - * - * @be: Beacon event information - * @bf: Beacon frame (part of b, really) - * @ts_jiffies: Timestamp (in jiffies) when the beacon was received - */ -struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, - struct uwb_beacon_frame *bf, - unsigned long ts_jiffies) -{ - struct uwb_beca_e *bce; - - bce = kzalloc(sizeof(*bce), GFP_KERNEL); - if (bce == NULL) - return NULL; - uwb_beca_e_init(bce); - bce->ts_jiffies = ts_jiffies; - bce->uwb_dev = NULL; - list_add(&bce->node, &uwb_beca.list); - return bce; -} - -/* - * Wipe out beacon entries that became stale - * - * Remove associated devicest too. - */ -void uwb_beca_purge(void) -{ - struct uwb_beca_e *bce, *next; - unsigned long expires; - - mutex_lock(&uwb_beca.mutex); - list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { - expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); - if (time_after(jiffies, expires)) { - uwbd_dev_offair(bce); - list_del(&bce->node); - uwb_bce_put(bce); - } - } - mutex_unlock(&uwb_beca.mutex); -} - -/* Clean up the whole beacon cache. Called on shutdown */ -void uwb_beca_release(void) -{ - struct uwb_beca_e *bce, *next; - mutex_lock(&uwb_beca.mutex); - list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { - list_del(&bce->node); - uwb_bce_put(bce); - } - mutex_unlock(&uwb_beca.mutex); -} - -static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, - struct uwb_beacon_frame *bf) -{ - char macbuf[UWB_ADDR_STRSIZE]; - char devbuf[UWB_ADDR_STRSIZE]; - char dstbuf[UWB_ADDR_STRSIZE]; - - uwb_mac_addr_print(macbuf, sizeof(macbuf), &bf->Device_Identifier); - uwb_dev_addr_print(devbuf, sizeof(devbuf), &bf->hdr.SrcAddr); - uwb_dev_addr_print(dstbuf, sizeof(dstbuf), &bf->hdr.DestAddr); - dev_info(&rc->uwb_dev.dev, - "BEACON from %s to %s (ch%u offset %u slot %u MAC %s)\n", - devbuf, dstbuf, be->bChannelNumber, be->wBPSTOffset, - bf->Beacon_Slot_Number, macbuf); -} - -/* - * @bce: beacon cache entry, referenced - */ -ssize_t uwb_bce_print_IEs(struct uwb_dev *uwb_dev, struct uwb_beca_e *bce, - char *buf, size_t size) -{ - ssize_t result = 0; - struct uwb_rc_evt_beacon *be; - struct uwb_beacon_frame *bf; - struct uwb_buf_ctx ctx = { - .buf = buf, - .bytes = 0, - .size = size - }; - - mutex_lock(&bce->mutex); - be = bce->be; - if (be == NULL) - goto out; - bf = (void *) be->BeaconInfo; - uwb_ie_for_each(uwb_dev, uwb_ie_dump_hex, &ctx, - bf->IEData, be->wBeaconInfoLength - sizeof(*bf)); - result = ctx.bytes; -out: - mutex_unlock(&bce->mutex); - return result; -} - -/* - * Verify that the beacon event, frame and IEs are ok - */ -static int uwb_verify_beacon(struct uwb_rc *rc, struct uwb_event *evt, - struct uwb_rc_evt_beacon *be) -{ - int result = -EINVAL; - struct uwb_beacon_frame *bf; - struct device *dev = &rc->uwb_dev.dev; - - /* Is there enough data to decode a beacon frame? */ - if (evt->notif.size < sizeof(*be) + sizeof(*bf)) { - dev_err(dev, "BEACON event: Not enough data to decode " - "(%zu vs %zu bytes needed)\n", evt->notif.size, - sizeof(*be) + sizeof(*bf)); - goto error; - } - /* FIXME: make sure beacon frame IEs are fine and that the whole thing - * is consistent */ - result = 0; -error: - return result; -} - -/* - * Handle UWB_RC_EVT_BEACON events - * - * We check the beacon cache to see how the received beacon fares. If - * is there already we refresh the timestamp. If not we create a new - * entry. - * - * According to the WHCI and WUSB specs, only one beacon frame is - * allowed per notification block, so we don't bother about scanning - * for more. - */ -int uwbd_evt_handle_rc_beacon(struct uwb_event *evt) -{ - int result = -EINVAL; - struct uwb_rc *rc; - struct uwb_rc_evt_beacon *be; - struct uwb_beacon_frame *bf; - struct uwb_beca_e *bce; - unsigned long last_ts; - - rc = evt->rc; - be = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon, rceb); - result = uwb_verify_beacon(rc, evt, be); - if (result < 0) - return result; - - /* FIXME: handle alien beacons. */ - if (be->bBeaconType == UWB_RC_BEACON_TYPE_OL_ALIEN || - be->bBeaconType == UWB_RC_BEACON_TYPE_NOL_ALIEN) { - return -ENOSYS; - } - - bf = (struct uwb_beacon_frame *) be->BeaconInfo; - - /* - * Drop beacons from devices with a NULL EUI-48 -- they cannot - * be uniquely identified. - * - * It's expected that these will all be WUSB devices and they - * have a WUSB specific connection method so ignoring them - * here shouldn't be a problem. - */ - if (uwb_mac_addr_bcast(&bf->Device_Identifier)) - return 0; - - mutex_lock(&uwb_beca.mutex); - bce = __uwb_beca_find_bymac(&bf->Device_Identifier); - if (bce == NULL) { - /* Not in there, a new device is pinging */ - uwb_beacon_print(evt->rc, be, bf); - bce = __uwb_beca_add(be, bf, evt->ts_jiffies); - if (bce == NULL) { - mutex_unlock(&uwb_beca.mutex); - return -ENOMEM; - } - } - mutex_unlock(&uwb_beca.mutex); - - mutex_lock(&bce->mutex); - /* purge old beacon data */ - kfree(bce->be); - - last_ts = bce->ts_jiffies; - - /* Update commonly used fields */ - bce->ts_jiffies = evt->ts_jiffies; - bce->be = be; - bce->dev_addr = bf->hdr.SrcAddr; - bce->mac_addr = &bf->Device_Identifier; - be->wBPSTOffset = le16_to_cpu(be->wBPSTOffset); - be->wBeaconInfoLength = le16_to_cpu(be->wBeaconInfoLength); - stats_add_sample(&bce->lqe_stats, be->bLQI - 7); - stats_add_sample(&bce->rssi_stats, be->bRSSI + 18); - - /* - * This might be a beacon from a new device. - */ - if (bce->uwb_dev == NULL) - uwbd_dev_onair(evt->rc, bce); - - mutex_unlock(&bce->mutex); - - return 1; /* we keep the event data */ -} - -/* - * Handle UWB_RC_EVT_BEACON_SIZE events - * - * XXXXX - */ -int uwbd_evt_handle_rc_beacon_size(struct uwb_event *evt) -{ - int result = -EINVAL; - struct device *dev = &evt->rc->uwb_dev.dev; - struct uwb_rc_evt_beacon_size *bs; - - /* Is there enough data to decode the event? */ - if (evt->notif.size < sizeof(*bs)) { - dev_err(dev, "BEACON SIZE notification: Not enough data to " - "decode (%zu vs %zu bytes needed)\n", - evt->notif.size, sizeof(*bs)); - goto error; - } - bs = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon_size, rceb); - if (0) - dev_info(dev, "Beacon size changed to %u bytes " - "(FIXME: action?)\n", le16_to_cpu(bs->wNewBeaconSize)); - else { - /* temporary hack until we do something with this message... */ - static unsigned count; - if (++count % 1000 == 0) - dev_info(dev, "Beacon size changed %u times " - "(FIXME: action?)\n", count); - } - result = 0; -error: - return result; -} - -/** - * uwbd_evt_handle_rc_bp_slot_change - handle a BP_SLOT_CHANGE event - * @evt: the BP_SLOT_CHANGE notification from the radio controller - * - * If the event indicates that no beacon period slots were available - * then radio controller has transitioned to a non-beaconing state. - * Otherwise, simply save the current beacon slot. - */ -int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event *evt) -{ - struct uwb_rc *rc = evt->rc; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_evt_bp_slot_change *bpsc; - - if (evt->notif.size < sizeof(*bpsc)) { - dev_err(dev, "BP SLOT CHANGE event: Not enough data\n"); - return -EINVAL; - } - bpsc = container_of(evt->notif.rceb, struct uwb_rc_evt_bp_slot_change, rceb); - - mutex_lock(&rc->uwb_dev.mutex); - if (uwb_rc_evt_bp_slot_change_no_slot(bpsc)) { - dev_info(dev, "stopped beaconing: No free slots in BP\n"); - rc->beaconing = -1; - } else - rc->uwb_dev.beacon_slot = uwb_rc_evt_bp_slot_change_slot_num(bpsc); - mutex_unlock(&rc->uwb_dev.mutex); - - return 0; -} - -/** - * Handle UWB_RC_EVT_BPOIE_CHANGE events - * - * XXXXX - */ -struct uwb_ie_bpo { - struct uwb_ie_hdr hdr; - u8 bp_length; - u8 data[]; -} __attribute__((packed)); - -int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *evt) -{ - int result = -EINVAL; - struct device *dev = &evt->rc->uwb_dev.dev; - struct uwb_rc_evt_bpoie_change *bpoiec; - struct uwb_ie_bpo *bpoie; - static unsigned count; /* FIXME: this is a temp hack */ - size_t iesize; - - /* Is there enough data to decode it? */ - if (evt->notif.size < sizeof(*bpoiec)) { - dev_err(dev, "BPOIEC notification: Not enough data to " - "decode (%zu vs %zu bytes needed)\n", - evt->notif.size, sizeof(*bpoiec)); - goto error; - } - bpoiec = container_of(evt->notif.rceb, struct uwb_rc_evt_bpoie_change, rceb); - iesize = le16_to_cpu(bpoiec->wBPOIELength); - if (iesize < sizeof(*bpoie)) { - dev_err(dev, "BPOIEC notification: Not enough IE data to " - "decode (%zu vs %zu bytes needed)\n", - iesize, sizeof(*bpoie)); - goto error; - } - if (++count % 1000 == 0) /* Lame placeholder */ - dev_info(dev, "BPOIE: %u changes received\n", count); - /* - * FIXME: At this point we should go over all the IEs in the - * bpoiec->BPOIE array and act on each. - */ - result = 0; -error: - return result; -} - -/** - * uwb_bg_joined - is the RC in a beacon group? - * @rc: the radio controller - * - * Returns true if the radio controller is in a beacon group (even if - * it's the sole member). - */ -int uwb_bg_joined(struct uwb_rc *rc) -{ - return rc->beaconing != -1; -} -EXPORT_SYMBOL_GPL(uwb_bg_joined); - -/* - * Print beaconing state. - */ -static ssize_t uwb_rc_beacon_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - ssize_t result; - - mutex_lock(&rc->uwb_dev.mutex); - result = sprintf(buf, "%d\n", rc->beaconing); - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -/* - * Start beaconing on the specified channel, or stop beaconing. - * - * The BPST offset of when to start searching for a beacon group to - * join may be specified. - */ -static ssize_t uwb_rc_beacon_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - int channel; - unsigned bpst_offset = 0; - ssize_t result = -EINVAL; - - result = sscanf(buf, "%d %u\n", &channel, &bpst_offset); - if (result >= 1) - result = uwb_rc_beacon(rc, channel, bpst_offset); - - return result < 0 ? result : size; -} -DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, uwb_rc_beacon_show, uwb_rc_beacon_store); diff --git a/trunk/drivers/uwb/driver.c b/trunk/drivers/uwb/driver.c deleted file mode 100644 index 521cdeb84971..000000000000 --- a/trunk/drivers/uwb/driver.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Ultra Wide Band - * Driver initialization, etc - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * Life cycle: FIXME: explain - * - * UWB radio controller: - * - * 1. alloc a uwb_rc, zero it - * 2. call uwb_rc_init() on it to set it up + ops (won't do any - * kind of allocation) - * 3. register (now it is owned by the UWB stack--deregister before - * freeing/destroying). - * 4. It lives on it's own now (UWB stack handles)--when it - * disconnects, call unregister() - * 5. free it. - * - * Make sure you have a reference to the uwb_rc before calling - * any of the UWB API functions. - * - * TODO: - * - * 1. Locking and life cycle management is crappy still. All entry - * points to the UWB HCD API assume you have a reference on the - * uwb_rc structure and that it won't go away. They mutex lock it - * before doing anything. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "uwb-internal.h" - - -/* UWB stack attributes (or 'global' constants) */ - - -/** - * If a beacon dissapears for longer than this, then we consider the - * device who was represented by that beacon to be gone. - * - * ECMA-368[17.2.3, last para] establishes that a device must not - * consider a device to be its neighbour if he doesn't receive a beacon - * for more than mMaxLostBeacons. mMaxLostBeacons is defined in - * ECMA-368[17.16] as 3; because we can get only one beacon per - * superframe, that'd be 3 * 65ms = 195 ~ 200 ms. Let's give it time - * for jitter and stuff and make it 500 ms. - */ -unsigned long beacon_timeout_ms = 500; - -static -ssize_t beacon_timeout_ms_show(struct class *class, char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms); -} - -static -ssize_t beacon_timeout_ms_store(struct class *class, - const char *buf, size_t size) -{ - unsigned long bt; - ssize_t result; - result = sscanf(buf, "%lu", &bt); - if (result != 1) - return -EINVAL; - beacon_timeout_ms = bt; - return size; -} - -static struct class_attribute uwb_class_attrs[] = { - __ATTR(beacon_timeout_ms, S_IWUSR | S_IRUGO, - beacon_timeout_ms_show, beacon_timeout_ms_store), - __ATTR_NULL, -}; - -/** Device model classes */ -struct class uwb_rc_class = { - .name = "uwb_rc", - .class_attrs = uwb_class_attrs, -}; - - -static int __init uwb_subsys_init(void) -{ - int result = 0; - - result = uwb_est_create(); - if (result < 0) { - printk(KERN_ERR "uwb: Can't initialize EST subsystem\n"); - goto error_est_init; - } - - result = class_register(&uwb_rc_class); - if (result < 0) - goto error_uwb_rc_class_register; - uwbd_start(); - uwb_dbg_init(); - return 0; - -error_uwb_rc_class_register: - uwb_est_destroy(); -error_est_init: - return result; -} -module_init(uwb_subsys_init); - -static void __exit uwb_subsys_exit(void) -{ - uwb_dbg_exit(); - uwbd_stop(); - class_unregister(&uwb_rc_class); - uwb_est_destroy(); - return; -} -module_exit(uwb_subsys_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Ultra Wide Band core"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/drp-avail.c b/trunk/drivers/uwb/drp-avail.c deleted file mode 100644 index 3febd8552808..000000000000 --- a/trunk/drivers/uwb/drp-avail.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Ultra Wide Band - * DRP availability management - * - * Copyright (C) 2005-2006 Intel Corporation - * Reinette Chatre - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - * Manage DRP Availability (the MAS available for DRP - * reservations). Thus: - * - * - Handle DRP Availability Change notifications - * - * - Allow the reservation manager to indicate MAS reserved/released - * by local (owned by/targeted at the radio controller) - * reservations. - * - * - Based on the two sources above, generate a DRP Availability IE to - * be included in the beacon. - * - * See also the documentation for struct uwb_drp_avail. - */ - -#include -#include -#include -#include -#include "uwb-internal.h" - -/** - * uwb_drp_avail_init - initialize an RC's MAS availability - * - * All MAS are available initially. The RC will inform use which - * slots are used for the BP (it may change in size). - */ -void uwb_drp_avail_init(struct uwb_rc *rc) -{ - bitmap_fill(rc->drp_avail.global, UWB_NUM_MAS); - bitmap_fill(rc->drp_avail.local, UWB_NUM_MAS); - bitmap_fill(rc->drp_avail.pending, UWB_NUM_MAS); -} - -/* - * Determine MAS available for new local reservations. - * - * avail = global & local & pending - */ -static void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail) -{ - bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); - bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS); -} - -/** - * uwb_drp_avail_reserve_pending - reserve MAS for a new reservation - * @rc: the radio controller - * @mas: the MAS to reserve - * - * Returns 0 on success, or -EBUSY if the MAS requested aren't available. - */ -int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas) -{ - struct uwb_mas_bm avail; - - uwb_drp_available(rc, &avail); - if (!bitmap_subset(mas->bm, avail.bm, UWB_NUM_MAS)) - return -EBUSY; - - bitmap_andnot(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); - return 0; -} - -/** - * uwb_drp_avail_reserve - reserve MAS for an established reservation - * @rc: the radio controller - * @mas: the MAS to reserve - */ -void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas) -{ - bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); - bitmap_andnot(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); - rc->drp_avail.ie_valid = false; -} - -/** - * uwb_drp_avail_release - release MAS from a pending or established reservation - * @rc: the radio controller - * @mas: the MAS to release - */ -void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas) -{ - bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); - bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); - rc->drp_avail.ie_valid = false; -} - -/** - * uwb_drp_avail_ie_update - update the DRP Availability IE - * @rc: the radio controller - * - * avail = global & local - */ -void uwb_drp_avail_ie_update(struct uwb_rc *rc) -{ - struct uwb_mas_bm avail; - - bitmap_and(avail.bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); - - rc->drp_avail.ie.hdr.element_id = UWB_IE_DRP_AVAILABILITY; - rc->drp_avail.ie.hdr.length = UWB_NUM_MAS / 8; - uwb_mas_bm_copy_le(rc->drp_avail.ie.bmp, &avail); - rc->drp_avail.ie_valid = true; -} - -/** - * Create an unsigned long from a buffer containing a byte stream. - * - * @array: pointer to buffer - * @itr: index of buffer from where we start - * @len: the buffer's remaining size may not be exact multiple of - * sizeof(unsigned long), @len is the length of buffer that needs - * to be converted. This will be sizeof(unsigned long) or smaller - * (BUG if not). If it is smaller then we will pad the remaining - * space of the result with zeroes. - */ -static -unsigned long get_val(u8 *array, size_t itr, size_t len) -{ - unsigned long val = 0; - size_t top = itr + len; - - BUG_ON(len > sizeof(val)); - - while (itr < top) { - val <<= 8; - val |= array[top - 1]; - top--; - } - val <<= 8 * (sizeof(val) - len); /* padding */ - return val; -} - -/** - * Initialize bitmap from data buffer. - * - * The bitmap to be converted could come from a IE, for example a - * DRP Availability IE. - * From ECMA-368 1.0 [16.8.7]: " - * octets: 1 1 N * (0 to 32) - * Element ID Length (=N) DRP Availability Bitmap - * - * The DRP Availability Bitmap field is up to 256 bits long, one - * bit for each MAS in the superframe, where the least-significant - * bit of the field corresponds to the first MAS in the superframe - * and successive bits correspond to successive MASs." - * - * The DRP Availability bitmap is in octets from 0 to 32, so octet - * 32 contains bits for MAS 1-8, etc. If the bitmap is smaller than 32 - * octets, the bits in octets not included at the end of the bitmap are - * treated as zero. In this case (when the bitmap is smaller than 32 - * octets) the MAS represented range from MAS 1 to MAS (size of bitmap) - * with the last octet still containing bits for MAS 1-8, etc. - * - * For example: - * F00F0102 03040506 0708090A 0B0C0D0E 0F010203 - * ^^^^ - * |||| - * |||| - * |||\LSB of byte is MAS 9 - * ||\MSB of byte is MAS 16 - * |\LSB of first byte is MAS 1 - * \ MSB of byte is MAS 8 - * - * An example of this encoding can be found in ECMA-368 Annex-D [Table D.11] - * - * The resulting bitmap will have the following mapping: - * bit position 0 == MAS 1 - * bit position 1 == MAS 2 - * ... - * bit position (UWB_NUM_MAS - 1) == MAS UWB_NUM_MAS - * - * @bmp_itr: pointer to bitmap (can be declared with DECLARE_BITMAP) - * @buffer: pointer to buffer containing bitmap data in big endian - * format (MSB first) - * @buffer_size:number of bytes with which bitmap should be initialized - */ -static -void buffer_to_bmp(unsigned long *bmp_itr, void *_buffer, - size_t buffer_size) -{ - u8 *buffer = _buffer; - size_t itr, len; - unsigned long val; - - itr = 0; - while (itr < buffer_size) { - len = buffer_size - itr >= sizeof(val) ? - sizeof(val) : buffer_size - itr; - val = get_val(buffer, itr, len); - bmp_itr[itr / sizeof(val)] = val; - itr += sizeof(val); - } -} - - -/** - * Extract DRP Availability bitmap from the notification. - * - * The notification that comes in contains a bitmap of (UWB_NUM_MAS / 8) bytes - * We convert that to our internal representation. - */ -static -int uwbd_evt_get_drp_avail(struct uwb_event *evt, unsigned long *bmp) -{ - struct device *dev = &evt->rc->uwb_dev.dev; - struct uwb_rc_evt_drp_avail *drp_evt; - int result = -EINVAL; - - /* Is there enough data to decode the event? */ - if (evt->notif.size < sizeof(*drp_evt)) { - dev_err(dev, "DRP Availability Change: Not enough " - "data to decode event [%zu bytes, %zu " - "needed]\n", evt->notif.size, sizeof(*drp_evt)); - goto error; - } - drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb); - buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8); - result = 0; -error: - return result; -} - - -/** - * Process an incoming DRP Availability notification. - * - * @evt: Event information (packs the actual event data, which - * radio controller it came to, etc). - * - * @returns: 0 on success (so uwbd() frees the event buffer), < 0 - * on error. - * - * According to ECMA-368 1.0 [16.8.7], bits set to ONE indicate that - * the MAS slot is available, bits set to ZERO indicate that the slot - * is busy. - * - * So we clear available slots, we set used slots :) - * - * The notification only marks non-availability based on the BP and - * received DRP IEs that are not for this radio controller. A copy of - * this bitmap is needed to generate the real availability (which - * includes local and pending reservations). - * - * The DRP Availability IE that this radio controller emits will need - * to be updated. - */ -int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt) -{ - int result; - struct uwb_rc *rc = evt->rc; - DECLARE_BITMAP(bmp, UWB_NUM_MAS); - - result = uwbd_evt_get_drp_avail(evt, bmp); - if (result < 0) - return result; - - mutex_lock(&rc->rsvs_mutex); - bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS); - rc->drp_avail.ie_valid = false; - mutex_unlock(&rc->rsvs_mutex); - - uwb_rsv_sched_update(rc); - - return 0; -} diff --git a/trunk/drivers/uwb/drp-ie.c b/trunk/drivers/uwb/drp-ie.c deleted file mode 100644 index 882724c5f126..000000000000 --- a/trunk/drivers/uwb/drp-ie.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * UWB DRP IE management. - * - * Copyright (C) 2005-2006 Intel Corporation - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include - -#include "uwb-internal.h" - -/* - * Allocate a DRP IE. - * - * To save having to free/allocate a DRP IE when its MAS changes, - * enough memory is allocated for the maxiumum number of DRP - * allocation fields. This gives an overhead per reservation of up to - * (UWB_NUM_ZONES - 1) * 4 = 60 octets. - */ -static struct uwb_ie_drp *uwb_drp_ie_alloc(void) -{ - struct uwb_ie_drp *drp_ie; - unsigned tiebreaker; - - drp_ie = kzalloc(sizeof(struct uwb_ie_drp) + - UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc), - GFP_KERNEL); - if (drp_ie) { - drp_ie->hdr.element_id = UWB_IE_DRP; - - get_random_bytes(&tiebreaker, sizeof(unsigned)); - uwb_ie_drp_set_tiebreaker(drp_ie, tiebreaker & 1); - } - return drp_ie; -} - - -/* - * Fill a DRP IE's allocation fields from a MAS bitmap. - */ -static void uwb_drp_ie_from_bm(struct uwb_ie_drp *drp_ie, - struct uwb_mas_bm *mas) -{ - int z, i, num_fields = 0, next = 0; - struct uwb_drp_alloc *zones; - __le16 current_bmp; - DECLARE_BITMAP(tmp_bmp, UWB_NUM_MAS); - DECLARE_BITMAP(tmp_mas_bm, UWB_MAS_PER_ZONE); - - zones = drp_ie->allocs; - - bitmap_copy(tmp_bmp, mas->bm, UWB_NUM_MAS); - - /* Determine unique MAS bitmaps in zones from bitmap. */ - for (z = 0; z < UWB_NUM_ZONES; z++) { - bitmap_copy(tmp_mas_bm, tmp_bmp, UWB_MAS_PER_ZONE); - if (bitmap_weight(tmp_mas_bm, UWB_MAS_PER_ZONE) > 0) { - bool found = false; - current_bmp = (__le16) *tmp_mas_bm; - for (i = 0; i < next; i++) { - if (current_bmp == zones[i].mas_bm) { - zones[i].zone_bm |= 1 << z; - found = true; - break; - } - } - if (!found) { - num_fields++; - zones[next].zone_bm = 1 << z; - zones[next].mas_bm = current_bmp; - next++; - } - } - bitmap_shift_right(tmp_bmp, tmp_bmp, UWB_MAS_PER_ZONE, UWB_NUM_MAS); - } - - /* Store in format ready for transmission (le16). */ - for (i = 0; i < num_fields; i++) { - drp_ie->allocs[i].zone_bm = cpu_to_le16(zones[i].zone_bm); - drp_ie->allocs[i].mas_bm = cpu_to_le16(zones[i].mas_bm); - } - - drp_ie->hdr.length = sizeof(struct uwb_ie_drp) - sizeof(struct uwb_ie_hdr) - + num_fields * sizeof(struct uwb_drp_alloc); -} - -/** - * uwb_drp_ie_update - update a reservation's DRP IE - * @rsv: the reservation - */ -int uwb_drp_ie_update(struct uwb_rsv *rsv) -{ - struct device *dev = &rsv->rc->uwb_dev.dev; - struct uwb_ie_drp *drp_ie; - int reason_code, status; - - switch (rsv->state) { - case UWB_RSV_STATE_NONE: - kfree(rsv->drp_ie); - rsv->drp_ie = NULL; - return 0; - case UWB_RSV_STATE_O_INITIATED: - reason_code = UWB_DRP_REASON_ACCEPTED; - status = 0; - break; - case UWB_RSV_STATE_O_PENDING: - reason_code = UWB_DRP_REASON_ACCEPTED; - status = 0; - break; - case UWB_RSV_STATE_O_MODIFIED: - reason_code = UWB_DRP_REASON_MODIFIED; - status = 1; - break; - case UWB_RSV_STATE_O_ESTABLISHED: - reason_code = UWB_DRP_REASON_ACCEPTED; - status = 1; - break; - case UWB_RSV_STATE_T_ACCEPTED: - reason_code = UWB_DRP_REASON_ACCEPTED; - status = 1; - break; - case UWB_RSV_STATE_T_DENIED: - reason_code = UWB_DRP_REASON_DENIED; - status = 0; - break; - default: - dev_dbg(dev, "rsv with unhandled state (%d)\n", rsv->state); - return -EINVAL; - } - - if (rsv->drp_ie == NULL) { - rsv->drp_ie = uwb_drp_ie_alloc(); - if (rsv->drp_ie == NULL) - return -ENOMEM; - } - drp_ie = rsv->drp_ie; - - uwb_ie_drp_set_owner(drp_ie, uwb_rsv_is_owner(rsv)); - uwb_ie_drp_set_status(drp_ie, status); - uwb_ie_drp_set_reason_code(drp_ie, reason_code); - uwb_ie_drp_set_stream_index(drp_ie, rsv->stream); - uwb_ie_drp_set_type(drp_ie, rsv->type); - - if (uwb_rsv_is_owner(rsv)) { - switch (rsv->target.type) { - case UWB_RSV_TARGET_DEV: - drp_ie->dev_addr = rsv->target.dev->dev_addr; - break; - case UWB_RSV_TARGET_DEVADDR: - drp_ie->dev_addr = rsv->target.devaddr; - break; - } - } else - drp_ie->dev_addr = rsv->owner->dev_addr; - - uwb_drp_ie_from_bm(drp_ie, &rsv->mas); - - rsv->ie_valid = true; - return 0; -} - -/* - * Set MAS bits from given MAS bitmap in a single zone of large bitmap. - * - * We are given a zone id and the MAS bitmap of bits that need to be set in - * this zone. Note that this zone may already have bits set and this only - * adds settings - we cannot simply assign the MAS bitmap contents to the - * zone contents. We iterate over the the bits (MAS) in the zone and set the - * bits that are set in the given MAS bitmap. - */ -static -void uwb_drp_ie_single_zone_to_bm(struct uwb_mas_bm *bm, u8 zone, u16 mas_bm) -{ - int mas; - u16 mas_mask; - - for (mas = 0; mas < UWB_MAS_PER_ZONE; mas++) { - mas_mask = 1 << mas; - if (mas_bm & mas_mask) - set_bit(zone * UWB_NUM_ZONES + mas, bm->bm); - } -} - -/** - * uwb_drp_ie_zones_to_bm - convert DRP allocation fields to a bitmap - * @mas: MAS bitmap that will be populated to correspond to the - * allocation fields in the DRP IE - * @drp_ie: the DRP IE that contains the allocation fields. - * - * The input format is an array of MAS allocation fields (16 bit Zone - * bitmap, 16 bit MAS bitmap) as described in [ECMA-368] section - * 16.8.6. The output is a full 256 bit MAS bitmap. - * - * We go over all the allocation fields, for each allocation field we - * know which zones are impacted. We iterate over all the zones - * impacted and call a function that will set the correct MAS bits in - * each zone. - */ -void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie) -{ - int numallocs = (drp_ie->hdr.length - 4) / 4; - const struct uwb_drp_alloc *alloc; - int cnt; - u16 zone_bm, mas_bm; - u8 zone; - u16 zone_mask; - - for (cnt = 0; cnt < numallocs; cnt++) { - alloc = &drp_ie->allocs[cnt]; - zone_bm = le16_to_cpu(alloc->zone_bm); - mas_bm = le16_to_cpu(alloc->mas_bm); - for (zone = 0; zone < UWB_NUM_ZONES; zone++) { - zone_mask = 1 << zone; - if (zone_bm & zone_mask) - uwb_drp_ie_single_zone_to_bm(bm, zone, mas_bm); - } - } -} diff --git a/trunk/drivers/uwb/drp.c b/trunk/drivers/uwb/drp.c deleted file mode 100644 index c0b1e5e2bd08..000000000000 --- a/trunk/drivers/uwb/drp.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Ultra Wide Band - * Dynamic Reservation Protocol handling - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include "uwb-internal.h" - -/** - * Construct and send the SET DRP IE - * - * @rc: UWB Host controller - * @returns: >= 0 number of bytes still available in the beacon - * < 0 errno code on error. - * - * See WUSB[8.6.2.7]: The host must set all the DRP IEs that it wants the - * device to include in its beacon at the same time. We thus have to - * traverse all reservations and include the DRP IEs of all PENDING - * and NEGOTIATED reservations in a SET DRP command for transmission. - * - * A DRP Availability IE is appended. - * - * rc->uwb_dev.mutex is held - * - * FIXME We currently ignore the returned value indicating the remaining space - * in beacon. This could be used to deny reservation requests earlier if - * determined that they would cause the beacon space to be exceeded. - */ -static -int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_cmd_set_drp_ie *cmd; - struct uwb_rc_evt_set_drp_ie reply; - struct uwb_rsv *rsv; - int num_bytes = 0; - u8 *IEDataptr; - - result = -ENOMEM; - /* First traverse all reservations to determine memory needed. */ - list_for_each_entry(rsv, &rc->reservations, rc_node) { - if (rsv->drp_ie != NULL) - num_bytes += rsv->drp_ie->hdr.length + 2; - } - num_bytes += sizeof(rc->drp_avail.ie); - cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL); - if (cmd == NULL) - goto error; - cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; - cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_DRP_IE); - cmd->wIELength = num_bytes; - IEDataptr = (u8 *)&cmd->IEData[0]; - - /* Next traverse all reservations to place IEs in allocated memory. */ - list_for_each_entry(rsv, &rc->reservations, rc_node) { - if (rsv->drp_ie != NULL) { - memcpy(IEDataptr, rsv->drp_ie, - rsv->drp_ie->hdr.length + 2); - IEDataptr += rsv->drp_ie->hdr.length + 2; - } - } - memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie)); - - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_SET_DRP_IE; - result = uwb_rc_cmd(rc, "SET-DRP-IE", &cmd->rccb, - sizeof(*cmd) + num_bytes, &reply.rceb, - sizeof(reply)); - if (result < 0) - goto error_cmd; - result = le16_to_cpu(reply.wRemainingSpace); - if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: command execution " - "failed: %s (%d). RemainingSpace in beacon " - "= %d\n", uwb_rc_strerror(reply.bResultCode), - reply.bResultCode, result); - result = -EIO; - } else { - dev_dbg(dev, "SET-DRP-IE sent. RemainingSpace in beacon " - "= %d.\n", result); - result = 0; - } -error_cmd: - kfree(cmd); -error: - return result; - -} -/** - * Send all DRP IEs associated with this host - * - * @returns: >= 0 number of bytes still available in the beacon - * < 0 errno code on error. - * - * As per the protocol we obtain the host controller device lock to access - * bandwidth structures. - */ -int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) -{ - int result; - - mutex_lock(&rc->uwb_dev.mutex); - result = uwb_rc_gen_send_drp_ie(rc); - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -void uwb_drp_handle_timeout(struct uwb_rsv *rsv) -{ - struct device *dev = &rsv->rc->uwb_dev.dev; - - dev_dbg(dev, "reservation timeout in state %s (%d)\n", - uwb_rsv_state_str(rsv->state), rsv->state); - - switch (rsv->state) { - case UWB_RSV_STATE_O_INITIATED: - if (rsv->is_multicast) { - uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); - return; - } - break; - case UWB_RSV_STATE_O_ESTABLISHED: - if (rsv->is_multicast) - return; - break; - default: - break; - } - uwb_rsv_remove(rsv); -} - -/* - * Based on the DRP IE, transition a target reservation to a new - * state. - */ -static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, - struct uwb_ie_drp *drp_ie) -{ - struct device *dev = &rc->uwb_dev.dev; - int status; - enum uwb_drp_reason reason_code; - - status = uwb_ie_drp_status(drp_ie); - reason_code = uwb_ie_drp_reason_code(drp_ie); - - if (status) { - switch (reason_code) { - case UWB_DRP_REASON_ACCEPTED: - uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); - break; - case UWB_DRP_REASON_MODIFIED: - dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", - reason_code, status); - break; - default: - dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", - reason_code, status); - } - } else { - switch (reason_code) { - case UWB_DRP_REASON_ACCEPTED: - /* New reservations are handled in uwb_rsv_find(). */ - break; - case UWB_DRP_REASON_DENIED: - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); - break; - case UWB_DRP_REASON_CONFLICT: - case UWB_DRP_REASON_MODIFIED: - dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", - reason_code, status); - break; - default: - dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", - reason_code, status); - } - } -} - -/* - * Based on the DRP IE, transition an owner reservation to a new - * state. - */ -static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, - struct uwb_ie_drp *drp_ie) -{ - struct device *dev = &rc->uwb_dev.dev; - int status; - enum uwb_drp_reason reason_code; - - status = uwb_ie_drp_status(drp_ie); - reason_code = uwb_ie_drp_reason_code(drp_ie); - - if (status) { - switch (reason_code) { - case UWB_DRP_REASON_ACCEPTED: - uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); - break; - case UWB_DRP_REASON_MODIFIED: - dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", - reason_code, status); - break; - default: - dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", - reason_code, status); - } - } else { - switch (reason_code) { - case UWB_DRP_REASON_PENDING: - uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_PENDING); - break; - case UWB_DRP_REASON_DENIED: - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); - break; - case UWB_DRP_REASON_CONFLICT: - case UWB_DRP_REASON_MODIFIED: - dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", - reason_code, status); - break; - default: - dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", - reason_code, status); - } - } -} - -/* - * Process a received DRP IE, it's either for a reservation owned by - * the RC or targeted at it (or it's for a WUSB cluster reservation). - */ -static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, - struct uwb_ie_drp *drp_ie) -{ - struct uwb_rsv *rsv; - - rsv = uwb_rsv_find(rc, src, drp_ie); - if (!rsv) { - /* - * No reservation? It's either for a recently - * terminated reservation; or the DRP IE couldn't be - * processed (e.g., an invalid IE or out of memory). - */ - return; - } - - /* - * Do nothing with DRP IEs for reservations that have been - * terminated. - */ - if (rsv->state == UWB_RSV_STATE_NONE) { - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); - return; - } - - if (uwb_ie_drp_owner(drp_ie)) - uwb_drp_process_target(rc, rsv, drp_ie); - else - uwb_drp_process_owner(rc, rsv, drp_ie); -} - - -/* - * Process all the DRP IEs (both DRP IEs and the DRP Availability IE) - * from a device. - */ -static -void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, - size_t ielen, struct uwb_dev *src_dev) -{ - struct device *dev = &rc->uwb_dev.dev; - struct uwb_ie_hdr *ie_hdr; - void *ptr; - - ptr = drp_evt->ie_data; - for (;;) { - ie_hdr = uwb_ie_next(&ptr, &ielen); - if (!ie_hdr) - break; - - switch (ie_hdr->element_id) { - case UWB_IE_DRP_AVAILABILITY: - /* FIXME: does something need to be done with this? */ - break; - case UWB_IE_DRP: - uwb_drp_process(rc, src_dev, (struct uwb_ie_drp *)ie_hdr); - break; - default: - dev_warn(dev, "unexpected IE in DRP notification\n"); - break; - } - } - - if (ielen > 0) - dev_warn(dev, "%d octets remaining in DRP notification\n", - (int)ielen); -} - - -/* - * Go through all the DRP IEs and find the ones that conflict with our - * reservations. - * - * FIXME: must resolve the conflict according the the rules in - * [ECMA-368]. - */ -static -void uwb_drp_process_conflict_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, - size_t ielen, struct uwb_dev *src_dev) -{ - struct device *dev = &rc->uwb_dev.dev; - struct uwb_ie_hdr *ie_hdr; - struct uwb_ie_drp *drp_ie; - void *ptr; - - ptr = drp_evt->ie_data; - for (;;) { - ie_hdr = uwb_ie_next(&ptr, &ielen); - if (!ie_hdr) - break; - - drp_ie = container_of(ie_hdr, struct uwb_ie_drp, hdr); - - /* FIXME: check if this DRP IE conflicts. */ - } - - if (ielen > 0) - dev_warn(dev, "%d octets remaining in DRP notification\n", - (int)ielen); -} - - -/* - * Terminate all reservations owned by, or targeted at, 'uwb_dev'. - */ -static void uwb_drp_terminate_all(struct uwb_rc *rc, struct uwb_dev *uwb_dev) -{ - struct uwb_rsv *rsv; - - list_for_each_entry(rsv, &rc->reservations, rc_node) { - if (rsv->owner == uwb_dev - || (rsv->target.type == UWB_RSV_TARGET_DEV && rsv->target.dev == uwb_dev)) - uwb_rsv_remove(rsv); - } -} - - -/** - * uwbd_evt_handle_rc_drp - handle a DRP_IE event - * @evt: the DRP_IE event from the radio controller - * - * This processes DRP notifications from the radio controller, either - * initiating a new reservation or transitioning an existing - * reservation into a different state. - * - * DRP notifications can occur for three different reasons: - * - * - UWB_DRP_NOTIF_DRP_IE_RECVD: one or more DRP IEs with the RC as - * the target or source have been recieved. - * - * These DRP IEs could be new or for an existing reservation. - * - * If the DRP IE for an existing reservation ceases to be to - * recieved for at least mMaxLostBeacons, the reservation should be - * considered to be terminated. Note that the TERMINATE reason (see - * below) may not always be signalled (e.g., the remote device has - * two or more reservations established with the RC). - * - * - UWB_DRP_NOTIF_CONFLICT: DRP IEs from any device in the beacon - * group conflict with the RC's reservations. - * - * - UWB_DRP_NOTIF_TERMINATE: DRP IEs are no longer being received - * from a device (i.e., it's terminated all reservations). - * - * Only the software state of the reservations is changed; the setting - * of the radio controller's DRP IEs is done after all the events in - * an event buffer are processed. This saves waiting multiple times - * for the SET_DRP_IE command to complete. - */ -int uwbd_evt_handle_rc_drp(struct uwb_event *evt) -{ - struct device *dev = &evt->rc->uwb_dev.dev; - struct uwb_rc *rc = evt->rc; - struct uwb_rc_evt_drp *drp_evt; - size_t ielength, bytes_left; - struct uwb_dev_addr src_addr; - struct uwb_dev *src_dev; - int reason; - - /* Is there enough data to decode the event (and any IEs in - its payload)? */ - if (evt->notif.size < sizeof(*drp_evt)) { - dev_err(dev, "DRP event: Not enough data to decode event " - "[%zu bytes left, %zu needed]\n", - evt->notif.size, sizeof(*drp_evt)); - return 0; - } - bytes_left = evt->notif.size - sizeof(*drp_evt); - drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp, rceb); - ielength = le16_to_cpu(drp_evt->ie_length); - if (bytes_left != ielength) { - dev_err(dev, "DRP event: Not enough data in payload [%zu" - "bytes left, %zu declared in the event]\n", - bytes_left, ielength); - return 0; - } - - memcpy(src_addr.data, &drp_evt->src_addr, sizeof(src_addr)); - src_dev = uwb_dev_get_by_devaddr(rc, &src_addr); - if (!src_dev) { - /* - * A DRP notification from an unrecognized device. - * - * This is probably from a WUSB device that doesn't - * have an EUI-48 and therefore doesn't show up in the - * UWB device database. It's safe to simply ignore - * these. - */ - return 0; - } - - mutex_lock(&rc->rsvs_mutex); - - reason = uwb_rc_evt_drp_reason(drp_evt); - - switch (reason) { - case UWB_DRP_NOTIF_DRP_IE_RCVD: - uwb_drp_process_all(rc, drp_evt, ielength, src_dev); - break; - case UWB_DRP_NOTIF_CONFLICT: - uwb_drp_process_conflict_all(rc, drp_evt, ielength, src_dev); - break; - case UWB_DRP_NOTIF_TERMINATE: - uwb_drp_terminate_all(rc, src_dev); - break; - default: - dev_warn(dev, "ignored DRP event with reason code: %d\n", reason); - break; - } - - mutex_unlock(&rc->rsvs_mutex); - - uwb_dev_put(src_dev); - return 0; -} diff --git a/trunk/drivers/uwb/est.c b/trunk/drivers/uwb/est.c deleted file mode 100644 index 5fe566b7c845..000000000000 --- a/trunk/drivers/uwb/est.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Ultra Wide Band Radio Control - * Event Size Tables management - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * Infrastructure, code and data tables for guessing the size of - * events received on the notification endpoints of UWB radio - * controllers. - * - * You define a table of events and for each, its size and how to get - * the extra size. - * - * ENTRY POINTS: - * - * uwb_est_{init/destroy}(): To initialize/release the EST subsystem. - * - * uwb_est_[u]register(): To un/register event size tables - * uwb_est_grow() - * - * uwb_est_find_size(): Get the size of an event - * uwb_est_get_size() - */ -#include -#define D_LOCAL 0 -#include -#include "uwb-internal.h" - - -struct uwb_est { - u16 type_event_high; - u16 vendor, product; - u8 entries; - const struct uwb_est_entry *entry; -}; - - -static struct uwb_est *uwb_est; -static u8 uwb_est_size; -static u8 uwb_est_used; -static DEFINE_RWLOCK(uwb_est_lock); - -/** - * WUSB Standard Event Size Table, HWA-RC interface - * - * Sizes for events and notifications type 0 (general), high nibble 0. - */ -static -struct uwb_est_entry uwb_est_00_00xx[] = { - [UWB_RC_EVT_IE_RCV] = { - .size = sizeof(struct uwb_rc_evt_ie_rcv), - .offset = 1 + offsetof(struct uwb_rc_evt_ie_rcv, wIELength), - }, - [UWB_RC_EVT_BEACON] = { - .size = sizeof(struct uwb_rc_evt_beacon), - .offset = 1 + offsetof(struct uwb_rc_evt_beacon, wBeaconInfoLength), - }, - [UWB_RC_EVT_BEACON_SIZE] = { - .size = sizeof(struct uwb_rc_evt_beacon_size), - }, - [UWB_RC_EVT_BPOIE_CHANGE] = { - .size = sizeof(struct uwb_rc_evt_bpoie_change), - .offset = 1 + offsetof(struct uwb_rc_evt_bpoie_change, - wBPOIELength), - }, - [UWB_RC_EVT_BP_SLOT_CHANGE] = { - .size = sizeof(struct uwb_rc_evt_bp_slot_change), - }, - [UWB_RC_EVT_BP_SWITCH_IE_RCV] = { - .size = sizeof(struct uwb_rc_evt_bp_switch_ie_rcv), - .offset = 1 + offsetof(struct uwb_rc_evt_bp_switch_ie_rcv, wIELength), - }, - [UWB_RC_EVT_DEV_ADDR_CONFLICT] = { - .size = sizeof(struct uwb_rc_evt_dev_addr_conflict), - }, - [UWB_RC_EVT_DRP_AVAIL] = { - .size = sizeof(struct uwb_rc_evt_drp_avail) - }, - [UWB_RC_EVT_DRP] = { - .size = sizeof(struct uwb_rc_evt_drp), - .offset = 1 + offsetof(struct uwb_rc_evt_drp, ie_length), - }, - [UWB_RC_EVT_BP_SWITCH_STATUS] = { - .size = sizeof(struct uwb_rc_evt_bp_switch_status), - }, - [UWB_RC_EVT_CMD_FRAME_RCV] = { - .size = sizeof(struct uwb_rc_evt_cmd_frame_rcv), - .offset = 1 + offsetof(struct uwb_rc_evt_cmd_frame_rcv, dataLength), - }, - [UWB_RC_EVT_CHANNEL_CHANGE_IE_RCV] = { - .size = sizeof(struct uwb_rc_evt_channel_change_ie_rcv), - .offset = 1 + offsetof(struct uwb_rc_evt_channel_change_ie_rcv, wIELength), - }, - [UWB_RC_CMD_CHANNEL_CHANGE] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_DEV_ADDR_MGMT] = { - .size = sizeof(struct uwb_rc_evt_dev_addr_mgmt) }, - [UWB_RC_CMD_GET_IE] = { - .size = sizeof(struct uwb_rc_evt_get_ie), - .offset = 1 + offsetof(struct uwb_rc_evt_get_ie, wIELength), - }, - [UWB_RC_CMD_RESET] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SCAN] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SET_BEACON_FILTER] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SET_DRP_IE] = { - .size = sizeof(struct uwb_rc_evt_set_drp_ie), - }, - [UWB_RC_CMD_SET_IE] = { - .size = sizeof(struct uwb_rc_evt_set_ie), - }, - [UWB_RC_CMD_SET_NOTIFICATION_FILTER] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SET_TX_POWER] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SLEEP] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_START_BEACON] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_STOP_BEACON] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_BP_MERGE] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SEND_COMMAND_FRAME] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, - [UWB_RC_CMD_SET_ASIE_NOTIF] = { - .size = sizeof(struct uwb_rc_evt_confirm), - }, -}; - -static -struct uwb_est_entry uwb_est_01_00xx[] = { - [UWB_RC_DAA_ENERGY_DETECTED] = { - .size = sizeof(struct uwb_rc_evt_daa_energy_detected), - }, - [UWB_RC_SET_DAA_ENERGY_MASK] = { - .size = sizeof(struct uwb_rc_evt_set_daa_energy_mask), - }, - [UWB_RC_SET_NOTIFICATION_FILTER_EX] = { - .size = sizeof(struct uwb_rc_evt_set_notification_filter_ex), - }, -}; - -/** - * Initialize the EST subsystem - * - * Register the standard tables also. - * - * FIXME: tag init - */ -int uwb_est_create(void) -{ - int result; - - uwb_est_size = 2; - uwb_est_used = 0; - uwb_est = kzalloc(uwb_est_size * sizeof(uwb_est[0]), GFP_KERNEL); - if (uwb_est == NULL) - return -ENOMEM; - - result = uwb_est_register(UWB_RC_CET_GENERAL, 0, 0xffff, 0xffff, - uwb_est_00_00xx, ARRAY_SIZE(uwb_est_00_00xx)); - if (result < 0) - goto out; - result = uwb_est_register(UWB_RC_CET_EX_TYPE_1, 0, 0xffff, 0xffff, - uwb_est_01_00xx, ARRAY_SIZE(uwb_est_01_00xx)); -out: - return result; -} - - -/** Clean it up */ -void uwb_est_destroy(void) -{ - kfree(uwb_est); - uwb_est = NULL; - uwb_est_size = uwb_est_used = 0; -} - - -/** - * Double the capacity of the EST table - * - * @returns 0 if ok, < 0 errno no error. - */ -static -int uwb_est_grow(void) -{ - size_t actual_size = uwb_est_size * sizeof(uwb_est[0]); - void *new = kmalloc(2 * actual_size, GFP_ATOMIC); - if (new == NULL) - return -ENOMEM; - memcpy(new, uwb_est, actual_size); - memset(new + actual_size, 0, actual_size); - kfree(uwb_est); - uwb_est = new; - uwb_est_size *= 2; - return 0; -} - - -/** - * Register an event size table - * - * Makes room for it if the table is full, and then inserts it in the - * right position (entries are sorted by type, event_high, vendor and - * then product). - * - * @vendor: vendor code for matching against the device (0x0000 and - * 0xffff mean any); use 0x0000 to force all to match without - * checking possible vendor specific ones, 0xfffff to match - * after checking vendor specific ones. - * - * @product: product code from that vendor; same matching rules, use - * 0x0000 for not allowing vendor specific matches, 0xffff - * for allowing. - * - * This arragement just makes the tables sort differenty. Because the - * table is sorted by growing type-event_high-vendor-product, a zero - * vendor will match before than a 0x456a vendor, that will match - * before a 0xfffff vendor. - * - * @returns 0 if ok, < 0 errno on error (-ENOENT if not found). - */ -/* FIXME: add bus type to vendor/product code */ -int uwb_est_register(u8 type, u8 event_high, u16 vendor, u16 product, - const struct uwb_est_entry *entry, size_t entries) -{ - unsigned long flags; - unsigned itr; - u16 type_event_high; - int result = 0; - - write_lock_irqsave(&uwb_est_lock, flags); - if (uwb_est_used == uwb_est_size) { - result = uwb_est_grow(); - if (result < 0) - goto out; - } - /* Find the right spot to insert it in */ - type_event_high = type << 8 | event_high; - for (itr = 0; itr < uwb_est_used; itr++) - if (uwb_est[itr].type_event_high < type - && uwb_est[itr].vendor < vendor - && uwb_est[itr].product < product) - break; - - /* Shift others to make room for the new one? */ - if (itr < uwb_est_used) - memmove(&uwb_est[itr+1], &uwb_est[itr], uwb_est_used - itr); - uwb_est[itr].type_event_high = type << 8 | event_high; - uwb_est[itr].vendor = vendor; - uwb_est[itr].product = product; - uwb_est[itr].entry = entry; - uwb_est[itr].entries = entries; - uwb_est_used++; -out: - write_unlock_irqrestore(&uwb_est_lock, flags); - return result; -} -EXPORT_SYMBOL_GPL(uwb_est_register); - - -/** - * Unregister an event size table - * - * This just removes the specified entry and moves the ones after it - * to fill in the gap. This is needed to keep the list sorted; no - * reallocation is done to reduce the size of the table. - * - * We unregister by all the data we used to register instead of by - * pointer to the @entry array because we might have used the same - * table for a bunch of IDs (for example). - * - * @returns 0 if ok, < 0 errno on error (-ENOENT if not found). - */ -int uwb_est_unregister(u8 type, u8 event_high, u16 vendor, u16 product, - const struct uwb_est_entry *entry, size_t entries) -{ - unsigned long flags; - unsigned itr; - struct uwb_est est_cmp = { - .type_event_high = type << 8 | event_high, - .vendor = vendor, - .product = product, - .entry = entry, - .entries = entries - }; - write_lock_irqsave(&uwb_est_lock, flags); - for (itr = 0; itr < uwb_est_used; itr++) - if (!memcmp(&uwb_est[itr], &est_cmp, sizeof(est_cmp))) - goto found; - write_unlock_irqrestore(&uwb_est_lock, flags); - return -ENOENT; - -found: - if (itr < uwb_est_used - 1) /* Not last one? move ones above */ - memmove(&uwb_est[itr], &uwb_est[itr+1], uwb_est_used - itr - 1); - uwb_est_used--; - write_unlock_irqrestore(&uwb_est_lock, flags); - return 0; -} -EXPORT_SYMBOL_GPL(uwb_est_unregister); - - -/** - * Get the size of an event from a table - * - * @rceb: pointer to the buffer with the event - * @rceb_size: size of the area pointed to by @rceb in bytes. - * @returns: > 0 Size of the event - * -ENOSPC An area big enough was not provided to look - * ahead into the event's guts and guess the size. - * -EINVAL Unknown event code (wEvent). - * - * This will look at the received RCEB and guess what is the total - * size. For variable sized events, it will look further ahead into - * their length field to see how much data should be read. - * - * Note this size is *not* final--the neh (Notification/Event Handle) - * might specificy an extra size to add. - */ -static -ssize_t uwb_est_get_size(struct uwb_rc *uwb_rc, struct uwb_est *est, - u8 event_low, const struct uwb_rceb *rceb, - size_t rceb_size) -{ - unsigned offset; - ssize_t size; - struct device *dev = &uwb_rc->uwb_dev.dev; - const struct uwb_est_entry *entry; - - size = -ENOENT; - if (event_low >= est->entries) { /* in range? */ - dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: event %u out of range\n", - est, est->type_event_high, est->vendor, est->product, - est->entries, event_low); - goto out; - } - size = -ENOENT; - entry = &est->entry[event_low]; - if (entry->size == 0 && entry->offset == 0) { /* unknown? */ - dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: event %u unknown\n", - est, est->type_event_high, est->vendor, est->product, - est->entries, event_low); - goto out; - } - offset = entry->offset; /* extra fries with that? */ - if (offset == 0) - size = entry->size; - else { - /* Ops, got an extra size field at 'offset'--read it */ - const void *ptr = rceb; - size_t type_size = 0; - offset--; - size = -ENOSPC; /* enough data for more? */ - switch (entry->type) { - case UWB_EST_16: type_size = sizeof(__le16); break; - case UWB_EST_8: type_size = sizeof(u8); break; - default: BUG(); - } - if (offset + type_size > rceb_size) { - dev_err(dev, "EST %p 0x%04x/%04x/%04x[%u]: " - "not enough data to read extra size\n", - est, est->type_event_high, est->vendor, - est->product, est->entries); - goto out; - } - size = entry->size; - ptr += offset; - switch (entry->type) { - case UWB_EST_16: size += le16_to_cpu(*(__le16 *)ptr); break; - case UWB_EST_8: size += *(u8 *)ptr; break; - default: BUG(); - } - } -out: - return size; -} - - -/** - * Guesses the size of a WA event - * - * @rceb: pointer to the buffer with the event - * @rceb_size: size of the area pointed to by @rceb in bytes. - * @returns: > 0 Size of the event - * -ENOSPC An area big enough was not provided to look - * ahead into the event's guts and guess the size. - * -EINVAL Unknown event code (wEvent). - * - * This will look at the received RCEB and guess what is the total - * size by checking all the tables registered with - * uwb_est_register(). For variable sized events, it will look further - * ahead into their length field to see how much data should be read. - * - * Note this size is *not* final--the neh (Notification/Event Handle) - * might specificy an extra size to add or replace. - */ -ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, - size_t rceb_size) -{ - /* FIXME: add vendor/product data */ - ssize_t size; - struct device *dev = &rc->uwb_dev.dev; - unsigned long flags; - unsigned itr; - u16 type_event_high, event; - u8 *ptr = (u8 *) rceb; - - read_lock_irqsave(&uwb_est_lock, flags); - d_printf(2, dev, "Size query for event 0x%02x/%04x/%02x," - " buffer size %ld\n", - (unsigned) rceb->bEventType, - (unsigned) le16_to_cpu(rceb->wEvent), - (unsigned) rceb->bEventContext, - (long) rceb_size); - size = -ENOSPC; - if (rceb_size < sizeof(*rceb)) - goto out; - event = le16_to_cpu(rceb->wEvent); - type_event_high = rceb->bEventType << 8 | (event & 0xff00) >> 8; - for (itr = 0; itr < uwb_est_used; itr++) { - d_printf(3, dev, "Checking EST 0x%04x/%04x/%04x\n", - uwb_est[itr].type_event_high, uwb_est[itr].vendor, - uwb_est[itr].product); - if (uwb_est[itr].type_event_high != type_event_high) - continue; - size = uwb_est_get_size(rc, &uwb_est[itr], - event & 0x00ff, rceb, rceb_size); - /* try more tables that might handle the same type */ - if (size != -ENOENT) - goto out; - } - dev_dbg(dev, "event 0x%02x/%04x/%02x: no handlers available; " - "RCEB %02x %02x %02x %02x\n", - (unsigned) rceb->bEventType, - (unsigned) le16_to_cpu(rceb->wEvent), - (unsigned) rceb->bEventContext, - ptr[0], ptr[1], ptr[2], ptr[3]); - size = -ENOENT; -out: - read_unlock_irqrestore(&uwb_est_lock, flags); - return size; -} -EXPORT_SYMBOL_GPL(uwb_est_find_size); diff --git a/trunk/drivers/uwb/hwa-rc.c b/trunk/drivers/uwb/hwa-rc.c deleted file mode 100644 index 3d26fa0f8ae1..000000000000 --- a/trunk/drivers/uwb/hwa-rc.c +++ /dev/null @@ -1,926 +0,0 @@ -/* - * WUSB Host Wire Adapter: Radio Control Interface (WUSB[8.6]) - * Radio Control command/event transport - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Initialize the Radio Control interface Driver. - * - * For each device probed, creates an 'struct hwarc' which contains - * just the representation of the UWB Radio Controller, and the logic - * for reading notifications and passing them to the UWB Core. - * - * So we initialize all of those, register the UWB Radio Controller - * and setup the notification/event handle to pipe the notifications - * to the UWB management Daemon. - * - * Command and event filtering. - * - * This is the driver for the Radio Control Interface described in WUSB - * 1.0. The core UWB module assumes that all drivers are compliant to the - * WHCI 0.95 specification. We thus create a filter that parses all - * incoming messages from the (WUSB 1.0) device and manipulate them to - * conform to the WHCI 0.95 specification. Similarly, outgoing messages - * are parsed and manipulated to conform to the WUSB 1.0 compliant messages - * that the device expects. Only a few messages are affected: - * Affected events: - * UWB_RC_EVT_BEACON - * UWB_RC_EVT_BP_SLOT_CHANGE - * UWB_RC_EVT_DRP_AVAIL - * UWB_RC_EVT_DRP - * Affected commands: - * UWB_RC_CMD_SCAN - * UWB_RC_CMD_SET_DRP_IE - * - * - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "uwb-internal.h" -#define D_LOCAL 1 -#include - -/* The device uses commands and events from the WHCI specification, although - * reporting itself as WUSB compliant. */ -#define WUSB_QUIRK_WHCI_CMD_EVT 0x01 - -/** - * Descriptor for an instance of the UWB Radio Control Driver that - * attaches to the RCI interface of the Host Wired Adapter. - * - * Unless there is a lock specific to the 'data members', all access - * is protected by uwb_rc->mutex. - * - * The NEEP (Notification/Event EndPoint) URB (@neep_urb) writes to - * @rd_buffer. Note there is no locking because it is perfectly (heh!) - * serialized--probe() submits an URB, callback is called, processes - * the data (synchronously), submits another URB, and so on. There is - * no concurrent access to the buffer. - */ -struct hwarc { - struct usb_device *usb_dev; - struct usb_interface *usb_iface; - struct uwb_rc *uwb_rc; /* UWB host controller */ - struct urb *neep_urb; /* Notification endpoint handling */ - struct edc neep_edc; - void *rd_buffer; /* NEEP read buffer */ -}; - - -/* Beacon received notification (WUSB 1.0 [8.6.3.2]) */ -struct uwb_rc_evt_beacon_WUSB_0100 { - struct uwb_rceb rceb; - u8 bChannelNumber; - __le16 wBPSTOffset; - u8 bLQI; - u8 bRSSI; - __le16 wBeaconInfoLength; - u8 BeaconInfo[]; -} __attribute__((packed)); - -/** - * Filter WUSB 1.0 BEACON RCV notification to be WHCI 0.95 - * - * @header: the incoming event - * @buf_size: size of buffer containing incoming event - * @new_size: size of event after filtering completed - * - * The WHCI 0.95 spec has a "Beacon Type" field. This value is unknown at - * the time we receive the beacon from WUSB so we just set it to - * UWB_RC_BEACON_TYPE_NEIGHBOR as a default. - * The solution below allocates memory upon receipt of every beacon from a - * WUSB device. This will deteriorate performance. What is the right way to - * do this? - */ -static -int hwarc_filter_evt_beacon_WUSB_0100(struct uwb_rc *rc, - struct uwb_rceb **header, - const size_t buf_size, - size_t *new_size) -{ - struct uwb_rc_evt_beacon_WUSB_0100 *be; - struct uwb_rc_evt_beacon *newbe; - size_t bytes_left, ielength; - struct device *dev = &rc->uwb_dev.dev; - - be = container_of(*header, struct uwb_rc_evt_beacon_WUSB_0100, rceb); - bytes_left = buf_size; - if (bytes_left < sizeof(*be)) { - dev_err(dev, "Beacon Received Notification: Not enough data " - "to decode for filtering (%zu vs %zu bytes needed)\n", - bytes_left, sizeof(*be)); - return -EINVAL; - } - bytes_left -= sizeof(*be); - ielength = le16_to_cpu(be->wBeaconInfoLength); - if (bytes_left < ielength) { - dev_err(dev, "Beacon Received Notification: Not enough data " - "to decode IEs (%zu vs %zu bytes needed)\n", - bytes_left, ielength); - return -EINVAL; - } - newbe = kzalloc(sizeof(*newbe) + ielength, GFP_ATOMIC); - if (newbe == NULL) - return -ENOMEM; - newbe->rceb = be->rceb; - newbe->bChannelNumber = be->bChannelNumber; - newbe->bBeaconType = UWB_RC_BEACON_TYPE_NEIGHBOR; - newbe->wBPSTOffset = be->wBPSTOffset; - newbe->bLQI = be->bLQI; - newbe->bRSSI = be->bRSSI; - newbe->wBeaconInfoLength = be->wBeaconInfoLength; - memcpy(newbe->BeaconInfo, be->BeaconInfo, ielength); - *header = &newbe->rceb; - *new_size = sizeof(*newbe) + ielength; - return 1; /* calling function will free memory */ -} - - -/* DRP Availability change notification (WUSB 1.0 [8.6.3.8]) */ -struct uwb_rc_evt_drp_avail_WUSB_0100 { - struct uwb_rceb rceb; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/** - * Filter WUSB 1.0 DRP AVAILABILITY CHANGE notification to be WHCI 0.95 - * - * @header: the incoming event - * @buf_size: size of buffer containing incoming event - * @new_size: size of event after filtering completed - */ -static -int hwarc_filter_evt_drp_avail_WUSB_0100(struct uwb_rc *rc, - struct uwb_rceb **header, - const size_t buf_size, - size_t *new_size) -{ - struct uwb_rc_evt_drp_avail_WUSB_0100 *da; - struct uwb_rc_evt_drp_avail *newda; - struct uwb_ie_hdr *ie_hdr; - size_t bytes_left, ielength; - struct device *dev = &rc->uwb_dev.dev; - - - da = container_of(*header, struct uwb_rc_evt_drp_avail_WUSB_0100, rceb); - bytes_left = buf_size; - if (bytes_left < sizeof(*da)) { - dev_err(dev, "Not enough data to decode DRP Avail " - "Notification for filtering. Expected %zu, " - "received %zu.\n", (size_t)sizeof(*da), bytes_left); - return -EINVAL; - } - bytes_left -= sizeof(*da); - ielength = le16_to_cpu(da->wIELength); - if (bytes_left < ielength) { - dev_err(dev, "DRP Avail Notification filter: IE length " - "[%zu bytes] does not match actual length " - "[%zu bytes].\n", ielength, bytes_left); - return -EINVAL; - } - if (ielength < sizeof(*ie_hdr)) { - dev_err(dev, "DRP Avail Notification filter: Not enough " - "data to decode IE [%zu bytes, %zu needed]\n", - ielength, sizeof(*ie_hdr)); - return -EINVAL; - } - ie_hdr = (void *) da->IEData; - if (ie_hdr->length > 32) { - dev_err(dev, "DRP Availability Change event has unexpected " - "length for filtering. Expected < 32 bytes, " - "got %zu bytes.\n", (size_t)ie_hdr->length); - return -EINVAL; - } - newda = kzalloc(sizeof(*newda), GFP_ATOMIC); - if (newda == NULL) - return -ENOMEM; - newda->rceb = da->rceb; - memcpy(newda->bmp, (u8 *) ie_hdr + sizeof(*ie_hdr), ie_hdr->length); - *header = &newda->rceb; - *new_size = sizeof(*newda); - return 1; /* calling function will free memory */ -} - - -/* DRP notification (WUSB 1.0 [8.6.3.9]) */ -struct uwb_rc_evt_drp_WUSB_0100 { - struct uwb_rceb rceb; - struct uwb_dev_addr wSrcAddr; - u8 bExplicit; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/** - * Filter WUSB 1.0 DRP Notification to be WHCI 0.95 - * - * @header: the incoming event - * @buf_size: size of buffer containing incoming event - * @new_size: size of event after filtering completed - * - * It is hard to manage DRP reservations without having a Reason code. - * Unfortunately there is none in the WUSB spec. We just set the default to - * DRP IE RECEIVED. - * We do not currently use the bBeaconSlotNumber value, so we set this to - * zero for now. - */ -static -int hwarc_filter_evt_drp_WUSB_0100(struct uwb_rc *rc, - struct uwb_rceb **header, - const size_t buf_size, - size_t *new_size) -{ - struct uwb_rc_evt_drp_WUSB_0100 *drpev; - struct uwb_rc_evt_drp *newdrpev; - size_t bytes_left, ielength; - struct device *dev = &rc->uwb_dev.dev; - - drpev = container_of(*header, struct uwb_rc_evt_drp_WUSB_0100, rceb); - bytes_left = buf_size; - if (bytes_left < sizeof(*drpev)) { - dev_err(dev, "Not enough data to decode DRP Notification " - "for filtering. Expected %zu, received %zu.\n", - (size_t)sizeof(*drpev), bytes_left); - return -EINVAL; - } - ielength = le16_to_cpu(drpev->wIELength); - bytes_left -= sizeof(*drpev); - if (bytes_left < ielength) { - dev_err(dev, "DRP Notification filter: header length [%zu " - "bytes] does not match actual length [%zu " - "bytes].\n", ielength, bytes_left); - return -EINVAL; - } - newdrpev = kzalloc(sizeof(*newdrpev) + ielength, GFP_ATOMIC); - if (newdrpev == NULL) - return -ENOMEM; - newdrpev->rceb = drpev->rceb; - newdrpev->src_addr = drpev->wSrcAddr; - newdrpev->reason = UWB_DRP_NOTIF_DRP_IE_RCVD; - newdrpev->beacon_slot_number = 0; - newdrpev->ie_length = drpev->wIELength; - memcpy(newdrpev->ie_data, drpev->IEData, ielength); - *header = &newdrpev->rceb; - *new_size = sizeof(*newdrpev) + ielength; - return 1; /* calling function will free memory */ -} - - -/* Scan Command (WUSB 1.0 [8.6.2.5]) */ -struct uwb_rc_cmd_scan_WUSB_0100 { - struct uwb_rccb rccb; - u8 bChannelNumber; - u8 bScanState; -} __attribute__((packed)); - -/** - * Filter WHCI 0.95 SCAN command to be WUSB 1.0 SCAN command - * - * @header: command sent to device (compliant to WHCI 0.95) - * @size: size of command sent to device - * - * We only reduce the size by two bytes because the WUSB 1.0 scan command - * does not have the last field (wStarttime). Also, make sure we don't send - * the device an unexpected scan type. - */ -static -int hwarc_filter_cmd_scan_WUSB_0100(struct uwb_rc *rc, - struct uwb_rccb **header, - size_t *size) -{ - struct uwb_rc_cmd_scan *sc; - - sc = container_of(*header, struct uwb_rc_cmd_scan, rccb); - - if (sc->bScanState == UWB_SCAN_ONLY_STARTTIME) - sc->bScanState = UWB_SCAN_ONLY; - /* Don't send the last two bytes. */ - *size -= 2; - return 0; -} - - -/* SET DRP IE command (WUSB 1.0 [8.6.2.7]) */ -struct uwb_rc_cmd_set_drp_ie_WUSB_0100 { - struct uwb_rccb rccb; - u8 bExplicit; - __le16 wIELength; - struct uwb_ie_drp IEData[]; -} __attribute__((packed)); - -/** - * Filter WHCI 0.95 SET DRP IE command to be WUSB 1.0 SET DRP IE command - * - * @header: command sent to device (compliant to WHCI 0.95) - * @size: size of command sent to device - * - * WUSB has an extra bExplicit field - we assume always explicit - * negotiation so this field is set. The command expected by the device is - * thus larger than the one prepared by the driver so we need to - * reallocate memory to accommodate this. - * We trust the driver to send us the correct data so no checking is done - * on incoming data - evn though it is variable length. - */ -static -int hwarc_filter_cmd_set_drp_ie_WUSB_0100(struct uwb_rc *rc, - struct uwb_rccb **header, - size_t *size) -{ - struct uwb_rc_cmd_set_drp_ie *orgcmd; - struct uwb_rc_cmd_set_drp_ie_WUSB_0100 *cmd; - size_t ielength; - - orgcmd = container_of(*header, struct uwb_rc_cmd_set_drp_ie, rccb); - ielength = le16_to_cpu(orgcmd->wIELength); - cmd = kzalloc(sizeof(*cmd) + ielength, GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - cmd->rccb = orgcmd->rccb; - cmd->bExplicit = 0; - cmd->wIELength = orgcmd->wIELength; - memcpy(cmd->IEData, orgcmd->IEData, ielength); - *header = &cmd->rccb; - *size = sizeof(*cmd) + ielength; - return 1; /* calling function will free memory */ -} - - -/** - * Filter data from WHCI driver to WUSB device - * - * @header: WHCI 0.95 compliant command from driver - * @size: length of command - * - * The routine managing commands to the device (uwb_rc_cmd()) will call the - * filtering function pointer (if it exists) before it passes any data to - * the device. At this time the command has been formatted according to - * WHCI 0.95 and is ready to be sent to the device. - * - * The filter function will be provided with the current command and its - * length. The function will manipulate the command if necessary and - * potentially reallocate memory for a command that needed more memory that - * the given command. If new memory was created the function will return 1 - * to indicate to the calling function that the memory need to be freed - * when not needed any more. The size will contain the new length of the - * command. - * If memory has not been allocated we rely on the original mechanisms to - * free the memory of the command - even when we reduce the value of size. - */ -static -int hwarc_filter_cmd_WUSB_0100(struct uwb_rc *rc, struct uwb_rccb **header, - size_t *size) -{ - int result; - struct uwb_rccb *rccb = *header; - int cmd = le16_to_cpu(rccb->wCommand); - switch (cmd) { - case UWB_RC_CMD_SCAN: - result = hwarc_filter_cmd_scan_WUSB_0100(rc, header, size); - break; - case UWB_RC_CMD_SET_DRP_IE: - result = hwarc_filter_cmd_set_drp_ie_WUSB_0100(rc, header, size); - break; - default: - result = -ENOANO; - break; - } - return result; -} - - -/** - * Filter data from WHCI driver to WUSB device - * - * @header: WHCI 0.95 compliant command from driver - * @size: length of command - * - * Filter commands based on which protocol the device supports. The WUSB - * errata should be the same as WHCI 0.95 so we do not filter that here - - * only WUSB 1.0. - */ -static -int hwarc_filter_cmd(struct uwb_rc *rc, struct uwb_rccb **header, - size_t *size) -{ - int result = -ENOANO; - if (rc->version == 0x0100) - result = hwarc_filter_cmd_WUSB_0100(rc, header, size); - return result; -} - - -/** - * Compute return value as sum of incoming value and value at given offset - * - * @rceb: event for which we compute the size, it contains a variable - * length field. - * @core_size: size of the "non variable" part of the event - * @offset: place in event where the length of the variable part is stored - * @buf_size: total length of buffer in which event arrived - we need to make - * sure we read the offset in memory that is still part of the event - */ -static -ssize_t hwarc_get_event_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, - size_t core_size, size_t offset, - const size_t buf_size) -{ - ssize_t size = -ENOSPC; - const void *ptr = rceb; - size_t type_size = sizeof(__le16); - struct device *dev = &rc->uwb_dev.dev; - - if (offset + type_size >= buf_size) { - dev_err(dev, "Not enough data to read extra size of event " - "0x%02x/%04x/%02x, only got %zu bytes.\n", - rceb->bEventType, le16_to_cpu(rceb->wEvent), - rceb->bEventContext, buf_size); - goto out; - } - ptr += offset; - size = core_size + le16_to_cpu(*(__le16 *)ptr); -out: - return size; -} - - -/* Beacon slot change notification (WUSB 1.0 [8.6.3.5]) */ -struct uwb_rc_evt_bp_slot_change_WUSB_0100 { - struct uwb_rceb rceb; - u8 bSlotNumber; -} __attribute__((packed)); - - -/** - * Filter data from WUSB device to WHCI driver - * - * @header: incoming event - * @buf_size: size of buffer in which event arrived - * @_event_size: actual size of event in the buffer - * @new_size: size of event after filtered - * - * We don't know how the buffer is constructed - there may be more than one - * event in it so buffer length does not determine event length. We first - * determine the expected size of the incoming event. This value is passed - * back only if the actual filtering succeeded (so we know the computed - * expected size is correct). This value will be zero if - * the event did not need any filtering. - * - * WHCI interprets the BP Slot Change event's data differently than - * WUSB. The event sizes are exactly the same. The data field - * indicates the new beacon slot in which a RC is transmitting its - * beacon. The maximum value of this is 96 (wMacBPLength ECMA-368 - * 17.16 (Table 117)). We thus know that the WUSB value will not set - * the bit bNoSlot, so we don't really do anything (placeholder). - */ -static -int hwarc_filter_event_WUSB_0100(struct uwb_rc *rc, struct uwb_rceb **header, - const size_t buf_size, size_t *_real_size, - size_t *_new_size) -{ - int result = -ENOANO; - struct uwb_rceb *rceb = *header; - int event = le16_to_cpu(rceb->wEvent); - size_t event_size; - size_t core_size, offset; - - if (rceb->bEventType != UWB_RC_CET_GENERAL) - goto out; - switch (event) { - case UWB_RC_EVT_BEACON: - core_size = sizeof(struct uwb_rc_evt_beacon_WUSB_0100); - offset = offsetof(struct uwb_rc_evt_beacon_WUSB_0100, - wBeaconInfoLength); - event_size = hwarc_get_event_size(rc, rceb, core_size, - offset, buf_size); - if (event_size < 0) - goto out; - *_real_size = event_size; - result = hwarc_filter_evt_beacon_WUSB_0100(rc, header, - buf_size, _new_size); - break; - case UWB_RC_EVT_BP_SLOT_CHANGE: - *_new_size = *_real_size = - sizeof(struct uwb_rc_evt_bp_slot_change_WUSB_0100); - result = 0; - break; - - case UWB_RC_EVT_DRP_AVAIL: - core_size = sizeof(struct uwb_rc_evt_drp_avail_WUSB_0100); - offset = offsetof(struct uwb_rc_evt_drp_avail_WUSB_0100, - wIELength); - event_size = hwarc_get_event_size(rc, rceb, core_size, - offset, buf_size); - if (event_size < 0) - goto out; - *_real_size = event_size; - result = hwarc_filter_evt_drp_avail_WUSB_0100( - rc, header, buf_size, _new_size); - break; - - case UWB_RC_EVT_DRP: - core_size = sizeof(struct uwb_rc_evt_drp_WUSB_0100); - offset = offsetof(struct uwb_rc_evt_drp_WUSB_0100, wIELength); - event_size = hwarc_get_event_size(rc, rceb, core_size, - offset, buf_size); - if (event_size < 0) - goto out; - *_real_size = event_size; - result = hwarc_filter_evt_drp_WUSB_0100(rc, header, - buf_size, _new_size); - break; - - default: - break; - } -out: - return result; -} - -/** - * Filter data from WUSB device to WHCI driver - * - * @header: incoming event - * @buf_size: size of buffer in which event arrived - * @_event_size: actual size of event in the buffer - * @_new_size: size of event after filtered - * - * Filter events based on which protocol the device supports. The WUSB - * errata should be the same as WHCI 0.95 so we do not filter that here - - * only WUSB 1.0. - * - * If we don't handle it, we return -ENOANO (why the weird error code? - * well, so if I get it, I can pinpoint in the code that raised - * it...after all, not too many places use the higher error codes). - */ -static -int hwarc_filter_event(struct uwb_rc *rc, struct uwb_rceb **header, - const size_t buf_size, size_t *_real_size, - size_t *_new_size) -{ - int result = -ENOANO; - if (rc->version == 0x0100) - result = hwarc_filter_event_WUSB_0100( - rc, header, buf_size, _real_size, _new_size); - return result; -} - - -/** - * Execute an UWB RC command on HWA - * - * @rc: Instance of a Radio Controller that is a HWA - * @cmd: Buffer containing the RCCB and payload to execute - * @cmd_size: Size of the command buffer. - * - * NOTE: rc's mutex has to be locked - */ -static -int hwarc_cmd(struct uwb_rc *uwb_rc, const struct uwb_rccb *cmd, size_t cmd_size) -{ - struct hwarc *hwarc = uwb_rc->priv; - return usb_control_msg( - hwarc->usb_dev, usb_sndctrlpipe(hwarc->usb_dev, 0), - WA_EXEC_RC_CMD, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, hwarc->usb_iface->cur_altsetting->desc.bInterfaceNumber, - (void *) cmd, cmd_size, 100 /* FIXME: this is totally arbitrary */); -} - -static -int hwarc_reset(struct uwb_rc *uwb_rc) -{ - struct hwarc *hwarc = uwb_rc->priv; - return usb_reset_device(hwarc->usb_dev); -} - -/** - * Callback for the notification and event endpoint - * - * Check's that everything is fine and then passes the read data to - * the notification/event handling mechanism (neh). - */ -static -void hwarc_neep_cb(struct urb *urb) -{ - struct hwarc *hwarc = urb->context; - struct usb_interface *usb_iface = hwarc->usb_iface; - struct device *dev = &usb_iface->dev; - int result; - - switch (result = urb->status) { - case 0: - d_printf(3, dev, "NEEP: receive stat %d, %zu bytes\n", - urb->status, (size_t)urb->actual_length); - uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer, - urb->actual_length); - break; - case -ECONNRESET: /* Not an error, but a controlled situation; */ - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - d_printf(2, dev, "NEEP: URB reset/noent %d\n", urb->status); - goto out; - case -ESHUTDOWN: /* going away! */ - d_printf(2, dev, "NEEP: URB down %d\n", urb->status); - goto out; - default: /* On general errors, retry unless it gets ugly */ - if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) - goto error_exceeded; - dev_err(dev, "NEEP: URB error %d\n", urb->status); - } - result = usb_submit_urb(urb, GFP_ATOMIC); - d_printf(3, dev, "NEEP: submit %d\n", result); - if (result < 0) { - dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n", - result); - goto error; - } -out: - return; - -error_exceeded: - dev_err(dev, "NEEP: URB max acceptable errors " - "exceeded, resetting device\n"); -error: - uwb_rc_neh_error(hwarc->uwb_rc, result); - uwb_rc_reset_all(hwarc->uwb_rc); - return; -} - -static void hwarc_init(struct hwarc *hwarc) -{ - edc_init(&hwarc->neep_edc); -} - -/** - * Initialize the notification/event endpoint stuff - * - * Note this is effectively a parallel thread; it knows that - * hwarc->uwb_rc always exists because the existence of a 'hwarc' - * means that there is a reverence on the hwarc->uwb_rc (see - * _probe()), and thus _neep_cb() can execute safely. - */ -static int hwarc_neep_init(struct uwb_rc *rc) -{ - struct hwarc *hwarc = rc->priv; - struct usb_interface *iface = hwarc->usb_iface; - struct usb_device *usb_dev = interface_to_usbdev(iface); - struct device *dev = &iface->dev; - int result; - struct usb_endpoint_descriptor *epd; - - epd = &iface->cur_altsetting->endpoint[0].desc; - hwarc->rd_buffer = (void *) __get_free_page(GFP_KERNEL); - if (hwarc->rd_buffer == NULL) { - dev_err(dev, "Unable to allocate notification's read buffer\n"); - goto error_rd_buffer; - } - hwarc->neep_urb = usb_alloc_urb(0, GFP_KERNEL); - if (hwarc->neep_urb == NULL) { - dev_err(dev, "Unable to allocate notification URB\n"); - goto error_urb_alloc; - } - usb_fill_int_urb(hwarc->neep_urb, usb_dev, - usb_rcvintpipe(usb_dev, epd->bEndpointAddress), - hwarc->rd_buffer, PAGE_SIZE, - hwarc_neep_cb, hwarc, epd->bInterval); - result = usb_submit_urb(hwarc->neep_urb, GFP_ATOMIC); - if (result < 0) { - dev_err(dev, "Cannot submit notification URB: %d\n", result); - goto error_neep_submit; - } - return 0; - -error_neep_submit: - usb_free_urb(hwarc->neep_urb); -error_urb_alloc: - free_page((unsigned long)hwarc->rd_buffer); -error_rd_buffer: - return -ENOMEM; -} - - -/** Clean up all the notification endpoint resources */ -static void hwarc_neep_release(struct uwb_rc *rc) -{ - struct hwarc *hwarc = rc->priv; - - usb_kill_urb(hwarc->neep_urb); - usb_free_urb(hwarc->neep_urb); - free_page((unsigned long)hwarc->rd_buffer); -} - -/** - * Get the version from class-specific descriptor - * - * NOTE: this descriptor comes with the big bundled configuration - * descriptor that includes the interfaces' and endpoints', so - * we just look for it in the cached copy kept by the USB stack. - * - * NOTE2: We convert LE fields to CPU order. - */ -static int hwarc_get_version(struct uwb_rc *rc) -{ - int result; - - struct hwarc *hwarc = rc->priv; - struct uwb_rc_control_intf_class_desc *descr; - struct device *dev = &rc->uwb_dev.dev; - struct usb_device *usb_dev = hwarc->usb_dev; - char *itr; - struct usb_descriptor_header *hdr; - size_t itr_size, actconfig_idx; - u16 version; - - actconfig_idx = (usb_dev->actconfig - usb_dev->config) / - sizeof(usb_dev->config[0]); - itr = usb_dev->rawdescriptors[actconfig_idx]; - itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); - while (itr_size >= sizeof(*hdr)) { - hdr = (struct usb_descriptor_header *) itr; - d_printf(3, dev, "Extra device descriptor: " - "type %02x/%u bytes @ %zu (%zu left)\n", - hdr->bDescriptorType, hdr->bLength, - (itr - usb_dev->rawdescriptors[actconfig_idx]), - itr_size); - if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL) - goto found; - itr += hdr->bLength; - itr_size -= hdr->bLength; - } - dev_err(dev, "cannot find Radio Control Interface Class descriptor\n"); - return -ENODEV; - -found: - result = -EINVAL; - if (hdr->bLength > itr_size) { /* is it available? */ - dev_err(dev, "incomplete Radio Control Interface Class " - "descriptor (%zu bytes left, %u needed)\n", - itr_size, hdr->bLength); - goto error; - } - if (hdr->bLength < sizeof(*descr)) { - dev_err(dev, "short Radio Control Interface Class " - "descriptor\n"); - goto error; - } - descr = (struct uwb_rc_control_intf_class_desc *) hdr; - /* Make LE fields CPU order */ - version = __le16_to_cpu(descr->bcdRCIVersion); - if (version != 0x0100) { - dev_err(dev, "Device reports protocol version 0x%04x. We " - "do not support that. \n", version); - result = -EINVAL; - goto error; - } - rc->version = version; - d_printf(3, dev, "Device supports WUSB protocol version 0x%04x \n", - rc->version); - result = 0; -error: - return result; -} - -/* - * By creating a 'uwb_rc', we have a reference on it -- that reference - * is the one we drop when we disconnect. - * - * No need to switch altsettings; according to WUSB1.0[8.6.1.1], there - * is only one altsetting allowed. - */ -static int hwarc_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - int result; - struct uwb_rc *uwb_rc; - struct hwarc *hwarc; - struct device *dev = &iface->dev; - - result = -ENOMEM; - uwb_rc = uwb_rc_alloc(); - if (uwb_rc == NULL) { - dev_err(dev, "unable to allocate RC instance\n"); - goto error_rc_alloc; - } - hwarc = kzalloc(sizeof(*hwarc), GFP_KERNEL); - if (hwarc == NULL) { - dev_err(dev, "unable to allocate HWA RC instance\n"); - goto error_alloc; - } - hwarc_init(hwarc); - hwarc->usb_dev = usb_get_dev(interface_to_usbdev(iface)); - hwarc->usb_iface = usb_get_intf(iface); - hwarc->uwb_rc = uwb_rc; - - uwb_rc->owner = THIS_MODULE; - uwb_rc->start = hwarc_neep_init; - uwb_rc->stop = hwarc_neep_release; - uwb_rc->cmd = hwarc_cmd; - uwb_rc->reset = hwarc_reset; - if (id->driver_info & WUSB_QUIRK_WHCI_CMD_EVT) { - uwb_rc->filter_cmd = NULL; - uwb_rc->filter_event = NULL; - } else { - uwb_rc->filter_cmd = hwarc_filter_cmd; - uwb_rc->filter_event = hwarc_filter_event; - } - - result = uwb_rc_add(uwb_rc, dev, hwarc); - if (result < 0) - goto error_rc_add; - result = hwarc_get_version(uwb_rc); - if (result < 0) { - dev_err(dev, "cannot retrieve version of RC \n"); - goto error_get_version; - } - usb_set_intfdata(iface, hwarc); - return 0; - -error_get_version: - uwb_rc_rm(uwb_rc); -error_rc_add: - usb_put_intf(iface); - usb_put_dev(hwarc->usb_dev); -error_alloc: - uwb_rc_put(uwb_rc); -error_rc_alloc: - return result; -} - -static void hwarc_disconnect(struct usb_interface *iface) -{ - struct hwarc *hwarc = usb_get_intfdata(iface); - struct uwb_rc *uwb_rc = hwarc->uwb_rc; - - usb_set_intfdata(hwarc->usb_iface, NULL); - uwb_rc_rm(uwb_rc); - usb_put_intf(hwarc->usb_iface); - usb_put_dev(hwarc->usb_dev); - d_printf(1, &hwarc->usb_iface->dev, "freed hwarc %p\n", hwarc); - kfree(hwarc); - uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ -} - -/** USB device ID's that we handle */ -static struct usb_device_id hwarc_id_table[] = { - /* D-Link DUB-1210 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3d02, 0xe0, 0x01, 0x02), - .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, - /* Intel i1480 (using firmware 1.3PA2-20070828) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02), - .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, - /* Generic match for the Radio Control interface */ - { USB_INTERFACE_INFO(0xe0, 0x01, 0x02), }, - { }, -}; -MODULE_DEVICE_TABLE(usb, hwarc_id_table); - -static struct usb_driver hwarc_driver = { - .name = "hwa-rc", - .probe = hwarc_probe, - .disconnect = hwarc_disconnect, - .id_table = hwarc_id_table, -}; - -static int __init hwarc_driver_init(void) -{ - int result; - result = usb_register(&hwarc_driver); - if (result < 0) - printk(KERN_ERR "HWA-RC: Cannot register USB driver: %d\n", - result); - return result; - -} -module_init(hwarc_driver_init); - -static void __exit hwarc_driver_exit(void) -{ - usb_deregister(&hwarc_driver); -} -module_exit(hwarc_driver_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Host Wireless Adapter Radio Control Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/i1480/Makefile b/trunk/drivers/uwb/i1480/Makefile deleted file mode 100644 index 212bbc7d4c32..000000000000 --- a/trunk/drivers/uwb/i1480/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_UWB_I1480U) += dfu/ i1480-est.o -obj-$(CONFIG_UWB_I1480U_WLP) += i1480u-wlp/ diff --git a/trunk/drivers/uwb/i1480/dfu/Makefile b/trunk/drivers/uwb/i1480/dfu/Makefile deleted file mode 100644 index bd1b9f25424c..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -obj-$(CONFIG_UWB_I1480U) += i1480-dfu-usb.o - -i1480-dfu-usb-objs := \ - dfu.o \ - mac.o \ - phy.o \ - usb.o - - diff --git a/trunk/drivers/uwb/i1480/dfu/dfu.c b/trunk/drivers/uwb/i1480/dfu/dfu.c deleted file mode 100644 index 9097b3b30385..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/dfu.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Intel Wireless UWB Link 1480 - * Main driver - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Common code for firmware upload used by the USB and PCI version; - * i1480_fw_upload() takes a device descriptor and uses the function - * pointers it provides to upload firmware and prepare the PHY. - * - * As well, provides common functions used by the rest of the code. - */ -#include "i1480-dfu.h" -#include -#include -#include -#include -#include -#include - -#define D_LOCAL 0 -#include - -/** - * i1480_rceb_check - Check RCEB for expected field values - * @i1480: pointer to device for which RCEB is being checked - * @rceb: RCEB being checked - * @cmd: which command the RCEB is related to - * @context: expected context - * @expected_type: expected event type - * @expected_event: expected event - * - * If @cmd is NULL, do not print error messages, but still return an error - * code. - * - * Return 0 if @rceb matches the expected values, -EINVAL otherwise. - */ -int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb, - const char *cmd, u8 context, u8 expected_type, - unsigned expected_event) -{ - int result = 0; - struct device *dev = i1480->dev; - if (rceb->bEventContext != context) { - if (cmd) - dev_err(dev, "%s: unexpected context id 0x%02x " - "(expected 0x%02x)\n", cmd, - rceb->bEventContext, context); - result = -EINVAL; - } - if (rceb->bEventType != expected_type) { - if (cmd) - dev_err(dev, "%s: unexpected event type 0x%02x " - "(expected 0x%02x)\n", cmd, - rceb->bEventType, expected_type); - result = -EINVAL; - } - if (le16_to_cpu(rceb->wEvent) != expected_event) { - if (cmd) - dev_err(dev, "%s: unexpected event 0x%04x " - "(expected 0x%04x)\n", cmd, - le16_to_cpu(rceb->wEvent), expected_event); - result = -EINVAL; - } - return result; -} -EXPORT_SYMBOL_GPL(i1480_rceb_check); - - -/** - * Execute a Radio Control Command - * - * Command data has to be in i1480->cmd_buf. - * - * @returns size of the reply data filled in i1480->evt_buf or < 0 errno - * code on error. - */ -ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size, - size_t reply_size) -{ - ssize_t result; - struct uwb_rceb *reply = i1480->evt_buf; - struct uwb_rccb *cmd = i1480->cmd_buf; - u16 expected_event = reply->wEvent; - u8 expected_type = reply->bEventType; - u8 context; - - d_fnstart(3, i1480->dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size); - init_completion(&i1480->evt_complete); - i1480->evt_result = -EINPROGRESS; - do { - get_random_bytes(&context, 1); - } while (context == 0x00 || context == 0xff); - cmd->bCommandContext = context; - result = i1480->cmd(i1480, cmd_name, cmd_size); - if (result < 0) - goto error; - /* wait for the callback to report a event was received */ - result = wait_for_completion_interruptible_timeout( - &i1480->evt_complete, HZ); - if (result == 0) { - result = -ETIMEDOUT; - goto error; - } - if (result < 0) - goto error; - result = i1480->evt_result; - if (result < 0) { - dev_err(i1480->dev, "%s: command reply reception failed: %zd\n", - cmd_name, result); - goto error; - } - /* - * Firmware versions >= 1.4.12224 for IOGear GUWA100U generate a - * spurious notification after firmware is downloaded. So check whether - * the receibed RCEB is such notification before assuming that the - * command has failed. - */ - if (i1480_rceb_check(i1480, i1480->evt_buf, NULL, - 0, 0xfd, 0x0022) == 0) { - /* Now wait for the actual RCEB for this command. */ - result = i1480->wait_init_done(i1480); - if (result < 0) - goto error; - result = i1480->evt_result; - } - if (result != reply_size) { - dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n", - cmd_name, result, reply_size); - result = -EINVAL; - goto error; - } - /* Verify we got the right event in response */ - result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context, - expected_type, expected_event); -error: - d_fnend(3, i1480->dev, "(%p, %s, %zu) = %zd\n", - i1480, cmd_name, cmd_size, result); - return result; -} -EXPORT_SYMBOL_GPL(i1480_cmd); - - -static -int i1480_print_state(struct i1480 *i1480) -{ - int result; - u32 *buf = (u32 *) i1480->cmd_buf; - - result = i1480->read(i1480, 0x80080000, 2 * sizeof(*buf)); - if (result < 0) { - dev_err(i1480->dev, "cannot read U & L states: %d\n", result); - goto error; - } - dev_info(i1480->dev, "state U 0x%08x, L 0x%08x\n", buf[0], buf[1]); -error: - return result; -} - - -/* - * PCI probe, firmware uploader - * - * _mac_fw_upload() will call rc_setup(), which needs an rc_release(). - */ -int i1480_fw_upload(struct i1480 *i1480) -{ - int result; - - result = i1480_pre_fw_upload(i1480); /* PHY pre fw */ - if (result < 0 && result != -ENOENT) { - i1480_print_state(i1480); - goto error; - } - result = i1480_mac_fw_upload(i1480); /* MAC fw */ - if (result < 0) { - if (result == -ENOENT) - dev_err(i1480->dev, "Cannot locate MAC FW file '%s'\n", - i1480->mac_fw_name); - else - i1480_print_state(i1480); - goto error; - } - result = i1480_phy_fw_upload(i1480); /* PHY fw */ - if (result < 0 && result != -ENOENT) { - i1480_print_state(i1480); - goto error_rc_release; - } - /* - * FIXME: find some reliable way to check whether firmware is running - * properly. Maybe use some standard request that has no side effects? - */ - dev_info(i1480->dev, "firmware uploaded successfully\n"); -error_rc_release: - if (i1480->rc_release) - i1480->rc_release(i1480); - result = 0; -error: - return result; -} -EXPORT_SYMBOL_GPL(i1480_fw_upload); diff --git a/trunk/drivers/uwb/i1480/dfu/i1480-dfu.h b/trunk/drivers/uwb/i1480/dfu/i1480-dfu.h deleted file mode 100644 index 46f45e800f36..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/i1480-dfu.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * i1480 Device Firmware Upload - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This driver is the firmware uploader for the Intel Wireless UWB - * Link 1480 device (both in the USB and PCI incarnations). - * - * The process is quite simple: we stop the device, write the firmware - * to its memory and then restart it. Wait for the device to let us - * know it is done booting firmware. Ready. - * - * We might have to upload before or after a phy firmware (which might - * be done in two methods, using a normal firmware image or through - * the MPI port). - * - * Because USB and PCI use common methods, we just make ops out of the - * common operations (read, write, wait_init_done and cmd) and - * implement them in usb.c and pci.c. - * - * The flow is (some parts omitted): - * - * i1480_{usb,pci}_probe() On enumerate/discovery - * i1480_fw_upload() - * i1480_pre_fw_upload() - * __mac_fw_upload() - * fw_hdrs_load() - * mac_fw_hdrs_push() - * i1480->write() [i1480_{usb,pci}_write()] - * i1480_fw_cmp() - * i1480->read() [i1480_{usb,pci}_read()] - * i1480_mac_fw_upload() - * __mac_fw_upload() - * i1480->setup(() - * i1480->wait_init_done() - * i1480_cmd_reset() - * i1480->cmd() [i1480_{usb,pci}_cmd()] - * ... - * i1480_phy_fw_upload() - * request_firmware() - * i1480_mpi_write() - * i1480->cmd() [i1480_{usb,pci}_cmd()] - * - * Once the probe function enumerates the device and uploads the - * firmware, we just exit with -ENODEV, as we don't really want to - * attach to the device. - */ -#ifndef __i1480_DFU_H__ -#define __i1480_DFU_H__ - -#include -#include -#include - -#define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) - -#if i1480_FW > 0x00000302 -#define i1480_RCEB_EXTENDED -#endif - -struct uwb_rccb; -struct uwb_rceb; - -/* - * Common firmware upload handlers - * - * Normally you embed this struct in another one specific to your hw. - * - * @write Write to device's memory from buffer. - * @read Read from device's memory to i1480->evt_buf. - * @setup Setup device after basic firmware is uploaded - * @wait_init_done - * Wait for the device to send a notification saying init - * is done. - * @cmd FOP for issuing the command to the hardware. The - * command data is contained in i1480->cmd_buf and the size - * is supplied as an argument. The command replied is put - * in i1480->evt_buf and the size in i1480->evt_result (or if - * an error, a < 0 errno code). - * - * @cmd_buf Memory buffer used to send commands to the device. - * Allocated by the upper layers i1480_fw_upload(). - * Size has to be @buf_size. - * @evt_buf Memory buffer used to place the async notifications - * received by the hw. Allocated by the upper layers - * i1480_fw_upload(). - * Size has to be @buf_size. - * @cmd_complete - * Low level driver uses this to notify code waiting afor - * an event that the event has arrived and data is in - * i1480->evt_buf (and size/result in i1480->evt_result). - * @hw_rev - * Use this value to activate dfu code to support new revisions - * of hardware. i1480_init() sets this to a default value. - * It should be updated by the USB and PCI code. - */ -struct i1480 { - struct device *dev; - - int (*write)(struct i1480 *, u32 addr, const void *, size_t); - int (*read)(struct i1480 *, u32 addr, size_t); - int (*rc_setup)(struct i1480 *); - void (*rc_release)(struct i1480 *); - int (*wait_init_done)(struct i1480 *); - int (*cmd)(struct i1480 *, const char *cmd_name, size_t cmd_size); - const char *pre_fw_name; - const char *mac_fw_name; - const char *mac_fw_name_deprecate; /* FIXME: Will go away */ - const char *phy_fw_name; - u8 hw_rev; - - size_t buf_size; /* size of both evt_buf and cmd_buf */ - void *evt_buf, *cmd_buf; - ssize_t evt_result; - struct completion evt_complete; -}; - -static inline -void i1480_init(struct i1480 *i1480) -{ - i1480->hw_rev = 1; - init_completion(&i1480->evt_complete); -} - -extern int i1480_fw_upload(struct i1480 *); -extern int i1480_pre_fw_upload(struct i1480 *); -extern int i1480_mac_fw_upload(struct i1480 *); -extern int i1480_phy_fw_upload(struct i1480 *); -extern ssize_t i1480_cmd(struct i1480 *, const char *, size_t, size_t); -extern int i1480_rceb_check(const struct i1480 *, - const struct uwb_rceb *, const char *, u8, - u8, unsigned); - -enum { - /* Vendor specific command type */ - i1480_CET_VS1 = 0xfd, - /* i1480 commands */ - i1480_CMD_SET_IP_MAS = 0x000e, - i1480_CMD_GET_MAC_PHY_INFO = 0x0003, - i1480_CMD_MPI_WRITE = 0x000f, - i1480_CMD_MPI_READ = 0x0010, - /* i1480 events */ -#if i1480_FW > 0x00000302 - i1480_EVT_CONFIRM = 0x0002, - i1480_EVT_RM_INIT_DONE = 0x0101, - i1480_EVT_DEV_ADD = 0x0103, - i1480_EVT_DEV_RM = 0x0104, - i1480_EVT_DEV_ID_CHANGE = 0x0105, - i1480_EVT_GET_MAC_PHY_INFO = i1480_CMD_GET_MAC_PHY_INFO, -#else - i1480_EVT_CONFIRM = 0x0002, - i1480_EVT_RM_INIT_DONE = 0x0101, - i1480_EVT_DEV_ADD = 0x0103, - i1480_EVT_DEV_RM = 0x0104, - i1480_EVT_DEV_ID_CHANGE = 0x0105, - i1480_EVT_GET_MAC_PHY_INFO = i1480_EVT_CONFIRM, -#endif -}; - - -struct i1480_evt_confirm { - struct uwb_rceb rceb; -#ifdef i1480_RCEB_EXTENDED - __le16 wParamLength; -#endif - u8 bResultCode; -} __attribute__((packed)); - - -struct i1480_rceb { - struct uwb_rceb rceb; -#ifdef i1480_RCEB_EXTENDED - __le16 wParamLength; -#endif -} __attribute__((packed)); - - -/** - * Get MAC & PHY Information confirm event structure - * - * Confirm event returned by the command. - */ -struct i1480_evt_confirm_GMPI { -#if i1480_FW > 0x00000302 - struct uwb_rceb rceb; - __le16 wParamLength; - __le16 status; - u8 mac_addr[6]; /* EUI-64 bit IEEE address [still 8 bytes?] */ - u8 dev_addr[2]; - __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ - u8 hw_rev; - u8 phy_vendor; - u8 phy_rev; /* major v = >> 8; minor = v & 0xff */ - __le16 mac_caps; - u8 phy_caps[3]; - u8 key_stores; - __le16 mcast_addr_stores; - u8 sec_mode_supported; -#else - struct uwb_rceb rceb; - u8 status; - u8 mac_addr[8]; /* EUI-64 bit IEEE address [still 8 bytes?] */ - u8 dev_addr[2]; - __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ - __le16 phy_fw_rev; /* major v = >> 8; minor = v & 0xff */ - __le16 mac_caps; - u8 phy_caps; - u8 key_stores; - __le16 mcast_addr_stores; - u8 sec_mode_supported; -#endif -} __attribute__((packed)); - - -struct i1480_cmd_mpi_write { - struct uwb_rccb rccb; - __le16 size; - u8 data[]; -}; - - -struct i1480_cmd_mpi_read { - struct uwb_rccb rccb; - __le16 size; - struct { - u8 page, offset; - } __attribute__((packed)) data[]; -} __attribute__((packed)); - - -struct i1480_evt_mpi_read { - struct uwb_rceb rceb; -#ifdef i1480_RCEB_EXTENDED - __le16 wParamLength; -#endif - u8 bResultCode; - __le16 size; - struct { - u8 page, offset, value; - } __attribute__((packed)) data[]; -} __attribute__((packed)); - - -#endif /* #ifndef __i1480_DFU_H__ */ diff --git a/trunk/drivers/uwb/i1480/dfu/mac.c b/trunk/drivers/uwb/i1480/dfu/mac.c deleted file mode 100644 index 2e4d8f07c165..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/mac.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Intel Wireless UWB Link 1480 - * MAC Firmware upload implementation - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Implementation of the code for parsing the firmware file (extract - * the headers and binary code chunks) in the fw_*() functions. The - * code to upload pre and mac firmwares is the same, so it uses a - * common entry point in __mac_fw_upload(), which uses the i1480 - * function pointers to push the firmware to the device. - */ -#include -#include -#include -#include "i1480-dfu.h" - -#define D_LOCAL 0 -#include - -/* - * Descriptor for a continuous segment of MAC fw data - */ -struct fw_hdr { - unsigned long address; - size_t length; - const u32 *bin; - struct fw_hdr *next; -}; - - -/* Free a chain of firmware headers */ -static -void fw_hdrs_free(struct fw_hdr *hdr) -{ - struct fw_hdr *next; - - while (hdr) { - next = hdr->next; - kfree(hdr); - hdr = next; - } -} - - -/* Fill a firmware header descriptor from a memory buffer */ -static -int fw_hdr_load(struct i1480 *i1480, struct fw_hdr *hdr, unsigned hdr_cnt, - const char *_data, const u32 *data_itr, const u32 *data_top) -{ - size_t hdr_offset = (const char *) data_itr - _data; - size_t remaining_size = (void *) data_top - (void *) data_itr; - if (data_itr + 2 > data_top) { - dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in header at " - "offset %zu, limit %zu\n", - hdr_cnt, hdr_offset, - (const char *) data_itr + 2 - _data, - (const char *) data_top - _data); - return -EINVAL; - } - hdr->next = NULL; - hdr->address = le32_to_cpu(*data_itr++); - hdr->length = le32_to_cpu(*data_itr++); - hdr->bin = data_itr; - if (hdr->length > remaining_size) { - dev_err(i1480->dev, "fw hdr #%u/%zu: EOF reached in data; " - "chunk too long (%zu bytes), only %zu left\n", - hdr_cnt, hdr_offset, hdr->length, remaining_size); - return -EINVAL; - } - return 0; -} - - -/** - * Get a buffer where the firmware is supposed to be and create a - * chain of headers linking them together. - * - * @phdr: where to place the pointer to the first header (headers link - * to the next via the @hdr->next ptr); need to free the whole - * chain when done. - * - * @_data: Pointer to the data buffer. - * - * @_data_size: Size of the data buffer (bytes); data size has to be a - * multiple of 4. Function will fail if not. - * - * Goes over the whole binary blob; reads the first chunk and creates - * a fw hdr from it (which points to where the data is in @_data and - * the length of the chunk); then goes on to the next chunk until - * done. Each header is linked to the next. - */ -static -int fw_hdrs_load(struct i1480 *i1480, struct fw_hdr **phdr, - const char *_data, size_t data_size) -{ - int result; - unsigned hdr_cnt = 0; - u32 *data = (u32 *) _data, *data_itr, *data_top; - struct fw_hdr *hdr, **prev_hdr = phdr; - - result = -EINVAL; - /* Check size is ok and pointer is aligned */ - if (data_size % sizeof(u32) != 0) - goto error; - if ((unsigned long) _data % sizeof(u16) != 0) - goto error; - *phdr = NULL; - data_itr = data; - data_top = (u32 *) (_data + data_size); - while (data_itr < data_top) { - result = -ENOMEM; - hdr = kmalloc(sizeof(*hdr), GFP_KERNEL); - if (hdr == NULL) { - dev_err(i1480->dev, "Cannot allocate fw header " - "for chunk #%u\n", hdr_cnt); - goto error_alloc; - } - result = fw_hdr_load(i1480, hdr, hdr_cnt, - _data, data_itr, data_top); - if (result < 0) - goto error_load; - data_itr += 2 + hdr->length; - *prev_hdr = hdr; - prev_hdr = &hdr->next; - hdr_cnt++; - }; - *prev_hdr = NULL; - return 0; - -error_load: - kfree(hdr); -error_alloc: - fw_hdrs_free(*phdr); -error: - return result; -} - - -/** - * Compares a chunk of fw with one in the devices's memory - * - * @i1480: Device instance - * @hdr: Pointer to the firmware chunk - * @returns: 0 if equal, < 0 errno on error. If > 0, it is the offset - * where the difference was found (plus one). - * - * Kind of dirty and simplistic, but does the trick in both the PCI - * and USB version. We do a quick[er] memcmp(), and if it fails, we do - * a byte-by-byte to find the offset. - */ -static -ssize_t i1480_fw_cmp(struct i1480 *i1480, struct fw_hdr *hdr) -{ - ssize_t result = 0; - u32 src_itr = 0, cnt; - size_t size = hdr->length*sizeof(hdr->bin[0]); - size_t chunk_size; - u8 *bin = (u8 *) hdr->bin; - - while (size > 0) { - chunk_size = size < i1480->buf_size ? size : i1480->buf_size; - result = i1480->read(i1480, hdr->address + src_itr, chunk_size); - if (result < 0) { - dev_err(i1480->dev, "error reading for verification: " - "%zd\n", result); - goto error; - } - if (memcmp(i1480->cmd_buf, bin + src_itr, result)) { - u8 *buf = i1480->cmd_buf; - d_printf(2, i1480->dev, - "original data @ %p + %u, %zu bytes\n", - bin, src_itr, result); - d_dump(4, i1480->dev, bin + src_itr, result); - for (cnt = 0; cnt < result; cnt++) - if (bin[src_itr + cnt] != buf[cnt]) { - dev_err(i1480->dev, "byte failed at " - "src_itr %u cnt %u [0x%02x " - "vs 0x%02x]\n", src_itr, cnt, - bin[src_itr + cnt], buf[cnt]); - result = src_itr + cnt + 1; - goto cmp_failed; - } - } - src_itr += result; - size -= result; - } - result = 0; -error: -cmp_failed: - return result; -} - - -/** - * Writes firmware headers to the device. - * - * @prd: PRD instance - * @hdr: Processed firmware - * @returns: 0 if ok, < 0 errno on error. - */ -static -int mac_fw_hdrs_push(struct i1480 *i1480, struct fw_hdr *hdr, - const char *fw_name, const char *fw_tag) -{ - struct device *dev = i1480->dev; - ssize_t result = 0; - struct fw_hdr *hdr_itr; - int verif_retry_count; - - d_fnstart(3, dev, "(%p, %p)\n", i1480, hdr); - /* Now, header by header, push them to the hw */ - for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) { - verif_retry_count = 0; -retry: - dev_dbg(dev, "fw chunk (%zu @ 0x%08lx)\n", - hdr_itr->length * sizeof(hdr_itr->bin[0]), - hdr_itr->address); - result = i1480->write(i1480, hdr_itr->address, hdr_itr->bin, - hdr_itr->length*sizeof(hdr_itr->bin[0])); - if (result < 0) { - dev_err(dev, "%s fw '%s': write failed (%zuB @ 0x%lx):" - " %zd\n", fw_tag, fw_name, - hdr_itr->length * sizeof(hdr_itr->bin[0]), - hdr_itr->address, result); - break; - } - result = i1480_fw_cmp(i1480, hdr_itr); - if (result < 0) { - dev_err(dev, "%s fw '%s': verification read " - "failed (%zuB @ 0x%lx): %zd\n", - fw_tag, fw_name, - hdr_itr->length * sizeof(hdr_itr->bin[0]), - hdr_itr->address, result); - break; - } - if (result > 0) { /* Offset where it failed + 1 */ - result--; - dev_err(dev, "%s fw '%s': WARNING: verification " - "failed at 0x%lx: retrying\n", - fw_tag, fw_name, hdr_itr->address + result); - if (++verif_retry_count < 3) - goto retry; /* write this block again! */ - dev_err(dev, "%s fw '%s': verification failed at 0x%lx: " - "tried %d times\n", fw_tag, fw_name, - hdr_itr->address + result, verif_retry_count); - result = -EINVAL; - break; - } - } - d_fnend(3, dev, "(%zd)\n", result); - return result; -} - - -/** Puts the device in firmware upload mode.*/ -static -int mac_fw_upload_enable(struct i1480 *i1480) -{ - int result; - u32 reg = 0x800000c0; - u32 *buffer = (u32 *)i1480->cmd_buf; - - if (i1480->hw_rev > 1) - reg = 0x8000d0d4; - result = i1480->read(i1480, reg, sizeof(u32)); - if (result < 0) - goto error_cmd; - *buffer &= ~i1480_FW_UPLOAD_MODE_MASK; - result = i1480->write(i1480, reg, buffer, sizeof(u32)); - if (result < 0) - goto error_cmd; - return 0; -error_cmd: - dev_err(i1480->dev, "can't enable fw upload mode: %d\n", result); - return result; -} - - -/** Gets the device out of firmware upload mode. */ -static -int mac_fw_upload_disable(struct i1480 *i1480) -{ - int result; - u32 reg = 0x800000c0; - u32 *buffer = (u32 *)i1480->cmd_buf; - - if (i1480->hw_rev > 1) - reg = 0x8000d0d4; - result = i1480->read(i1480, reg, sizeof(u32)); - if (result < 0) - goto error_cmd; - *buffer |= i1480_FW_UPLOAD_MODE_MASK; - result = i1480->write(i1480, reg, buffer, sizeof(u32)); - if (result < 0) - goto error_cmd; - return 0; -error_cmd: - dev_err(i1480->dev, "can't disable fw upload mode: %d\n", result); - return result; -} - - - -/** - * Generic function for uploading a MAC firmware. - * - * @i1480: Device instance - * @fw_name: Name of firmware file to upload. - * @fw_tag: Name of the firmware type (for messages) - * [eg: MAC, PRE] - * @do_wait: Wait for device to emit initialization done message (0 - * for PRE fws, 1 for MAC fws). - * @returns: 0 if ok, < 0 errno on error. - */ -static -int __mac_fw_upload(struct i1480 *i1480, const char *fw_name, - const char *fw_tag) -{ - int result; - const struct firmware *fw; - struct fw_hdr *fw_hdrs; - - d_fnstart(3, i1480->dev, "(%p, %s, %s)\n", i1480, fw_name, fw_tag); - result = request_firmware(&fw, fw_name, i1480->dev); - if (result < 0) /* Up to caller to complain on -ENOENT */ - goto out; - d_printf(3, i1480->dev, "%s fw '%s': uploading\n", fw_tag, fw_name); - result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size); - if (result < 0) { - dev_err(i1480->dev, "%s fw '%s': failed to parse firmware " - "file: %d\n", fw_tag, fw_name, result); - goto out_release; - } - result = mac_fw_upload_enable(i1480); - if (result < 0) - goto out_hdrs_release; - result = mac_fw_hdrs_push(i1480, fw_hdrs, fw_name, fw_tag); - mac_fw_upload_disable(i1480); -out_hdrs_release: - if (result >= 0) - dev_info(i1480->dev, "%s fw '%s': uploaded\n", fw_tag, fw_name); - else - dev_err(i1480->dev, "%s fw '%s': failed to upload (%d), " - "power cycle device\n", fw_tag, fw_name, result); - fw_hdrs_free(fw_hdrs); -out_release: - release_firmware(fw); -out: - d_fnend(3, i1480->dev, "(%p, %s, %s) = %d\n", i1480, fw_name, fw_tag, - result); - return result; -} - - -/** - * Upload a pre-PHY firmware - * - */ -int i1480_pre_fw_upload(struct i1480 *i1480) -{ - int result; - result = __mac_fw_upload(i1480, i1480->pre_fw_name, "PRE"); - if (result == 0) - msleep(400); - return result; -} - - -/** - * Reset a the MAC and PHY - * - * @i1480: Device's instance - * @returns: 0 if ok, < 0 errno code on error - * - * We put the command on kmalloc'ed memory as some arches cannot do - * USB from the stack. The reply event is copied from an stage buffer, - * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. - * - * We issue the reset to make sure the UWB controller reinits the PHY; - * this way we can now if the PHY init went ok. - */ -static -int i1480_cmd_reset(struct i1480 *i1480) -{ - int result; - struct uwb_rccb *cmd = (void *) i1480->cmd_buf; - struct i1480_evt_reset { - struct uwb_rceb rceb; - u8 bResultCode; - } __attribute__((packed)) *reply = (void *) i1480->evt_buf; - - result = -ENOMEM; - cmd->bCommandType = UWB_RC_CET_GENERAL; - cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET); - reply->rceb.bEventType = UWB_RC_CET_GENERAL; - reply->rceb.wEvent = UWB_RC_CMD_RESET; - result = i1480_cmd(i1480, "RESET", sizeof(*cmd), sizeof(*reply)); - if (result < 0) - goto out; - if (reply->bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(i1480->dev, "RESET: command execution failed: %u\n", - reply->bResultCode); - result = -EIO; - } -out: - return result; - -} - - -/* Wait for the MAC FW to start running */ -static -int i1480_fw_is_running_q(struct i1480 *i1480) -{ - int cnt = 0; - int result; - u32 *val = (u32 *) i1480->cmd_buf; - - d_fnstart(3, i1480->dev, "(i1480 %p)\n", i1480); - for (cnt = 0; cnt < 10; cnt++) { - msleep(100); - result = i1480->read(i1480, 0x80080000, 4); - if (result < 0) { - dev_err(i1480->dev, "Can't read 0x8008000: %d\n", result); - goto out; - } - if (*val == 0x55555555UL) /* fw running? cool */ - goto out; - } - dev_err(i1480->dev, "Timed out waiting for fw to start\n"); - result = -ETIMEDOUT; -out: - d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result); - return result; - -} - - -/** - * Upload MAC firmware, wait for it to start - * - * @i1480: Device instance - * @fw_name: Name of the file that contains the firmware - * - * This has to be called after the pre fw has been uploaded (if - * there is any). - */ -int i1480_mac_fw_upload(struct i1480 *i1480) -{ - int result = 0, deprecated_name = 0; - struct i1480_rceb *rcebe = (void *) i1480->evt_buf; - - d_fnstart(3, i1480->dev, "(%p)\n", i1480); - result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC"); - if (result == -ENOENT) { - result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate, - "MAC"); - deprecated_name = 1; - } - if (result < 0) - return result; - if (deprecated_name == 1) - dev_warn(i1480->dev, - "WARNING: firmware file name %s is deprecated, " - "please rename to %s\n", - i1480->mac_fw_name_deprecate, i1480->mac_fw_name); - result = i1480_fw_is_running_q(i1480); - if (result < 0) - goto error_fw_not_running; - result = i1480->rc_setup ? i1480->rc_setup(i1480) : 0; - if (result < 0) { - dev_err(i1480->dev, "Cannot setup after MAC fw upload: %d\n", - result); - goto error_setup; - } - result = i1480->wait_init_done(i1480); /* wait init'on */ - if (result < 0) { - dev_err(i1480->dev, "MAC fw '%s': Initialization timed out " - "(%d)\n", i1480->mac_fw_name, result); - goto error_init_timeout; - } - /* verify we got the right initialization done event */ - if (i1480->evt_result != sizeof(*rcebe)) { - dev_err(i1480->dev, "MAC fw '%s': initialization event returns " - "wrong size (%zu bytes vs %zu needed)\n", - i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe)); - dump_bytes(i1480->dev, rcebe, min(i1480->evt_result, (ssize_t)32)); - goto error_size; - } - result = -EIO; - if (i1480_rceb_check(i1480, &rcebe->rceb, NULL, 0, i1480_CET_VS1, - i1480_EVT_RM_INIT_DONE) < 0) { - dev_err(i1480->dev, "wrong initialization event 0x%02x/%04x/%02x " - "received; expected 0x%02x/%04x/00\n", - rcebe->rceb.bEventType, le16_to_cpu(rcebe->rceb.wEvent), - rcebe->rceb.bEventContext, i1480_CET_VS1, - i1480_EVT_RM_INIT_DONE); - goto error_init_timeout; - } - result = i1480_cmd_reset(i1480); - if (result < 0) - dev_err(i1480->dev, "MAC fw '%s': MBOA reset failed (%d)\n", - i1480->mac_fw_name, result); -error_fw_not_running: -error_init_timeout: -error_size: -error_setup: - d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result); - return result; -} diff --git a/trunk/drivers/uwb/i1480/dfu/phy.c b/trunk/drivers/uwb/i1480/dfu/phy.c deleted file mode 100644 index 3b1a87de8e63..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/phy.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Intel Wireless UWB Link 1480 - * PHY parameters upload - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Code for uploading the PHY parameters to the PHY through the UWB - * Radio Control interface. - * - * We just send the data through the MPI interface using HWA-like - * commands and then reset the PHY to make sure it is ok. - */ -#include -#include -#include -#include -#include "i1480-dfu.h" - - -/** - * Write a value array to an address of the MPI interface - * - * @i1480: Device descriptor - * @data: Data array to write - * @size: Size of the data array - * @returns: 0 if ok, < 0 errno code on error. - * - * The data array is organized into pairs: - * - * ADDRESS VALUE - * - * ADDRESS is BE 16 bit unsigned, VALUE 8 bit unsigned. Size thus has - * to be a multiple of three. - */ -static -int i1480_mpi_write(struct i1480 *i1480, const void *data, size_t size) -{ - int result; - struct i1480_cmd_mpi_write *cmd = i1480->cmd_buf; - struct i1480_evt_confirm *reply = i1480->evt_buf; - - BUG_ON(size > 480); - result = -ENOMEM; - cmd->rccb.bCommandType = i1480_CET_VS1; - cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_WRITE); - cmd->size = cpu_to_le16(size); - memcpy(cmd->data, data, size); - reply->rceb.bEventType = i1480_CET_VS1; - reply->rceb.wEvent = i1480_CMD_MPI_WRITE; - result = i1480_cmd(i1480, "MPI-WRITE", sizeof(*cmd) + size, sizeof(*reply)); - if (result < 0) - goto out; - if (reply->bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(i1480->dev, "MPI-WRITE: command execution failed: %d\n", - reply->bResultCode); - result = -EIO; - } -out: - return result; -} - - -/** - * Read a value array to from an address of the MPI interface - * - * @i1480: Device descriptor - * @data: where to place the read array - * @srcaddr: Where to read from - * @size: Size of the data read array - * @returns: 0 if ok, < 0 errno code on error. - * - * The command data array is organized into pairs ADDR0 ADDR1..., and - * the returned data in ADDR0 VALUE0 ADDR1 VALUE1... - * - * We generate the command array to be a sequential read and then - * rearrange the result. - * - * We use the i1480->cmd_buf for the command, i1480->evt_buf for the reply. - * - * As the reply has to fit in 512 bytes (i1480->evt_buffer), the max amount - * of values we can read is (512 - sizeof(*reply)) / 3 - */ -static -int i1480_mpi_read(struct i1480 *i1480, u8 *data, u16 srcaddr, size_t size) -{ - int result; - struct i1480_cmd_mpi_read *cmd = i1480->cmd_buf; - struct i1480_evt_mpi_read *reply = i1480->evt_buf; - unsigned cnt; - - memset(i1480->cmd_buf, 0x69, 512); - memset(i1480->evt_buf, 0x69, 512); - - BUG_ON(size > (i1480->buf_size - sizeof(*reply)) / 3); - result = -ENOMEM; - cmd->rccb.bCommandType = i1480_CET_VS1; - cmd->rccb.wCommand = cpu_to_le16(i1480_CMD_MPI_READ); - cmd->size = cpu_to_le16(3*size); - for (cnt = 0; cnt < size; cnt++) { - cmd->data[cnt].page = (srcaddr + cnt) >> 8; - cmd->data[cnt].offset = (srcaddr + cnt) & 0xff; - } - reply->rceb.bEventType = i1480_CET_VS1; - reply->rceb.wEvent = i1480_CMD_MPI_READ; - result = i1480_cmd(i1480, "MPI-READ", sizeof(*cmd) + 2*size, - sizeof(*reply) + 3*size); - if (result < 0) - goto out; - if (reply->bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(i1480->dev, "MPI-READ: command execution failed: %d\n", - reply->bResultCode); - result = -EIO; - } - for (cnt = 0; cnt < size; cnt++) { - if (reply->data[cnt].page != (srcaddr + cnt) >> 8) - dev_err(i1480->dev, "MPI-READ: page inconsistency at " - "index %u: expected 0x%02x, got 0x%02x\n", cnt, - (srcaddr + cnt) >> 8, reply->data[cnt].page); - if (reply->data[cnt].offset != ((srcaddr + cnt) & 0x00ff)) - dev_err(i1480->dev, "MPI-READ: offset inconsistency at " - "index %u: expected 0x%02x, got 0x%02x\n", cnt, - (srcaddr + cnt) & 0x00ff, - reply->data[cnt].offset); - data[cnt] = reply->data[cnt].value; - } - result = 0; -out: - return result; -} - - -/** - * Upload a PHY firmware, wait for it to start - * - * @i1480: Device instance - * @fw_name: Name of the file that contains the firmware - * - * We assume the MAC fw is up and running. This means we can use the - * MPI interface to write the PHY firmware. Once done, we issue an - * MBOA Reset, which will force the MAC to reset and reinitialize the - * PHY. If that works, we are ready to go. - * - * Max packet size for the MPI write is 512, so the max buffer is 480 - * (which gives us 160 byte triads of MSB, LSB and VAL for the data). - */ -int i1480_phy_fw_upload(struct i1480 *i1480) -{ - int result; - const struct firmware *fw; - const char *data_itr, *data_top; - const size_t MAX_BLK_SIZE = 480; /* 160 triads */ - size_t data_size; - u8 phy_stat; - - result = request_firmware(&fw, i1480->phy_fw_name, i1480->dev); - if (result < 0) - goto out; - /* Loop writing data in chunks as big as possible until done. */ - for (data_itr = fw->data, data_top = data_itr + fw->size; - data_itr < data_top; data_itr += MAX_BLK_SIZE) { - data_size = min(MAX_BLK_SIZE, (size_t) (data_top - data_itr)); - result = i1480_mpi_write(i1480, data_itr, data_size); - if (result < 0) - goto error_mpi_write; - } - /* Read MPI page 0, offset 6; if 0, PHY was initialized correctly. */ - result = i1480_mpi_read(i1480, &phy_stat, 0x0006, 1); - if (result < 0) { - dev_err(i1480->dev, "PHY: can't get status: %d\n", result); - goto error_mpi_status; - } - if (phy_stat != 0) { - result = -ENODEV; - dev_info(i1480->dev, "error, PHY not ready: %u\n", phy_stat); - goto error_phy_status; - } - dev_info(i1480->dev, "PHY fw '%s': uploaded\n", i1480->phy_fw_name); -error_phy_status: -error_mpi_status: -error_mpi_write: - release_firmware(fw); - if (result < 0) - dev_err(i1480->dev, "PHY fw '%s': failed to upload (%d), " - "power cycle device\n", i1480->phy_fw_name, result); -out: - return result; -} diff --git a/trunk/drivers/uwb/i1480/dfu/usb.c b/trunk/drivers/uwb/i1480/dfu/usb.c deleted file mode 100644 index 98eeeff051aa..000000000000 --- a/trunk/drivers/uwb/i1480/dfu/usb.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Intel Wireless UWB Link 1480 - * USB SKU firmware upload implementation - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This driver will prepare the i1480 device to behave as a real - * Wireless USB HWA adaptor by uploading the firmware. - * - * When the device is connected or driver is loaded, i1480_usb_probe() - * is called--this will allocate and initialize the device structure, - * fill in the pointers to the common functions (read, write, - * wait_init_done and cmd for HWA command execution) and once that is - * done, call the common firmware uploading routine. Then clean up and - * return -ENODEV, as we don't attach to the device. - * - * The rest are the basic ops we implement that the fw upload code - * uses to do its job. All the ops in the common code are i1480->NAME, - * the functions are i1480_usb_NAME(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "i1480-dfu.h" - -#define D_LOCAL 0 -#include - - -struct i1480_usb { - struct i1480 i1480; - struct usb_device *usb_dev; - struct usb_interface *usb_iface; - struct urb *neep_urb; /* URB for reading from EP1 */ -}; - - -static -void i1480_usb_init(struct i1480_usb *i1480_usb) -{ - i1480_init(&i1480_usb->i1480); -} - - -static -int i1480_usb_create(struct i1480_usb *i1480_usb, struct usb_interface *iface) -{ - struct usb_device *usb_dev = interface_to_usbdev(iface); - int result = -ENOMEM; - - i1480_usb->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */ - i1480_usb->usb_iface = usb_get_intf(iface); - usb_set_intfdata(iface, i1480_usb); /* Bind the driver to iface0 */ - i1480_usb->neep_urb = usb_alloc_urb(0, GFP_KERNEL); - if (i1480_usb->neep_urb == NULL) - goto error; - return 0; - -error: - usb_set_intfdata(iface, NULL); - usb_put_intf(iface); - usb_put_dev(usb_dev); - return result; -} - - -static -void i1480_usb_destroy(struct i1480_usb *i1480_usb) -{ - usb_kill_urb(i1480_usb->neep_urb); - usb_free_urb(i1480_usb->neep_urb); - usb_set_intfdata(i1480_usb->usb_iface, NULL); - usb_put_intf(i1480_usb->usb_iface); - usb_put_dev(i1480_usb->usb_dev); -} - - -/** - * Write a buffer to a memory address in the i1480 device - * - * @i1480: i1480 instance - * @memory_address: - * Address where to write the data buffer to. - * @buffer: Buffer to the data - * @size: Size of the buffer [has to be < 512]. - * @returns: 0 if ok, < 0 errno code on error. - * - * Data buffers to USB cannot be on the stack or in vmalloc'ed areas, - * so we copy it to the local i1480 buffer before proceeding. In any - * case, we have a max size we can send, soooo. - */ -static -int i1480_usb_write(struct i1480 *i1480, u32 memory_address, - const void *buffer, size_t size) -{ - int result = 0; - struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); - size_t buffer_size, itr = 0; - - d_fnstart(3, i1480->dev, "(%p, 0x%08x, %p, %zu)\n", - i1480, memory_address, buffer, size); - BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ - while (size > 0) { - buffer_size = size < i1480->buf_size ? size : i1480->buf_size; - memcpy(i1480->cmd_buf, buffer + itr, buffer_size); - result = usb_control_msg( - i1480_usb->usb_dev, usb_sndctrlpipe(i1480_usb->usb_dev, 0), - 0xf0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - cpu_to_le16(memory_address & 0xffff), - cpu_to_le16((memory_address >> 16) & 0xffff), - i1480->cmd_buf, buffer_size, 100 /* FIXME: arbitrary */); - if (result < 0) - break; - d_printf(3, i1480->dev, - "wrote @ 0x%08x %u bytes (of %zu bytes requested)\n", - memory_address, result, buffer_size); - d_dump(4, i1480->dev, i1480->cmd_buf, result); - itr += result; - memory_address += result; - size -= result; - } - d_fnend(3, i1480->dev, "(%p, 0x%08x, %p, %zu) = %d\n", - i1480, memory_address, buffer, size, result); - return result; -} - - -/** - * Read a block [max size 512] of the device's memory to @i1480's buffer. - * - * @i1480: i1480 instance - * @memory_address: - * Address where to read from. - * @size: Size to read. Smaller than or equal to 512. - * @returns: >= 0 number of bytes written if ok, < 0 errno code on error. - * - * NOTE: if the memory address or block is incorrect, you might get a - * stall or a different memory read. Caller has to verify the - * memory address and size passed back in the @neh structure. - */ -static -int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size) -{ - ssize_t result = 0, bytes = 0; - size_t itr, read_size = i1480->buf_size; - struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); - - d_fnstart(3, i1480->dev, "(%p, 0x%08x, %zu)\n", - i1480, addr, size); - BUG_ON(size > i1480->buf_size); - BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ - BUG_ON(read_size > 512); - - if (addr >= 0x8000d200 && addr < 0x8000d400) /* Yeah, HW quirk */ - read_size = 4; - - for (itr = 0; itr < size; itr += read_size) { - size_t itr_addr = addr + itr; - size_t itr_size = min(read_size, size - itr); - result = usb_control_msg( - i1480_usb->usb_dev, usb_rcvctrlpipe(i1480_usb->usb_dev, 0), - 0xf0, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - cpu_to_le16(itr_addr & 0xffff), - cpu_to_le16((itr_addr >> 16) & 0xffff), - i1480->cmd_buf + itr, itr_size, - 100 /* FIXME: arbitrary */); - if (result < 0) { - dev_err(i1480->dev, "%s: USB read error: %zd\n", - __func__, result); - goto out; - } - if (result != itr_size) { - result = -EIO; - dev_err(i1480->dev, - "%s: partial read got only %zu bytes vs %zu expected\n", - __func__, result, itr_size); - goto out; - } - bytes += result; - } - result = bytes; -out: - d_fnend(3, i1480->dev, "(%p, 0x%08x, %zu) = %zd\n", - i1480, addr, size, result); - if (result > 0) - d_dump(4, i1480->dev, i1480->cmd_buf, result); - return result; -} - - -/** - * Callback for reads on the notification/event endpoint - * - * Just enables the completion read handler. - */ -static -void i1480_usb_neep_cb(struct urb *urb) -{ - struct i1480 *i1480 = urb->context; - struct device *dev = i1480->dev; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: /* Not an error, but a controlled situation; */ - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - dev_dbg(dev, "NEEP: reset/noent %d\n", urb->status); - break; - case -ESHUTDOWN: /* going away! */ - dev_dbg(dev, "NEEP: down %d\n", urb->status); - break; - default: - dev_err(dev, "NEEP: unknown status %d\n", urb->status); - break; - } - i1480->evt_result = urb->actual_length; - complete(&i1480->evt_complete); - return; -} - - -/** - * Wait for the MAC FW to initialize - * - * MAC FW sends a 0xfd/0101/00 notification to EP1 when done - * initializing. Get that notification into i1480->evt_buf; upper layer - * will verify it. - * - * Set i1480->evt_result with the result of getting the event or its - * size (if succesful). - * - * Delivers the data directly to i1480->evt_buf - */ -static -int i1480_usb_wait_init_done(struct i1480 *i1480) -{ - int result; - struct device *dev = i1480->dev; - struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); - struct usb_endpoint_descriptor *epd; - - d_fnstart(3, dev, "(%p)\n", i1480); - init_completion(&i1480->evt_complete); - i1480->evt_result = -EINPROGRESS; - epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb(i1480_usb->neep_urb, i1480_usb->usb_dev, - usb_rcvintpipe(i1480_usb->usb_dev, epd->bEndpointAddress), - i1480->evt_buf, i1480->buf_size, - i1480_usb_neep_cb, i1480, epd->bInterval); - result = usb_submit_urb(i1480_usb->neep_urb, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "init done: cannot submit NEEP read: %d\n", - result); - goto error_submit; - } - /* Wait for the USB callback to get the data */ - result = wait_for_completion_interruptible_timeout( - &i1480->evt_complete, HZ); - if (result <= 0) { - result = result == 0 ? -ETIMEDOUT : result; - goto error_wait; - } - usb_kill_urb(i1480_usb->neep_urb); - d_fnend(3, dev, "(%p) = 0\n", i1480); - return 0; - -error_wait: - usb_kill_urb(i1480_usb->neep_urb); -error_submit: - i1480->evt_result = result; - d_fnend(3, dev, "(%p) = %d\n", i1480, result); - return result; -} - - -/** - * Generic function for issuing commands to the i1480 - * - * @i1480: i1480 instance - * @cmd_name: Name of the command (for error messages) - * @cmd: Pointer to command buffer - * @cmd_size: Size of the command buffer - * @reply: Buffer for the reply event - * @reply_size: Expected size back (including RCEB); the reply buffer - * is assumed to be as big as this. - * @returns: >= 0 size of the returned event data if ok, - * < 0 errno code on error. - * - * Arms the NE handle, issues the command to the device and checks the - * basics of the reply event. - */ -static -int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size) -{ - int result; - struct device *dev = i1480->dev; - struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); - struct usb_endpoint_descriptor *epd; - struct uwb_rccb *cmd = i1480->cmd_buf; - u8 iface_no; - - d_fnstart(3, dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size); - /* Post a read on the notification & event endpoint */ - iface_no = i1480_usb->usb_iface->cur_altsetting->desc.bInterfaceNumber; - epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb( - i1480_usb->neep_urb, i1480_usb->usb_dev, - usb_rcvintpipe(i1480_usb->usb_dev, epd->bEndpointAddress), - i1480->evt_buf, i1480->buf_size, - i1480_usb_neep_cb, i1480, epd->bInterval); - result = usb_submit_urb(i1480_usb->neep_urb, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "%s: cannot submit NEEP read: %d\n", - cmd_name, result); - goto error_submit_ep1; - } - /* Now post the command on EP0 */ - result = usb_control_msg( - i1480_usb->usb_dev, usb_sndctrlpipe(i1480_usb->usb_dev, 0), - WA_EXEC_RC_CMD, - USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, - 0, iface_no, - cmd, cmd_size, - 100 /* FIXME: this is totally arbitrary */); - if (result < 0) { - dev_err(dev, "%s: control request failed: %d\n", - cmd_name, result); - goto error_submit_ep0; - } - d_fnend(3, dev, "(%p, %s, %zu) = %d\n", - i1480, cmd_name, cmd_size, result); - return result; - -error_submit_ep0: - usb_kill_urb(i1480_usb->neep_urb); -error_submit_ep1: - d_fnend(3, dev, "(%p, %s, %zu) = %d\n", - i1480, cmd_name, cmd_size, result); - return result; -} - - -/* - * Probe a i1480 device for uploading firmware. - * - * We attach only to interface #0, which is the radio control interface. - */ -static -int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) -{ - struct i1480_usb *i1480_usb; - struct i1480 *i1480; - struct device *dev = &iface->dev; - int result; - - result = -ENODEV; - if (iface->cur_altsetting->desc.bInterfaceNumber != 0) { - dev_dbg(dev, "not attaching to iface %d\n", - iface->cur_altsetting->desc.bInterfaceNumber); - goto error; - } - if (iface->num_altsetting > 1 - && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) { - /* Need altsetting #1 [HW QUIRK] or EP1 won't work */ - result = usb_set_interface(interface_to_usbdev(iface), 0, 1); - if (result < 0) - dev_warn(dev, - "can't set altsetting 1 on iface 0: %d\n", - result); - } - - result = -ENOMEM; - i1480_usb = kzalloc(sizeof(*i1480_usb), GFP_KERNEL); - if (i1480_usb == NULL) { - dev_err(dev, "Unable to allocate instance\n"); - goto error; - } - i1480_usb_init(i1480_usb); - - i1480 = &i1480_usb->i1480; - i1480->buf_size = 512; - i1480->cmd_buf = kmalloc(2 * i1480->buf_size, GFP_KERNEL); - if (i1480->cmd_buf == NULL) { - dev_err(dev, "Cannot allocate transfer buffers\n"); - result = -ENOMEM; - goto error_buf_alloc; - } - i1480->evt_buf = i1480->cmd_buf + i1480->buf_size; - - result = i1480_usb_create(i1480_usb, iface); - if (result < 0) { - dev_err(dev, "Cannot create instance: %d\n", result); - goto error_create; - } - - /* setup the fops and upload the firmare */ - i1480->pre_fw_name = "i1480-pre-phy-0.0.bin"; - i1480->mac_fw_name = "i1480-usb-0.0.bin"; - i1480->mac_fw_name_deprecate = "ptc-0.0.bin"; - i1480->phy_fw_name = "i1480-phy-0.0.bin"; - i1480->dev = &iface->dev; - i1480->write = i1480_usb_write; - i1480->read = i1480_usb_read; - i1480->rc_setup = NULL; - i1480->wait_init_done = i1480_usb_wait_init_done; - i1480->cmd = i1480_usb_cmd; - - result = i1480_fw_upload(&i1480_usb->i1480); /* the real thing */ - if (result >= 0) { - usb_reset_device(i1480_usb->usb_dev); - result = -ENODEV; /* we don't want to bind to the iface */ - } - i1480_usb_destroy(i1480_usb); -error_create: - kfree(i1480->cmd_buf); -error_buf_alloc: - kfree(i1480_usb); -error: - return result; -} - -#define i1480_USB_DEV(v, p) \ -{ \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE \ - | USB_DEVICE_ID_MATCH_DEV_INFO \ - | USB_DEVICE_ID_MATCH_INT_INFO, \ - .idVendor = (v), \ - .idProduct = (p), \ - .bDeviceClass = 0xff, \ - .bDeviceSubClass = 0xff, \ - .bDeviceProtocol = 0xff, \ - .bInterfaceClass = 0xff, \ - .bInterfaceSubClass = 0xff, \ - .bInterfaceProtocol = 0xff, \ -} - - -/** USB device ID's that we handle */ -static struct usb_device_id i1480_usb_id_table[] = { - i1480_USB_DEV(0x8086, 0xdf3b), - i1480_USB_DEV(0x15a9, 0x0005), - i1480_USB_DEV(0x07d1, 0x3802), - i1480_USB_DEV(0x050d, 0x305a), - i1480_USB_DEV(0x3495, 0x3007), - {}, -}; -MODULE_DEVICE_TABLE(usb, i1480_usb_id_table); - - -static struct usb_driver i1480_dfu_driver = { - .name = "i1480-dfu-usb", - .id_table = i1480_usb_id_table, - .probe = i1480_usb_probe, - .disconnect = NULL, -}; - - -/* - * Initialize the i1480 DFU driver. - * - * We also need to register our function for guessing event sizes. - */ -static int __init i1480_dfu_driver_init(void) -{ - return usb_register(&i1480_dfu_driver); -} -module_init(i1480_dfu_driver_init); - - -static void __exit i1480_dfu_driver_exit(void) -{ - usb_deregister(&i1480_dfu_driver); -} -module_exit(i1480_dfu_driver_exit); - - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Intel Wireless UWB Link 1480 firmware uploader for USB"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/i1480/i1480-est.c b/trunk/drivers/uwb/i1480/i1480-est.c deleted file mode 100644 index 7bf8c6febae7..000000000000 --- a/trunk/drivers/uwb/i1480/i1480-est.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Intel Wireless UWB Link 1480 - * Event Size tables for Wired Adaptors - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#include -#include -#include -#include "dfu/i1480-dfu.h" - - -/** Event size table for wEvents 0x00XX */ -static struct uwb_est_entry i1480_est_fd00[] = { - /* Anybody expecting this response has to use - * neh->extra_size to specify the real size that will - * come back. */ - [i1480_EVT_CONFIRM] = { .size = sizeof(struct i1480_evt_confirm) }, - [i1480_CMD_SET_IP_MAS] = { .size = sizeof(struct i1480_evt_confirm) }, -#ifdef i1480_RCEB_EXTENDED - [0x09] = { - .size = sizeof(struct i1480_rceb), - .offset = 1 + offsetof(struct i1480_rceb, wParamLength), - }, -#endif -}; - -/** Event size table for wEvents 0x01XX */ -static struct uwb_est_entry i1480_est_fd01[] = { - [0xff & i1480_EVT_RM_INIT_DONE] = { .size = sizeof(struct i1480_rceb) }, - [0xff & i1480_EVT_DEV_ADD] = { .size = sizeof(struct i1480_rceb) + 9 }, - [0xff & i1480_EVT_DEV_RM] = { .size = sizeof(struct i1480_rceb) + 9 }, - [0xff & i1480_EVT_DEV_ID_CHANGE] = { - .size = sizeof(struct i1480_rceb) + 2 }, -}; - -static int i1480_est_init(void) -{ - int result = uwb_est_register(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b, - i1480_est_fd00, - ARRAY_SIZE(i1480_est_fd00)); - if (result < 0) { - printk(KERN_ERR "Can't register EST table fd00: %d\n", result); - return result; - } - result = uwb_est_register(i1480_CET_VS1, 0x01, 0x8086, 0x0c3b, - i1480_est_fd01, ARRAY_SIZE(i1480_est_fd01)); - if (result < 0) { - printk(KERN_ERR "Can't register EST table fd01: %d\n", result); - return result; - } - return 0; -} -module_init(i1480_est_init); - -static void i1480_est_exit(void) -{ - uwb_est_unregister(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b, - i1480_est_fd00, ARRAY_SIZE(i1480_est_fd00)); - uwb_est_unregister(i1480_CET_VS1, 0x01, 0x8086, 0x0c3b, - i1480_est_fd01, ARRAY_SIZE(i1480_est_fd01)); -} -module_exit(i1480_est_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("i1480's Vendor Specific Event Size Tables"); -MODULE_LICENSE("GPL"); - -/** - * USB device ID's that we handle - * - * [so we are loaded when this kind device is connected] - */ -static struct usb_device_id i1480_est_id_table[] = { - { USB_DEVICE(0x8086, 0xdf3b), }, - { USB_DEVICE(0x8086, 0x0c3b), }, - { }, -}; -MODULE_DEVICE_TABLE(usb, i1480_est_id_table); diff --git a/trunk/drivers/uwb/i1480/i1480-wlp.h b/trunk/drivers/uwb/i1480/i1480-wlp.h deleted file mode 100644 index 18a8b0e4567b..000000000000 --- a/trunk/drivers/uwb/i1480/i1480-wlp.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Intel 1480 Wireless UWB Link - * WLP specific definitions - * - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#ifndef __i1480_wlp_h__ -#define __i1480_wlp_h__ - -#include -#include -#include -#include -#include - -/* New simplified header format? */ -#undef WLP_HDR_FMT_2 /* FIXME: rename */ - -/** - * Values of the Delivery ID & Type field when PCA or DRP - * - * The Delivery ID & Type field in the WLP TX header indicates whether - * the frame is PCA or DRP. This is done based on the high level bit of - * this field. - * We use this constant to test if the traffic is PCA or DRP as follows: - * if (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP) - * this is DRP traffic - * else - * this is PCA traffic - */ -enum deliver_id_type_bit { - WLP_DRP = 8, -}; - -/** - * WLP TX header - * - * Indicates UWB/WLP-specific transmission parameters for a network - * packet. - */ -struct wlp_tx_hdr { - /* dword 0 */ - struct uwb_dev_addr dstaddr; - u8 key_index; - u8 mac_params; - /* dword 1 */ - u8 phy_params; -#ifndef WLP_HDR_FMT_2 - u8 reserved; - __le16 oui01; /* FIXME: not so sure if __le16 or u8[2] */ - /* dword 2 */ - u8 oui2; /* if all LE, it could be merged */ - __le16 prid; -#endif -} __attribute__((packed)); - -static inline int wlp_tx_hdr_delivery_id_type(const struct wlp_tx_hdr *hdr) -{ - return hdr->mac_params & 0x0f; -} - -static inline int wlp_tx_hdr_ack_policy(const struct wlp_tx_hdr *hdr) -{ - return (hdr->mac_params >> 4) & 0x07; -} - -static inline int wlp_tx_hdr_rts_cts(const struct wlp_tx_hdr *hdr) -{ - return (hdr->mac_params >> 7) & 0x01; -} - -static inline void wlp_tx_hdr_set_delivery_id_type(struct wlp_tx_hdr *hdr, int id) -{ - hdr->mac_params = (hdr->mac_params & ~0x0f) | id; -} - -static inline void wlp_tx_hdr_set_ack_policy(struct wlp_tx_hdr *hdr, - enum uwb_ack_pol policy) -{ - hdr->mac_params = (hdr->mac_params & ~0x70) | (policy << 4); -} - -static inline void wlp_tx_hdr_set_rts_cts(struct wlp_tx_hdr *hdr, int rts_cts) -{ - hdr->mac_params = (hdr->mac_params & ~0x80) | (rts_cts << 7); -} - -static inline enum uwb_phy_rate wlp_tx_hdr_phy_rate(const struct wlp_tx_hdr *hdr) -{ - return hdr->phy_params & 0x0f; -} - -static inline int wlp_tx_hdr_tx_power(const struct wlp_tx_hdr *hdr) -{ - return (hdr->phy_params >> 4) & 0x0f; -} - -static inline void wlp_tx_hdr_set_phy_rate(struct wlp_tx_hdr *hdr, enum uwb_phy_rate rate) -{ - hdr->phy_params = (hdr->phy_params & ~0x0f) | rate; -} - -static inline void wlp_tx_hdr_set_tx_power(struct wlp_tx_hdr *hdr, int pwr) -{ - hdr->phy_params = (hdr->phy_params & ~0xf0) | (pwr << 4); -} - - -/** - * WLP RX header - * - * Provides UWB/WLP-specific transmission data for a received - * network packet. - */ -struct wlp_rx_hdr { - /* dword 0 */ - struct uwb_dev_addr dstaddr; - struct uwb_dev_addr srcaddr; - /* dword 1 */ - u8 LQI; - s8 RSSI; - u8 reserved3; -#ifndef WLP_HDR_FMT_2 - u8 oui0; - /* dword 2 */ - __le16 oui12; - __le16 prid; -#endif -} __attribute__((packed)); - - -/** User configurable options for WLP */ -struct wlp_options { - struct mutex mutex; /* access to user configurable options*/ - struct wlp_tx_hdr def_tx_hdr; /* default tx hdr */ - u8 pca_base_priority; - u8 bw_alloc; /*index into bw_allocs[] for PCA/DRP reservations*/ -}; - - -static inline -void wlp_options_init(struct wlp_options *options) -{ - mutex_init(&options->mutex); - wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, UWB_ACK_INM); - wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, 1); - /* FIXME: default to phy caps */ - wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, UWB_PHY_RATE_480); -#ifndef WLP_HDR_FMT_2 - options->def_tx_hdr.prid = cpu_to_le16(0x0000); -#endif -} - - -/* sysfs helpers */ - -extern ssize_t uwb_pca_base_priority_store(struct wlp_options *, - const char *, size_t); -extern ssize_t uwb_pca_base_priority_show(const struct wlp_options *, char *); -extern ssize_t uwb_bw_alloc_store(struct wlp_options *, const char *, size_t); -extern ssize_t uwb_bw_alloc_show(const struct wlp_options *, char *); -extern ssize_t uwb_ack_policy_store(struct wlp_options *, - const char *, size_t); -extern ssize_t uwb_ack_policy_show(const struct wlp_options *, char *); -extern ssize_t uwb_rts_cts_store(struct wlp_options *, const char *, size_t); -extern ssize_t uwb_rts_cts_show(const struct wlp_options *, char *); -extern ssize_t uwb_phy_rate_store(struct wlp_options *, const char *, size_t); -extern ssize_t uwb_phy_rate_show(const struct wlp_options *, char *); - - -/** Simple bandwidth allocation (temporary and too simple) */ -struct wlp_bw_allocs { - const char *name; - struct { - u8 mask, stream; - } tx, rx; -}; - - -#endif /* #ifndef __i1480_wlp_h__ */ diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/Makefile b/trunk/drivers/uwb/i1480/i1480u-wlp/Makefile deleted file mode 100644 index fe6709b8e68b..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-$(CONFIG_UWB_I1480U_WLP) += i1480u-wlp.o - -i1480u-wlp-objs := \ - lc.o \ - netdev.o \ - rx.o \ - sysfs.o \ - tx.o diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h b/trunk/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h deleted file mode 100644 index 5f1b2951bb83..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Intel 1480 Wireless UWB Link USB - * Header formats, constants, general internal interfaces - * - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This is not an standard interface. - * - * FIXME: docs - * - * i1480u-wlp is pretty simple: two endpoints, one for tx, one for - * rx. rx is polled. Network packets (ethernet, whatever) are wrapped - * in i1480 TX or RX headers (for sending over the air), and these - * packets are wrapped in UNTD headers (for sending to the WLP UWB - * controller). - * - * UNTD packets (UNTD hdr + i1480 hdr + network packet) packets - * cannot be bigger than i1480u_MAX_FRG_SIZE. When this happens, the - * i1480 packet is broken in chunks/packets: - * - * UNTD-1st.hdr + i1480.hdr + payload - * UNTD-next.hdr + payload - * ... - * UNTD-last.hdr + payload - * - * so that each packet is smaller or equal than i1480u_MAX_FRG_SIZE. - * - * All HW structures and bitmaps are little endian, so we need to play - * ugly tricks when defining bitfields. Hoping for the day GCC - * implements __attribute__((endian(1234))). - * - * FIXME: ROADMAP to the whole implementation - */ - -#ifndef __i1480u_wlp_h__ -#define __i1480u_wlp_h__ - -#include -#include -#include /* struct uwb_rc, struct uwb_notifs_handler */ -#include -#include "../i1480-wlp.h" - -#undef i1480u_FLOW_CONTROL /* Enable flow control code */ - -/** - * Basic flow control - */ -enum { - i1480u_TX_INFLIGHT_MAX = 1000, - i1480u_TX_INFLIGHT_THRESHOLD = 100, -}; - -/** Maximum size of a transaction that we can tx/rx */ -enum { - /* Maximum packet size computed as follows: max UNTD header (8) + - * i1480 RX header (8) + max Ethernet header and payload (4096) + - * Padding added by skb_reserve (2) to make post Ethernet payload - * start on 16 byte boundary*/ - i1480u_MAX_RX_PKT_SIZE = 4114, - i1480u_MAX_FRG_SIZE = 512, - i1480u_RX_BUFS = 9, -}; - - -/** - * UNTD packet type - * - * We need to fragment any payload whose UNTD packet is going to be - * bigger than i1480u_MAX_FRG_SIZE. - */ -enum i1480u_pkt_type { - i1480u_PKT_FRAG_1ST = 0x1, - i1480u_PKT_FRAG_NXT = 0x0, - i1480u_PKT_FRAG_LST = 0x2, - i1480u_PKT_FRAG_CMP = 0x3 -}; -enum { - i1480u_PKT_NONE = 0x4, -}; - -/** USB Network Transfer Descriptor - common */ -struct untd_hdr { - u8 type; - __le16 len; -} __attribute__((packed)); - -static inline enum i1480u_pkt_type untd_hdr_type(const struct untd_hdr *hdr) -{ - return hdr->type & 0x03; -} - -static inline int untd_hdr_rx_tx(const struct untd_hdr *hdr) -{ - return (hdr->type >> 2) & 0x01; -} - -static inline void untd_hdr_set_type(struct untd_hdr *hdr, enum i1480u_pkt_type type) -{ - hdr->type = (hdr->type & ~0x03) | type; -} - -static inline void untd_hdr_set_rx_tx(struct untd_hdr *hdr, int rx_tx) -{ - hdr->type = (hdr->type & ~0x04) | (rx_tx << 2); -} - - -/** - * USB Network Transfer Descriptor - Complete Packet - * - * This is for a packet that is smaller (header + payload) than - * i1480u_MAX_FRG_SIZE. - * - * @hdr.total_len is the size of the payload; the payload doesn't - * count this header nor the padding, but includes the size of i1480 - * header. - */ -struct untd_hdr_cmp { - struct untd_hdr hdr; - u8 padding; -} __attribute__((packed)); - - -/** - * USB Network Transfer Descriptor - First fragment - * - * @hdr.len is the size of the *whole packet* (excluding UNTD - * headers); @fragment_len is the size of the payload (excluding UNTD - * headers, but including i1480 headers). - */ -struct untd_hdr_1st { - struct untd_hdr hdr; - __le16 fragment_len; - u8 padding[3]; -} __attribute__((packed)); - - -/** - * USB Network Transfer Descriptor - Next / Last [Rest] - * - * @hdr.len is the size of the payload, not including headrs. - */ -struct untd_hdr_rst { - struct untd_hdr hdr; - u8 padding; -} __attribute__((packed)); - - -/** - * Transmission context - * - * Wraps all the stuff needed to track a pending/active tx - * operation. - */ -struct i1480u_tx { - struct list_head list_node; - struct i1480u *i1480u; - struct urb *urb; - - struct sk_buff *skb; - struct wlp_tx_hdr *wlp_tx_hdr; - - void *buf; /* if NULL, no new buf was used */ - size_t buf_size; -}; - -/** - * Basic flow control - * - * We maintain a basic flow control counter. "count" how many TX URBs are - * outstanding. Only allow "max" - * TX URBs to be outstanding. If this value is reached the queue will be - * stopped. The queue will be restarted when there are - * "threshold" URBs outstanding. - * Maintain a counter of how many time the TX queue needed to be restarted - * due to the "max" being exceeded and the "threshold" reached again. The - * timestamp "restart_ts" is to keep track from when the counter was last - * queried (see sysfs handling of file wlp_tx_inflight). - */ -struct i1480u_tx_inflight { - atomic_t count; - unsigned long max; - unsigned long threshold; - unsigned long restart_ts; - atomic_t restart_count; -}; - -/** - * Instance of a i1480u WLP interface - * - * Keeps references to the USB device that wraps it, as well as it's - * interface and associated UWB host controller. As well, it also - * keeps a link to the netdevice for integration into the networking - * stack. - * We maintian separate error history for the tx and rx endpoints because - * the implementation does not rely on locking - having one shared - * structure between endpoints may cause problems. Adding locking to the - * implementation will have higher cost than adding a separate structure. - */ -struct i1480u { - struct usb_device *usb_dev; - struct usb_interface *usb_iface; - struct net_device *net_dev; - - spinlock_t lock; - struct net_device_stats stats; - - /* RX context handling */ - struct sk_buff *rx_skb; - struct uwb_dev_addr rx_srcaddr; - size_t rx_untd_pkt_size; - struct i1480u_rx_buf { - struct i1480u *i1480u; /* back pointer */ - struct urb *urb; - struct sk_buff *data; /* i1480u_MAX_RX_PKT_SIZE each */ - } rx_buf[i1480u_RX_BUFS]; /* N bufs */ - - spinlock_t tx_list_lock; /* TX context */ - struct list_head tx_list; - u8 tx_stream; - - struct stats lqe_stats, rssi_stats; /* radio statistics */ - - /* Options we can set from sysfs */ - struct wlp_options options; - struct uwb_notifs_handler uwb_notifs_handler; - struct edc tx_errors; - struct edc rx_errors; - struct wlp wlp; -#ifdef i1480u_FLOW_CONTROL - struct urb *notif_urb; - struct edc notif_edc; /* error density counter */ - u8 notif_buffer[1]; -#endif - struct i1480u_tx_inflight tx_inflight; -}; - -/* Internal interfaces */ -extern void i1480u_rx_cb(struct urb *urb); -extern int i1480u_rx_setup(struct i1480u *); -extern void i1480u_rx_release(struct i1480u *); -extern void i1480u_tx_release(struct i1480u *); -extern int i1480u_xmit_frame(struct wlp *, struct sk_buff *, - struct uwb_dev_addr *); -extern void i1480u_stop_queue(struct wlp *); -extern void i1480u_start_queue(struct wlp *); -extern int i1480u_sysfs_setup(struct i1480u *); -extern void i1480u_sysfs_release(struct i1480u *); - -/* netdev interface */ -extern int i1480u_open(struct net_device *); -extern int i1480u_stop(struct net_device *); -extern int i1480u_hard_start_xmit(struct sk_buff *, struct net_device *); -extern void i1480u_tx_timeout(struct net_device *); -extern int i1480u_set_config(struct net_device *, struct ifmap *); -extern struct net_device_stats *i1480u_get_stats(struct net_device *); -extern int i1480u_change_mtu(struct net_device *, int); -extern void i1480u_uwb_notifs_cb(void *, struct uwb_dev *, enum uwb_notifs); - -/* bandwidth allocation callback */ -extern void i1480u_bw_alloc_cb(struct uwb_rsv *); - -/* Sys FS */ -extern struct attribute_group i1480u_wlp_attr_group; - -#endif /* #ifndef __i1480u_wlp_h__ */ diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/lc.c b/trunk/drivers/uwb/i1480/i1480u-wlp/lc.c deleted file mode 100644 index 737d60cd5b73..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/lc.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Driver for the Linux Network stack. - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * This implements a very simple network driver for the WLP USB - * device that is associated to a UWB (Ultra Wide Band) host. - * - * This is seen as an interface of a composite device. Once the UWB - * host has an association to another WLP capable device, the - * networking interface (aka WLP) can start to send packets back and - * forth. - * - * Limitations: - * - * - Hand cranked; can't ifup the interface until there is an association - * - * - BW allocation very simplistic [see i1480u_mas_set() and callees]. - * - * - * ROADMAP: - * - * ENTRY POINTS (driver model): - * - * i1480u_driver_{exit,init}(): initialization of the driver. - * - * i1480u_probe(): called by the driver code when a device - * matching 'i1480u_id_table' is connected. - * - * This allocs a netdev instance, inits with - * i1480u_add(), then registers_netdev(). - * i1480u_init() - * i1480u_add() - * - * i1480u_disconnect(): device has been disconnected/module - * is being removed. - * i1480u_rm() - */ -#include -#include -#include -#include -#include "i1480u-wlp.h" - - - -static inline -void i1480u_init(struct i1480u *i1480u) -{ - /* nothing so far... doesn't it suck? */ - spin_lock_init(&i1480u->lock); - INIT_LIST_HEAD(&i1480u->tx_list); - spin_lock_init(&i1480u->tx_list_lock); - wlp_options_init(&i1480u->options); - edc_init(&i1480u->tx_errors); - edc_init(&i1480u->rx_errors); -#ifdef i1480u_FLOW_CONTROL - edc_init(&i1480u->notif_edc); -#endif - stats_init(&i1480u->lqe_stats); - stats_init(&i1480u->rssi_stats); - wlp_init(&i1480u->wlp); -} - -/** - * Fill WLP device information structure - * - * The structure will contain a few character arrays, each ending with a - * null terminated string. Each string has to fit (excluding terminating - * character) into a specified range obtained from the WLP substack. - * - * It is still not clear exactly how this device information should be - * obtained. Until we find out we use the USB device descriptor as backup, some - * information elements have intuitive mappings, other not. - */ -static -void i1480u_fill_device_info(struct wlp *wlp, struct wlp_device_info *dev_info) -{ - struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); - struct usb_device *usb_dev = i1480u->usb_dev; - /* Treat device name and model name the same */ - if (usb_dev->descriptor.iProduct) { - usb_string(usb_dev, usb_dev->descriptor.iProduct, - dev_info->name, sizeof(dev_info->name)); - usb_string(usb_dev, usb_dev->descriptor.iProduct, - dev_info->model_name, sizeof(dev_info->model_name)); - } - if (usb_dev->descriptor.iManufacturer) - usb_string(usb_dev, usb_dev->descriptor.iManufacturer, - dev_info->manufacturer, - sizeof(dev_info->manufacturer)); - scnprintf(dev_info->model_nr, sizeof(dev_info->model_nr), "%04x", - __le16_to_cpu(usb_dev->descriptor.bcdDevice)); - if (usb_dev->descriptor.iSerialNumber) - usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, - dev_info->serial, sizeof(dev_info->serial)); - /* FIXME: where should we obtain category? */ - dev_info->prim_dev_type.category = cpu_to_le16(WLP_DEV_CAT_OTHER); - /* FIXME: Complete OUI and OUIsubdiv attributes */ -} - -#ifdef i1480u_FLOW_CONTROL -/** - * Callback for the notification endpoint - * - * This mostly controls the xon/xoff protocol. In case of hard error, - * we stop the queue. If not, we always retry. - */ -static -void i1480u_notif_cb(struct urb *urb, struct pt_regs *regs) -{ - struct i1480u *i1480u = urb->context; - struct usb_interface *usb_iface = i1480u->usb_iface; - struct device *dev = &usb_iface->dev; - int result; - - switch (urb->status) { - case 0: /* Got valid data, do xon/xoff */ - switch (i1480u->notif_buffer[0]) { - case 'N': - dev_err(dev, "XOFF STOPPING queue at %lu\n", jiffies); - netif_stop_queue(i1480u->net_dev); - break; - case 'A': - dev_err(dev, "XON STARTING queue at %lu\n", jiffies); - netif_start_queue(i1480u->net_dev); - break; - default: - dev_err(dev, "NEP: unknown data 0x%02hhx\n", - i1480u->notif_buffer[0]); - } - break; - case -ECONNRESET: /* Controlled situation ... */ - case -ENOENT: /* we killed the URB... */ - dev_err(dev, "NEP: URB reset/noent %d\n", urb->status); - goto error; - case -ESHUTDOWN: /* going away! */ - dev_err(dev, "NEP: URB down %d\n", urb->status); - goto error; - default: /* Retry unless it gets ugly */ - if (edc_inc(&i1480u->notif_edc, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "NEP: URB max acceptable errors " - "exceeded; resetting device\n"); - goto error_reset; - } - dev_err(dev, "NEP: URB error %d\n", urb->status); - break; - } - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result < 0) { - dev_err(dev, "NEP: Can't resubmit URB: %d; resetting device\n", - result); - goto error_reset; - } - return; - -error_reset: - wlp_reset_all(&i1480-wlp); -error: - netif_stop_queue(i1480u->net_dev); - return; -} -#endif - -static -int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface) -{ - int result = -ENODEV; - struct wlp *wlp = &i1480u->wlp; - struct usb_device *usb_dev = interface_to_usbdev(iface); - struct net_device *net_dev = i1480u->net_dev; - struct uwb_rc *rc; - struct uwb_dev *uwb_dev; -#ifdef i1480u_FLOW_CONTROL - struct usb_endpoint_descriptor *epd; -#endif - - i1480u->usb_dev = usb_get_dev(usb_dev); - i1480u->usb_iface = iface; - rc = uwb_rc_get_by_grandpa(&i1480u->usb_dev->dev); - if (rc == NULL) { - dev_err(&iface->dev, "Cannot get associated UWB Radio " - "Controller\n"); - goto out; - } - wlp->xmit_frame = i1480u_xmit_frame; - wlp->fill_device_info = i1480u_fill_device_info; - wlp->stop_queue = i1480u_stop_queue; - wlp->start_queue = i1480u_start_queue; - result = wlp_setup(wlp, rc); - if (result < 0) { - dev_err(&iface->dev, "Cannot setup WLP\n"); - goto error_wlp_setup; - } - result = 0; - ether_setup(net_dev); /* make it an etherdevice */ - uwb_dev = &rc->uwb_dev; - /* FIXME: hookup address change notifications? */ - - memcpy(net_dev->dev_addr, uwb_dev->mac_addr.data, - sizeof(net_dev->dev_addr)); - - net_dev->hard_header_len = sizeof(struct untd_hdr_cmp) - + sizeof(struct wlp_tx_hdr) - + WLP_DATA_HLEN - + ETH_HLEN; - net_dev->mtu = 3500; - net_dev->tx_queue_len = 20; /* FIXME: maybe use 1000? */ - -/* net_dev->flags &= ~IFF_BROADCAST; FIXME: BUG in firmware */ - /* FIXME: multicast disabled */ - net_dev->flags &= ~IFF_MULTICAST; - net_dev->features &= ~NETIF_F_SG; - net_dev->features &= ~NETIF_F_FRAGLIST; - /* All NETIF_F_*_CSUM disabled */ - net_dev->features |= NETIF_F_HIGHDMA; - net_dev->watchdog_timeo = 5*HZ; /* FIXME: a better default? */ - - net_dev->open = i1480u_open; - net_dev->stop = i1480u_stop; - net_dev->hard_start_xmit = i1480u_hard_start_xmit; - net_dev->tx_timeout = i1480u_tx_timeout; - net_dev->get_stats = i1480u_get_stats; - net_dev->set_config = i1480u_set_config; - net_dev->change_mtu = i1480u_change_mtu; - -#ifdef i1480u_FLOW_CONTROL - /* Notification endpoint setup (submitted when we open the device) */ - i1480u->notif_urb = usb_alloc_urb(0, GFP_KERNEL); - if (i1480u->notif_urb == NULL) { - dev_err(&iface->dev, "Unable to allocate notification URB\n"); - result = -ENOMEM; - goto error_urb_alloc; - } - epd = &iface->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb(i1480u->notif_urb, usb_dev, - usb_rcvintpipe(usb_dev, epd->bEndpointAddress), - i1480u->notif_buffer, sizeof(i1480u->notif_buffer), - i1480u_notif_cb, i1480u, epd->bInterval); - -#endif - - i1480u->tx_inflight.max = i1480u_TX_INFLIGHT_MAX; - i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD; - i1480u->tx_inflight.restart_ts = jiffies; - usb_set_intfdata(iface, i1480u); - return result; - -#ifdef i1480u_FLOW_CONTROL -error_urb_alloc: -#endif - wlp_remove(wlp); -error_wlp_setup: - uwb_rc_put(rc); -out: - usb_put_dev(i1480u->usb_dev); - return result; -} - -static void i1480u_rm(struct i1480u *i1480u) -{ - struct uwb_rc *rc = i1480u->wlp.rc; - usb_set_intfdata(i1480u->usb_iface, NULL); -#ifdef i1480u_FLOW_CONTROL - usb_kill_urb(i1480u->notif_urb); - usb_free_urb(i1480u->notif_urb); -#endif - wlp_remove(&i1480u->wlp); - uwb_rc_put(rc); - usb_put_dev(i1480u->usb_dev); -} - -/** Just setup @net_dev's i1480u private data */ -static void i1480u_netdev_setup(struct net_device *net_dev) -{ - struct i1480u *i1480u = netdev_priv(net_dev); - /* Initialize @i1480u */ - memset(i1480u, 0, sizeof(*i1480u)); - i1480u_init(i1480u); -} - -/** - * Probe a i1480u interface and register it - * - * @iface: USB interface to link to - * @id: USB class/subclass/protocol id - * @returns: 0 if ok, < 0 errno code on error. - * - * Does basic housekeeping stuff and then allocs a netdev with space - * for the i1480u data. Initializes, registers in i1480u, registers in - * netdev, ready to go. - */ -static int i1480u_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - int result; - struct net_device *net_dev; - struct device *dev = &iface->dev; - struct i1480u *i1480u; - - /* Allocate instance [calls i1480u_netdev_setup() on it] */ - result = -ENOMEM; - net_dev = alloc_netdev(sizeof(*i1480u), "wlp%d", i1480u_netdev_setup); - if (net_dev == NULL) { - dev_err(dev, "no memory for network device instance\n"); - goto error_alloc_netdev; - } - SET_NETDEV_DEV(net_dev, dev); - i1480u = netdev_priv(net_dev); - i1480u->net_dev = net_dev; - result = i1480u_add(i1480u, iface); /* Now setup all the wlp stuff */ - if (result < 0) { - dev_err(dev, "cannot add i1480u device: %d\n", result); - goto error_i1480u_add; - } - result = register_netdev(net_dev); /* Okey dokey, bring it up */ - if (result < 0) { - dev_err(dev, "cannot register network device: %d\n", result); - goto error_register_netdev; - } - i1480u_sysfs_setup(i1480u); - if (result < 0) - goto error_sysfs_init; - return 0; - -error_sysfs_init: - unregister_netdev(net_dev); -error_register_netdev: - i1480u_rm(i1480u); -error_i1480u_add: - free_netdev(net_dev); -error_alloc_netdev: - return result; -} - - -/** - * Disconect a i1480u from the system. - * - * i1480u_stop() has been called before, so al the rx and tx contexts - * have been taken down already. Make sure the queue is stopped, - * unregister netdev and i1480u, free and kill. - */ -static void i1480u_disconnect(struct usb_interface *iface) -{ - struct i1480u *i1480u; - struct net_device *net_dev; - - i1480u = usb_get_intfdata(iface); - net_dev = i1480u->net_dev; - netif_stop_queue(net_dev); -#ifdef i1480u_FLOW_CONTROL - usb_kill_urb(i1480u->notif_urb); -#endif - i1480u_sysfs_release(i1480u); - unregister_netdev(net_dev); - i1480u_rm(i1480u); - free_netdev(net_dev); -} - -static struct usb_device_id i1480u_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE \ - | USB_DEVICE_ID_MATCH_DEV_INFO \ - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x8086, - .idProduct = 0x0c3b, - .bDeviceClass = 0xef, - .bDeviceSubClass = 0x02, - .bDeviceProtocol = 0x02, - .bInterfaceClass = 0xff, - .bInterfaceSubClass = 0xff, - .bInterfaceProtocol = 0xff, - }, - {}, -}; -MODULE_DEVICE_TABLE(usb, i1480u_id_table); - -static struct usb_driver i1480u_driver = { - .name = KBUILD_MODNAME, - .probe = i1480u_probe, - .disconnect = i1480u_disconnect, - .id_table = i1480u_id_table, -}; - -static int __init i1480u_driver_init(void) -{ - return usb_register(&i1480u_driver); -} -module_init(i1480u_driver_init); - - -static void __exit i1480u_driver_exit(void) -{ - usb_deregister(&i1480u_driver); -} -module_exit(i1480u_driver_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("i1480 Wireless UWB Link WLP networking for USB"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/netdev.c b/trunk/drivers/uwb/i1480/i1480u-wlp/netdev.c deleted file mode 100644 index 8802ac43d872..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/netdev.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Driver for the Linux Network stack. - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * Implementation of the netdevice linkage (except tx and rx related stuff). - * - * ROADMAP: - * - * ENTRY POINTS (Net device): - * - * i1480u_open(): Called when we ifconfig up the interface; - * associates to a UWB host controller, reserves - * bandwidth (MAS), sets up RX USB URB and starts - * the queue. - * - * i1480u_stop(): Called when we ifconfig down a interface; - * reverses _open(). - * - * i1480u_set_config(): - */ - -#include -#include -#include -#include "i1480u-wlp.h" - -struct i1480u_cmd_set_ip_mas { - struct uwb_rccb rccb; - struct uwb_dev_addr addr; - u8 stream; - u8 owner; - u8 type; /* enum uwb_drp_type */ - u8 baMAS[32]; -} __attribute__((packed)); - - -static -int i1480u_set_ip_mas( - struct uwb_rc *rc, - const struct uwb_dev_addr *dstaddr, - u8 stream, u8 owner, u8 type, unsigned long *mas) -{ - - int result; - struct i1480u_cmd_set_ip_mas *cmd; - struct uwb_rc_evt_confirm reply; - - result = -ENOMEM; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - goto error_kzalloc; - cmd->rccb.bCommandType = 0xfd; - cmd->rccb.wCommand = cpu_to_le16(0x000e); - cmd->addr = *dstaddr; - cmd->stream = stream; - cmd->owner = owner; - cmd->type = type; - if (mas == NULL) - memset(cmd->baMAS, 0x00, sizeof(cmd->baMAS)); - else - memcpy(cmd->baMAS, mas, sizeof(cmd->baMAS)); - reply.rceb.bEventType = 0xfd; - reply.rceb.wEvent = cpu_to_le16(0x000e); - result = uwb_rc_cmd(rc, "SET-IP-MAS", &cmd->rccb, sizeof(*cmd), - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - if (reply.bResultCode != UWB_RC_RES_FAIL) { - dev_err(&rc->uwb_dev.dev, - "SET-IP-MAS: command execution failed: %d\n", - reply.bResultCode); - result = -EIO; - } -error_cmd: - kfree(cmd); -error_kzalloc: - return result; -} - -/* - * Inform a WLP interface of a MAS reservation - * - * @rc is assumed refcnted. - */ -/* FIXME: detect if remote device is WLP capable? */ -static int i1480u_mas_set_dev(struct uwb_dev *uwb_dev, struct uwb_rc *rc, - u8 stream, u8 owner, u8 type, unsigned long *mas) -{ - int result = 0; - struct device *dev = &rc->uwb_dev.dev; - - result = i1480u_set_ip_mas(rc, &uwb_dev->dev_addr, stream, owner, - type, mas); - if (result < 0) { - char rcaddrbuf[UWB_ADDR_STRSIZE], devaddrbuf[UWB_ADDR_STRSIZE]; - uwb_dev_addr_print(rcaddrbuf, sizeof(rcaddrbuf), - &rc->uwb_dev.dev_addr); - uwb_dev_addr_print(devaddrbuf, sizeof(devaddrbuf), - &uwb_dev->dev_addr); - dev_err(dev, "Set IP MAS (%s to %s) failed: %d\n", - rcaddrbuf, devaddrbuf, result); - } - return result; -} - -/** - * Called by bandwidth allocator when change occurs in reservation. - * - * @rsv: The reservation that is being established, modified, or - * terminated. - * - * When a reservation is established, modified, or terminated the upper layer - * (WLP here) needs set/update the currently available Media Access Slots - * that can be use for IP traffic. - * - * Our action taken during failure depends on how the reservation is being - * changed: - * - if reservation is being established we do nothing if we cannot set the - * new MAS to be used - * - if reservation is being terminated we revert back to PCA whether the - * SET IP MAS command succeeds or not. - */ -void i1480u_bw_alloc_cb(struct uwb_rsv *rsv) -{ - int result = 0; - struct i1480u *i1480u = rsv->pal_priv; - struct device *dev = &i1480u->usb_iface->dev; - struct uwb_dev *target_dev = rsv->target.dev; - struct uwb_rc *rc = i1480u->wlp.rc; - u8 stream = rsv->stream; - int type = rsv->type; - int is_owner = rsv->owner == &rc->uwb_dev; - unsigned long *bmp = rsv->mas.bm; - - dev_err(dev, "WLP callback called - sending set ip mas\n"); - /*user cannot change options while setting configuration*/ - mutex_lock(&i1480u->options.mutex); - switch (rsv->state) { - case UWB_RSV_STATE_T_ACCEPTED: - case UWB_RSV_STATE_O_ESTABLISHED: - result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner, - type, bmp); - if (result < 0) { - dev_err(dev, "MAS reservation failed: %d\n", result); - goto out; - } - if (is_owner) { - wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr, - WLP_DRP | stream); - wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 0); - } - break; - case UWB_RSV_STATE_NONE: - /* revert back to PCA */ - result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner, - type, bmp); - if (result < 0) - dev_err(dev, "MAS reservation failed: %d\n", result); - /* Revert to PCA even though SET IP MAS failed. */ - wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr, - i1480u->options.pca_base_priority); - wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 1); - break; - default: - dev_err(dev, "unexpected WLP reservation state: %s (%d).\n", - uwb_rsv_state_str(rsv->state), rsv->state); - break; - } -out: - mutex_unlock(&i1480u->options.mutex); - return; -} - -/** - * - * Called on 'ifconfig up' - */ -int i1480u_open(struct net_device *net_dev) -{ - int result; - struct i1480u *i1480u = netdev_priv(net_dev); - struct wlp *wlp = &i1480u->wlp; - struct uwb_rc *rc; - struct device *dev = &i1480u->usb_iface->dev; - - rc = wlp->rc; - result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ - if (result < 0) - goto error_rx_setup; - netif_wake_queue(net_dev); -#ifdef i1480u_FLOW_CONTROL - result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);; - if (result < 0) { - dev_err(dev, "Can't submit notification URB: %d\n", result); - goto error_notif_urb_submit; - } -#endif - i1480u->uwb_notifs_handler.cb = i1480u_uwb_notifs_cb; - i1480u->uwb_notifs_handler.data = i1480u; - if (uwb_bg_joined(rc)) - netif_carrier_on(net_dev); - else - netif_carrier_off(net_dev); - uwb_notifs_register(rc, &i1480u->uwb_notifs_handler); - /* Interface is up with an address, now we can create WSS */ - result = wlp_wss_setup(net_dev, &wlp->wss); - if (result < 0) { - dev_err(dev, "Can't create WSS: %d. \n", result); - goto error_notif_deregister; - } - return 0; -error_notif_deregister: - uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); -#ifdef i1480u_FLOW_CONTROL -error_notif_urb_submit: -#endif - netif_stop_queue(net_dev); - i1480u_rx_release(i1480u); -error_rx_setup: - return result; -} - - -/** - * Called on 'ifconfig down' - */ -int i1480u_stop(struct net_device *net_dev) -{ - struct i1480u *i1480u = netdev_priv(net_dev); - struct wlp *wlp = &i1480u->wlp; - struct uwb_rc *rc = wlp->rc; - - BUG_ON(wlp->rc == NULL); - wlp_wss_remove(&wlp->wss); - uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); - netif_carrier_off(net_dev); -#ifdef i1480u_FLOW_CONTROL - usb_kill_urb(i1480u->notif_urb); -#endif - netif_stop_queue(net_dev); - i1480u_rx_release(i1480u); - i1480u_tx_release(i1480u); - return 0; -} - - -/** Report statistics */ -struct net_device_stats *i1480u_get_stats(struct net_device *net_dev) -{ - struct i1480u *i1480u = netdev_priv(net_dev); - return &i1480u->stats; -} - - -/** - * - * Change the interface config--we probably don't have to do anything. - */ -int i1480u_set_config(struct net_device *net_dev, struct ifmap *map) -{ - int result; - struct i1480u *i1480u = netdev_priv(net_dev); - BUG_ON(i1480u->wlp.rc == NULL); - result = 0; - return result; -} - -/** - * Change the MTU of the interface - */ -int i1480u_change_mtu(struct net_device *net_dev, int mtu) -{ - static union { - struct wlp_tx_hdr tx; - struct wlp_rx_hdr rx; - } i1480u_all_hdrs; - - if (mtu < ETH_HLEN) /* We encap eth frames */ - return -ERANGE; - if (mtu > 4000 - sizeof(i1480u_all_hdrs)) - return -ERANGE; - net_dev->mtu = mtu; - return 0; -} - - -/** - * Callback function to handle events from UWB - * When we see other devices we know the carrier is ok, - * if we are the only device in the beacon group we set the carrier - * state to off. - * */ -void i1480u_uwb_notifs_cb(void *data, struct uwb_dev *uwb_dev, - enum uwb_notifs event) -{ - struct i1480u *i1480u = data; - struct net_device *net_dev = i1480u->net_dev; - struct device *dev = &i1480u->usb_iface->dev; - switch (event) { - case UWB_NOTIF_BG_JOIN: - netif_carrier_on(net_dev); - dev_info(dev, "Link is up\n"); - break; - case UWB_NOTIF_BG_LEAVE: - netif_carrier_off(net_dev); - dev_info(dev, "Link is down\n"); - break; - default: - dev_err(dev, "don't know how to handle event %d from uwb\n", - event); - } -} - -/** - * Stop the network queue - * - * Enable WLP substack to stop network queue. We also set the flow control - * threshold at this time to prevent the flow control from restarting the - * queue. - * - * we are loosing the current threshold value here ... FIXME? - */ -void i1480u_stop_queue(struct wlp *wlp) -{ - struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); - struct net_device *net_dev = i1480u->net_dev; - i1480u->tx_inflight.threshold = 0; - netif_stop_queue(net_dev); -} - -/** - * Start the network queue - * - * Enable WLP substack to start network queue. Also re-enable the flow - * control to manage the queue again. - * - * We re-enable the flow control by storing the default threshold in the - * flow control threshold. This means that if the user modified the - * threshold before the queue was stopped and restarted that information - * will be lost. FIXME? - */ -void i1480u_start_queue(struct wlp *wlp) -{ - struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); - struct net_device *net_dev = i1480u->net_dev; - i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD; - netif_start_queue(net_dev); -} diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/rx.c b/trunk/drivers/uwb/i1480/i1480u-wlp/rx.c deleted file mode 100644 index 9fc035354a76..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/rx.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Driver for the Linux Network stack. - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * i1480u's RX handling is simple. i1480u will send the received - * network packets broken up in fragments; 1 to N fragments make a - * packet, we assemble them together and deliver the packet with netif_rx(). - * - * Beacuse each USB transfer is a *single* fragment (except when the - * transfer contains a first fragment), each URB called thus - * back contains one or two fragments. So we queue N URBs, each with its own - * fragment buffer. When a URB is done, we process it (adding to the - * current skb from the fragment buffer until complete). Once - * processed, we requeue the URB. There is always a bunch of URBs - * ready to take data, so the intergap should be minimal. - * - * An URB's transfer buffer is the data field of a socket buffer. This - * reduces copying as data can be passed directly to network layer. If a - * complete packet or 1st fragment is received the URB's transfer buffer is - * taken away from it and used to send data to the network layer. In this - * case a new transfer buffer is allocated to the URB before being requeued. - * If a "NEXT" or "LAST" fragment is received, the fragment contents is - * appended to the RX packet under construction and the transfer buffer - * is reused. To be able to use this buffer to assemble complete packets - * we set each buffer's size to that of the MAX ethernet packet that can - * be received. There is thus room for improvement in memory usage. - * - * When the max tx fragment size increases, we should be able to read - * data into the skbs directly with very simple code. - * - * ROADMAP: - * - * ENTRY POINTS: - * - * i1480u_rx_setup(): setup RX context [from i1480u_open()] - * - * i1480u_rx_release(): release RX context [from i1480u_stop()] - * - * i1480u_rx_cb(): called when the RX USB URB receives a - * packet. It removes the header and pushes it up - * the Linux netdev stack with netif_rx(). - * - * i1480u_rx_buffer() - * i1480u_drop() and i1480u_fix() - * i1480u_skb_deliver - * - */ - -#include -#include -#include "i1480u-wlp.h" - -#define D_LOCAL 0 -#include - - -/** - * Setup the RX context - * - * Each URB is provided with a transfer_buffer that is the data field - * of a new socket buffer. - */ -int i1480u_rx_setup(struct i1480u *i1480u) -{ - int result, cnt; - struct device *dev = &i1480u->usb_iface->dev; - struct net_device *net_dev = i1480u->net_dev; - struct usb_endpoint_descriptor *epd; - struct sk_buff *skb; - - /* Alloc RX stuff */ - i1480u->rx_skb = NULL; /* not in process of receiving packet */ - result = -ENOMEM; - epd = &i1480u->usb_iface->cur_altsetting->endpoint[1].desc; - for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) { - struct i1480u_rx_buf *rx_buf = &i1480u->rx_buf[cnt]; - rx_buf->i1480u = i1480u; - skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE); - if (!skb) { - dev_err(dev, - "RX: cannot allocate RX buffer %d\n", cnt); - result = -ENOMEM; - goto error; - } - skb->dev = net_dev; - skb->ip_summed = CHECKSUM_NONE; - skb_reserve(skb, 2); - rx_buf->data = skb; - rx_buf->urb = usb_alloc_urb(0, GFP_KERNEL); - if (unlikely(rx_buf->urb == NULL)) { - dev_err(dev, "RX: cannot allocate URB %d\n", cnt); - result = -ENOMEM; - goto error; - } - usb_fill_bulk_urb(rx_buf->urb, i1480u->usb_dev, - usb_rcvbulkpipe(i1480u->usb_dev, epd->bEndpointAddress), - rx_buf->data->data, i1480u_MAX_RX_PKT_SIZE - 2, - i1480u_rx_cb, rx_buf); - result = usb_submit_urb(rx_buf->urb, GFP_NOIO); - if (unlikely(result < 0)) { - dev_err(dev, "RX: cannot submit URB %d: %d\n", - cnt, result); - goto error; - } - } - return 0; - -error: - i1480u_rx_release(i1480u); - return result; -} - - -/** Release resources associated to the rx context */ -void i1480u_rx_release(struct i1480u *i1480u) -{ - int cnt; - for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) { - if (i1480u->rx_buf[cnt].data) - dev_kfree_skb(i1480u->rx_buf[cnt].data); - if (i1480u->rx_buf[cnt].urb) { - usb_kill_urb(i1480u->rx_buf[cnt].urb); - usb_free_urb(i1480u->rx_buf[cnt].urb); - } - } - if (i1480u->rx_skb != NULL) - dev_kfree_skb(i1480u->rx_skb); -} - -static -void i1480u_rx_unlink_urbs(struct i1480u *i1480u) -{ - int cnt; - for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) { - if (i1480u->rx_buf[cnt].urb) - usb_unlink_urb(i1480u->rx_buf[cnt].urb); - } -} - -/** Fix an out-of-sequence packet */ -#define i1480u_fix(i1480u, msg...) \ -do { \ - if (printk_ratelimit()) \ - dev_err(&i1480u->usb_iface->dev, msg); \ - dev_kfree_skb_irq(i1480u->rx_skb); \ - i1480u->rx_skb = NULL; \ - i1480u->rx_untd_pkt_size = 0; \ -} while (0) - - -/** Drop an out-of-sequence packet */ -#define i1480u_drop(i1480u, msg...) \ -do { \ - if (printk_ratelimit()) \ - dev_err(&i1480u->usb_iface->dev, msg); \ - i1480u->stats.rx_dropped++; \ -} while (0) - - - - -/** Finalizes setting up the SKB and delivers it - * - * We first pass the incoming frame to WLP substack for verification. It - * may also be a WLP association frame in which case WLP will take over the - * processing. If WLP does not take it over it will still verify it, if the - * frame is invalid the skb will be freed by WLP and we will not continue - * parsing. - * */ -static -void i1480u_skb_deliver(struct i1480u *i1480u) -{ - int should_parse; - struct net_device *net_dev = i1480u->net_dev; - struct device *dev = &i1480u->usb_iface->dev; - - d_printf(6, dev, "RX delivered pre skb(%p), %u bytes\n", - i1480u->rx_skb, i1480u->rx_skb->len); - d_dump(7, dev, i1480u->rx_skb->data, i1480u->rx_skb->len); - should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb, - &i1480u->rx_srcaddr); - if (!should_parse) - goto out; - i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev); - d_printf(5, dev, "RX delivered skb(%p), %u bytes\n", - i1480u->rx_skb, i1480u->rx_skb->len); - d_dump(7, dev, i1480u->rx_skb->data, - i1480u->rx_skb->len > 72 ? 72 : i1480u->rx_skb->len); - i1480u->stats.rx_packets++; - i1480u->stats.rx_bytes += i1480u->rx_untd_pkt_size; - net_dev->last_rx = jiffies; - /* FIXME: flow control: check netif_rx() retval */ - - netif_rx(i1480u->rx_skb); /* deliver */ -out: - i1480u->rx_skb = NULL; - i1480u->rx_untd_pkt_size = 0; -} - - -/** - * Process a buffer of data received from the USB RX endpoint - * - * First fragment arrives with next or last fragment. All other fragments - * arrive alone. - * - * /me hates long functions. - */ -static -void i1480u_rx_buffer(struct i1480u_rx_buf *rx_buf) -{ - unsigned pkt_completed = 0; /* !0 when we got all pkt fragments */ - size_t untd_hdr_size, untd_frg_size; - size_t i1480u_hdr_size; - struct wlp_rx_hdr *i1480u_hdr = NULL; - - struct i1480u *i1480u = rx_buf->i1480u; - struct sk_buff *skb = rx_buf->data; - int size_left = rx_buf->urb->actual_length; - void *ptr = rx_buf->urb->transfer_buffer; /* also rx_buf->data->data */ - struct untd_hdr *untd_hdr; - - struct net_device *net_dev = i1480u->net_dev; - struct device *dev = &i1480u->usb_iface->dev; - struct sk_buff *new_skb; - -#if 0 - dev_fnstart(dev, - "(i1480u %p ptr %p size_left %zu)\n", i1480u, ptr, size_left); - dev_err(dev, "RX packet, %zu bytes\n", size_left); - dump_bytes(dev, ptr, size_left); -#endif - i1480u_hdr_size = sizeof(struct wlp_rx_hdr); - - while (size_left > 0) { - if (pkt_completed) { - i1480u_drop(i1480u, "RX: fragment follows completed" - "packet in same buffer. Dropping\n"); - break; - } - untd_hdr = ptr; - if (size_left < sizeof(*untd_hdr)) { /* Check the UNTD header */ - i1480u_drop(i1480u, "RX: short UNTD header! Dropping\n"); - goto out; - } - if (unlikely(untd_hdr_rx_tx(untd_hdr) == 0)) { /* Paranoia: TX set? */ - i1480u_drop(i1480u, "RX: TX bit set! Dropping\n"); - goto out; - } - switch (untd_hdr_type(untd_hdr)) { /* Check the UNTD header type */ - case i1480u_PKT_FRAG_1ST: { - struct untd_hdr_1st *untd_hdr_1st = (void *) untd_hdr; - dev_dbg(dev, "1st fragment\n"); - untd_hdr_size = sizeof(struct untd_hdr_1st); - if (i1480u->rx_skb != NULL) - i1480u_fix(i1480u, "RX: 1st fragment out of " - "sequence! Fixing\n"); - if (size_left < untd_hdr_size + i1480u_hdr_size) { - i1480u_drop(i1480u, "RX: short 1st fragment! " - "Dropping\n"); - goto out; - } - i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len) - - i1480u_hdr_size; - untd_frg_size = le16_to_cpu(untd_hdr_1st->fragment_len); - if (size_left < untd_hdr_size + untd_frg_size) { - i1480u_drop(i1480u, - "RX: short payload! Dropping\n"); - goto out; - } - i1480u->rx_skb = skb; - i1480u_hdr = (void *) untd_hdr_1st + untd_hdr_size; - i1480u->rx_srcaddr = i1480u_hdr->srcaddr; - skb_put(i1480u->rx_skb, untd_hdr_size + untd_frg_size); - skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size); - stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7); - stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18); - rx_buf->data = NULL; /* need to create new buffer */ - break; - } - case i1480u_PKT_FRAG_NXT: { - dev_dbg(dev, "nxt fragment\n"); - untd_hdr_size = sizeof(struct untd_hdr_rst); - if (i1480u->rx_skb == NULL) { - i1480u_drop(i1480u, "RX: next fragment out of " - "sequence! Dropping\n"); - goto out; - } - if (size_left < untd_hdr_size) { - i1480u_drop(i1480u, "RX: short NXT fragment! " - "Dropping\n"); - goto out; - } - untd_frg_size = le16_to_cpu(untd_hdr->len); - if (size_left < untd_hdr_size + untd_frg_size) { - i1480u_drop(i1480u, - "RX: short payload! Dropping\n"); - goto out; - } - memmove(skb_put(i1480u->rx_skb, untd_frg_size), - ptr + untd_hdr_size, untd_frg_size); - break; - } - case i1480u_PKT_FRAG_LST: { - dev_dbg(dev, "Lst fragment\n"); - untd_hdr_size = sizeof(struct untd_hdr_rst); - if (i1480u->rx_skb == NULL) { - i1480u_drop(i1480u, "RX: last fragment out of " - "sequence! Dropping\n"); - goto out; - } - if (size_left < untd_hdr_size) { - i1480u_drop(i1480u, "RX: short LST fragment! " - "Dropping\n"); - goto out; - } - untd_frg_size = le16_to_cpu(untd_hdr->len); - if (size_left < untd_frg_size + untd_hdr_size) { - i1480u_drop(i1480u, - "RX: short payload! Dropping\n"); - goto out; - } - memmove(skb_put(i1480u->rx_skb, untd_frg_size), - ptr + untd_hdr_size, untd_frg_size); - pkt_completed = 1; - break; - } - case i1480u_PKT_FRAG_CMP: { - dev_dbg(dev, "cmp fragment\n"); - untd_hdr_size = sizeof(struct untd_hdr_cmp); - if (i1480u->rx_skb != NULL) - i1480u_fix(i1480u, "RX: fix out-of-sequence CMP" - " fragment!\n"); - if (size_left < untd_hdr_size + i1480u_hdr_size) { - i1480u_drop(i1480u, "RX: short CMP fragment! " - "Dropping\n"); - goto out; - } - i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len); - untd_frg_size = i1480u->rx_untd_pkt_size; - if (size_left < i1480u->rx_untd_pkt_size + untd_hdr_size) { - i1480u_drop(i1480u, - "RX: short payload! Dropping\n"); - goto out; - } - i1480u->rx_skb = skb; - i1480u_hdr = (void *) untd_hdr + untd_hdr_size; - i1480u->rx_srcaddr = i1480u_hdr->srcaddr; - stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7); - stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18); - skb_put(i1480u->rx_skb, untd_hdr_size + i1480u->rx_untd_pkt_size); - skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size); - rx_buf->data = NULL; /* for hand off skb to network stack */ - pkt_completed = 1; - i1480u->rx_untd_pkt_size -= i1480u_hdr_size; /* accurate stat */ - break; - } - default: - i1480u_drop(i1480u, "RX: unknown packet type %u! " - "Dropping\n", untd_hdr_type(untd_hdr)); - goto out; - } - size_left -= untd_hdr_size + untd_frg_size; - if (size_left > 0) - ptr += untd_hdr_size + untd_frg_size; - } - if (pkt_completed) - i1480u_skb_deliver(i1480u); -out: - /* recreate needed RX buffers*/ - if (rx_buf->data == NULL) { - /* buffer is being used to receive packet, create new */ - new_skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE); - if (!new_skb) { - if (printk_ratelimit()) - dev_err(dev, - "RX: cannot allocate RX buffer\n"); - } else { - new_skb->dev = net_dev; - new_skb->ip_summed = CHECKSUM_NONE; - skb_reserve(new_skb, 2); - rx_buf->data = new_skb; - } - } - return; -} - - -/** - * Called when an RX URB has finished receiving or has found some kind - * of error condition. - * - * LIMITATIONS: - * - * - We read USB-transfers, each transfer contains a SINGLE fragment - * (can contain a complete packet, or a 1st, next, or last fragment - * of a packet). - * Looks like a transfer can contain more than one fragment (07/18/06) - * - * - Each transfer buffer is the size of the maximum packet size (minus - * headroom), i1480u_MAX_PKT_SIZE - 2 - * - * - We always read the full USB-transfer, no partials. - * - * - Each transfer is read directly into a skb. This skb will be used to - * send data to the upper layers if it is the first fragment or a complete - * packet. In the other cases the data will be copied from the skb to - * another skb that is being prepared for the upper layers from a prev - * first fragment. - * - * It is simply too much of a pain. Gosh, there should be a unified - * SG infrastructure for *everything* [so that I could declare a SG - * buffer, pass it to USB for receiving, append some space to it if - * I wish, receive more until I have the whole chunk, adapt - * pointers on each fragment to remove hardware headers and then - * attach that to an skbuff and netif_rx()]. - */ -void i1480u_rx_cb(struct urb *urb) -{ - int result; - int do_parse_buffer = 1; - struct i1480u_rx_buf *rx_buf = urb->context; - struct i1480u *i1480u = rx_buf->i1480u; - struct device *dev = &i1480u->usb_iface->dev; - unsigned long flags; - u8 rx_buf_idx = rx_buf - i1480u->rx_buf; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: /* Not an error, but a controlled situation; */ - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - case -ESHUTDOWN: /* going away! */ - dev_err(dev, "RX URB[%u]: goind down %d\n", - rx_buf_idx, urb->status); - goto error; - default: - dev_err(dev, "RX URB[%u]: unknown status %d\n", - rx_buf_idx, urb->status); - if (edc_inc(&i1480u->rx_errors, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "RX: max acceptable errors exceeded," - " resetting device.\n"); - i1480u_rx_unlink_urbs(i1480u); - wlp_reset_all(&i1480u->wlp); - goto error; - } - do_parse_buffer = 0; - break; - } - spin_lock_irqsave(&i1480u->lock, flags); - /* chew the data fragments, extract network packets */ - if (do_parse_buffer) { - i1480u_rx_buffer(rx_buf); - if (rx_buf->data) { - rx_buf->urb->transfer_buffer = rx_buf->data->data; - result = usb_submit_urb(rx_buf->urb, GFP_ATOMIC); - if (result < 0) { - dev_err(dev, "RX URB[%u]: cannot submit %d\n", - rx_buf_idx, result); - } - } - } - spin_unlock_irqrestore(&i1480u->lock, flags); -error: - return; -} - diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/trunk/drivers/uwb/i1480/i1480u-wlp/sysfs.c deleted file mode 100644 index a1d8ca6ac935..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/sysfs.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Sysfs interfaces - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#include -#include -#include -#include "i1480u-wlp.h" - - -/** - * - * @dev: Class device from the net_device; assumed refcnted. - * - * Yes, I don't lock--we assume it is refcounted and I am getting a - * single byte value that is kind of atomic to read. - */ -ssize_t uwb_phy_rate_show(const struct wlp_options *options, char *buf) -{ - return sprintf(buf, "%u\n", - wlp_tx_hdr_phy_rate(&options->def_tx_hdr)); -} -EXPORT_SYMBOL_GPL(uwb_phy_rate_show); - - -ssize_t uwb_phy_rate_store(struct wlp_options *options, - const char *buf, size_t size) -{ - ssize_t result; - unsigned rate; - - result = sscanf(buf, "%u\n", &rate); - if (result != 1) { - result = -EINVAL; - goto out; - } - result = -EINVAL; - if (rate >= UWB_PHY_RATE_INVALID) - goto out; - wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, rate); - result = 0; -out: - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(uwb_phy_rate_store); - - -ssize_t uwb_rts_cts_show(const struct wlp_options *options, char *buf) -{ - return sprintf(buf, "%u\n", - wlp_tx_hdr_rts_cts(&options->def_tx_hdr)); -} -EXPORT_SYMBOL_GPL(uwb_rts_cts_show); - - -ssize_t uwb_rts_cts_store(struct wlp_options *options, - const char *buf, size_t size) -{ - ssize_t result; - unsigned value; - - result = sscanf(buf, "%u\n", &value); - if (result != 1) { - result = -EINVAL; - goto out; - } - result = -EINVAL; - wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, !!value); - result = 0; -out: - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(uwb_rts_cts_store); - - -ssize_t uwb_ack_policy_show(const struct wlp_options *options, char *buf) -{ - return sprintf(buf, "%u\n", - wlp_tx_hdr_ack_policy(&options->def_tx_hdr)); -} -EXPORT_SYMBOL_GPL(uwb_ack_policy_show); - - -ssize_t uwb_ack_policy_store(struct wlp_options *options, - const char *buf, size_t size) -{ - ssize_t result; - unsigned value; - - result = sscanf(buf, "%u\n", &value); - if (result != 1 || value > UWB_ACK_B_REQ) { - result = -EINVAL; - goto out; - } - wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, value); - result = 0; -out: - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(uwb_ack_policy_store); - - -/** - * Show the PCA base priority. - * - * We can access without locking, as the value is (for now) orthogonal - * to other values. - */ -ssize_t uwb_pca_base_priority_show(const struct wlp_options *options, - char *buf) -{ - return sprintf(buf, "%u\n", - options->pca_base_priority); -} -EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show); - - -/** - * Set the PCA base priority. - * - * We can access without locking, as the value is (for now) orthogonal - * to other values. - */ -ssize_t uwb_pca_base_priority_store(struct wlp_options *options, - const char *buf, size_t size) -{ - ssize_t result = -EINVAL; - u8 pca_base_priority; - - result = sscanf(buf, "%hhu\n", &pca_base_priority); - if (result != 1) { - result = -EINVAL; - goto out; - } - result = -EINVAL; - if (pca_base_priority >= 8) - goto out; - options->pca_base_priority = pca_base_priority; - /* Update TX header if we are currently using PCA. */ - if (result >= 0 && (wlp_tx_hdr_delivery_id_type(&options->def_tx_hdr) & WLP_DRP) == 0) - wlp_tx_hdr_set_delivery_id_type(&options->def_tx_hdr, options->pca_base_priority); - result = 0; -out: - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store); - -/** - * Show current inflight values - * - * Will print the current MAX and THRESHOLD values for the basic flow - * control. In addition it will report how many times the TX queue needed - * to be restarted since the last time this query was made. - */ -static ssize_t wlp_tx_inflight_show(struct i1480u_tx_inflight *inflight, - char *buf) -{ - ssize_t result; - unsigned long sec_elapsed = (jiffies - inflight->restart_ts)/HZ; - unsigned long restart_count = atomic_read(&inflight->restart_count); - - result = scnprintf(buf, PAGE_SIZE, "%lu %lu %d %lu %lu %lu\n" - "#read: threshold max inflight_count restarts " - "seconds restarts/sec\n" - "#write: threshold max\n", - inflight->threshold, inflight->max, - atomic_read(&inflight->count), - restart_count, sec_elapsed, - sec_elapsed == 0 ? 0 : restart_count/sec_elapsed); - inflight->restart_ts = jiffies; - atomic_set(&inflight->restart_count, 0); - return result; -} - -static -ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight, - const char *buf, size_t size) -{ - unsigned long in_threshold, in_max; - ssize_t result; - result = sscanf(buf, "%lu %lu", &in_threshold, &in_max); - if (result != 2) - return -EINVAL; - if (in_max <= in_threshold) - return -EINVAL; - inflight->max = in_max; - inflight->threshold = in_threshold; - return size; -} -/* - * Glue (or function adaptors) for accesing info on sysfs - * - * [we need this indirection because the PCI driver does almost the - * same] - * - * Linux 2.6.21 changed how 'struct netdevice' does attributes (from - * having a 'struct class_dev' to having a 'struct device'). That is - * quite of a pain. - * - * So we try to abstract that here. i1480u_SHOW() and i1480u_STORE() - * create adaptors for extracting the 'struct i1480u' from a 'struct - * dev' and calling a function for doing a sysfs operation (as we have - * them factorized already). i1480u_ATTR creates the attribute file - * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a - * class_device_attr_NAME or device_attr_NAME (for group registration). - */ -#include - -#define i1480u_SHOW(name, fn, param) \ -static ssize_t i1480u_show_##name(struct device *dev, \ - struct device_attribute *attr,\ - char *buf) \ -{ \ - struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \ - return fn(&i1480u->param, buf); \ -} - -#define i1480u_STORE(name, fn, param) \ -static ssize_t i1480u_store_##name(struct device *dev, \ - struct device_attribute *attr,\ - const char *buf, size_t size)\ -{ \ - struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \ - return fn(&i1480u->param, buf, size); \ -} - -#define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm, \ - i1480u_show_##name,\ - i1480u_store_##name) - -#define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name, \ - S_IRUGO, \ - i1480u_show_##name, NULL) - -#define i1480u_ATTR_NAME(a) (dev_attr_##a) - - -/* - * Sysfs adaptors - */ -i1480u_SHOW(uwb_phy_rate, uwb_phy_rate_show, options); -i1480u_STORE(uwb_phy_rate, uwb_phy_rate_store, options); -i1480u_ATTR(uwb_phy_rate, S_IRUGO | S_IWUSR); - -i1480u_SHOW(uwb_rts_cts, uwb_rts_cts_show, options); -i1480u_STORE(uwb_rts_cts, uwb_rts_cts_store, options); -i1480u_ATTR(uwb_rts_cts, S_IRUGO | S_IWUSR); - -i1480u_SHOW(uwb_ack_policy, uwb_ack_policy_show, options); -i1480u_STORE(uwb_ack_policy, uwb_ack_policy_store, options); -i1480u_ATTR(uwb_ack_policy, S_IRUGO | S_IWUSR); - -i1480u_SHOW(uwb_pca_base_priority, uwb_pca_base_priority_show, options); -i1480u_STORE(uwb_pca_base_priority, uwb_pca_base_priority_store, options); -i1480u_ATTR(uwb_pca_base_priority, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_eda, wlp_eda_show, wlp); -i1480u_STORE(wlp_eda, wlp_eda_store, wlp); -i1480u_ATTR(wlp_eda, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_uuid, wlp_uuid_show, wlp); -i1480u_STORE(wlp_uuid, wlp_uuid_store, wlp); -i1480u_ATTR(wlp_uuid, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_name, wlp_dev_name_show, wlp); -i1480u_STORE(wlp_dev_name, wlp_dev_name_store, wlp); -i1480u_ATTR(wlp_dev_name, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_manufacturer, wlp_dev_manufacturer_show, wlp); -i1480u_STORE(wlp_dev_manufacturer, wlp_dev_manufacturer_store, wlp); -i1480u_ATTR(wlp_dev_manufacturer, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_model_name, wlp_dev_model_name_show, wlp); -i1480u_STORE(wlp_dev_model_name, wlp_dev_model_name_store, wlp); -i1480u_ATTR(wlp_dev_model_name, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_model_nr, wlp_dev_model_nr_show, wlp); -i1480u_STORE(wlp_dev_model_nr, wlp_dev_model_nr_store, wlp); -i1480u_ATTR(wlp_dev_model_nr, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_serial, wlp_dev_serial_show, wlp); -i1480u_STORE(wlp_dev_serial, wlp_dev_serial_store, wlp); -i1480u_ATTR(wlp_dev_serial, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_prim_category, wlp_dev_prim_category_show, wlp); -i1480u_STORE(wlp_dev_prim_category, wlp_dev_prim_category_store, wlp); -i1480u_ATTR(wlp_dev_prim_category, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_prim_OUI, wlp_dev_prim_OUI_show, wlp); -i1480u_STORE(wlp_dev_prim_OUI, wlp_dev_prim_OUI_store, wlp); -i1480u_ATTR(wlp_dev_prim_OUI, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_show, wlp); -i1480u_STORE(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_store, wlp); -i1480u_ATTR(wlp_dev_prim_OUI_sub, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_dev_prim_subcat, wlp_dev_prim_subcat_show, wlp); -i1480u_STORE(wlp_dev_prim_subcat, wlp_dev_prim_subcat_store, wlp); -i1480u_ATTR(wlp_dev_prim_subcat, S_IRUGO | S_IWUSR); - -i1480u_SHOW(wlp_neighborhood, wlp_neighborhood_show, wlp); -i1480u_ATTR_SHOW(wlp_neighborhood); - -i1480u_SHOW(wss_activate, wlp_wss_activate_show, wlp.wss); -i1480u_STORE(wss_activate, wlp_wss_activate_store, wlp.wss); -i1480u_ATTR(wss_activate, S_IRUGO | S_IWUSR); - -/* - * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over - * the last 256 received WLP frames (ECMA-368 13.3). - * - * [the -7dB that have to be substracted from the LQI to make the LQE - * are already taken into account]. - */ -i1480u_SHOW(wlp_lqe, stats_show, lqe_stats); -i1480u_STORE(wlp_lqe, stats_store, lqe_stats); -i1480u_ATTR(wlp_lqe, S_IRUGO | S_IWUSR); - -/* - * Show the Receive Signal Strength Indicator averaged over all the - * received WLP frames (ECMA-368 13.3). Still is not clear what - * this value is, but is kind of a percentage of the signal strength - * at the antenna. - */ -i1480u_SHOW(wlp_rssi, stats_show, rssi_stats); -i1480u_STORE(wlp_rssi, stats_store, rssi_stats); -i1480u_ATTR(wlp_rssi, S_IRUGO | S_IWUSR); - -/** - * We maintain a basic flow control counter. "count" how many TX URBs are - * outstanding. Only allow "max" - * TX URBs to be outstanding. If this value is reached the queue will be - * stopped. The queue will be restarted when there are - * "threshold" URBs outstanding. - */ -i1480u_SHOW(wlp_tx_inflight, wlp_tx_inflight_show, tx_inflight); -i1480u_STORE(wlp_tx_inflight, wlp_tx_inflight_store, tx_inflight); -i1480u_ATTR(wlp_tx_inflight, S_IRUGO | S_IWUSR); - -static struct attribute *i1480u_attrs[] = { - &i1480u_ATTR_NAME(uwb_phy_rate).attr, - &i1480u_ATTR_NAME(uwb_rts_cts).attr, - &i1480u_ATTR_NAME(uwb_ack_policy).attr, - &i1480u_ATTR_NAME(uwb_pca_base_priority).attr, - &i1480u_ATTR_NAME(wlp_lqe).attr, - &i1480u_ATTR_NAME(wlp_rssi).attr, - &i1480u_ATTR_NAME(wlp_eda).attr, - &i1480u_ATTR_NAME(wlp_uuid).attr, - &i1480u_ATTR_NAME(wlp_dev_name).attr, - &i1480u_ATTR_NAME(wlp_dev_manufacturer).attr, - &i1480u_ATTR_NAME(wlp_dev_model_name).attr, - &i1480u_ATTR_NAME(wlp_dev_model_nr).attr, - &i1480u_ATTR_NAME(wlp_dev_serial).attr, - &i1480u_ATTR_NAME(wlp_dev_prim_category).attr, - &i1480u_ATTR_NAME(wlp_dev_prim_OUI).attr, - &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub).attr, - &i1480u_ATTR_NAME(wlp_dev_prim_subcat).attr, - &i1480u_ATTR_NAME(wlp_neighborhood).attr, - &i1480u_ATTR_NAME(wss_activate).attr, - &i1480u_ATTR_NAME(wlp_tx_inflight).attr, - NULL, -}; - -static struct attribute_group i1480u_attr_group = { - .name = NULL, /* we want them in the same directory */ - .attrs = i1480u_attrs, -}; - -int i1480u_sysfs_setup(struct i1480u *i1480u) -{ - int result; - struct device *dev = &i1480u->usb_iface->dev; - result = sysfs_create_group(&i1480u->net_dev->dev.kobj, - &i1480u_attr_group); - if (result < 0) - dev_err(dev, "cannot initialize sysfs attributes: %d\n", - result); - return result; -} - - -void i1480u_sysfs_release(struct i1480u *i1480u) -{ - sysfs_remove_group(&i1480u->net_dev->dev.kobj, - &i1480u_attr_group); -} diff --git a/trunk/drivers/uwb/i1480/i1480u-wlp/tx.c b/trunk/drivers/uwb/i1480/i1480u-wlp/tx.c deleted file mode 100644 index 3426bfb68240..000000000000 --- a/trunk/drivers/uwb/i1480/i1480u-wlp/tx.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Deal with TX (massaging data to transmit, handling it) - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Transmission engine. Get an skb, create from that a WLP transmit - * context, add a WLP TX header (which we keep prefilled in the - * device's instance), fill out the target-specific fields and - * fire it. - * - * ROADMAP: - * - * Entry points: - * - * i1480u_tx_release(): called by i1480u_disconnect() to release - * pending tx contexts. - * - * i1480u_tx_cb(): callback for TX contexts (USB URBs) - * i1480u_tx_destroy(): - * - * i1480u_tx_timeout(): called for timeout handling from the - * network stack. - * - * i1480u_hard_start_xmit(): called for transmitting an skb from - * the network stack. Will interact with WLP - * substack to verify and prepare frame. - * i1480u_xmit_frame(): actual transmission on hardware - * - * i1480u_tx_create() Creates TX context - * i1480u_tx_create_1() For packets in 1 fragment - * i1480u_tx_create_n() For packets in >1 fragments - * - * TODO: - * - * - FIXME: rewrite using usb_sg_*(), add asynch support to - * usb_sg_*(). It might not make too much sense as most of - * the times the MTU will be smaller than one page... - */ - -#include "i1480u-wlp.h" -#define D_LOCAL 5 -#include - -enum { - /* This is only for Next and Last TX packets */ - i1480u_MAX_PL_SIZE = i1480u_MAX_FRG_SIZE - - sizeof(struct untd_hdr_rst), -}; - -/** Free resources allocated to a i1480u tx context. */ -static -void i1480u_tx_free(struct i1480u_tx *wtx) -{ - kfree(wtx->buf); - if (wtx->skb) - dev_kfree_skb_irq(wtx->skb); - usb_free_urb(wtx->urb); - kfree(wtx); -} - -static -void i1480u_tx_destroy(struct i1480u *i1480u, struct i1480u_tx *wtx) -{ - unsigned long flags; - spin_lock_irqsave(&i1480u->tx_list_lock, flags); /* not active any more */ - list_del(&wtx->list_node); - i1480u_tx_free(wtx); - spin_unlock_irqrestore(&i1480u->tx_list_lock, flags); -} - -static -void i1480u_tx_unlink_urbs(struct i1480u *i1480u) -{ - unsigned long flags; - struct i1480u_tx *wtx, *next; - - spin_lock_irqsave(&i1480u->tx_list_lock, flags); - list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) { - usb_unlink_urb(wtx->urb); - } - spin_unlock_irqrestore(&i1480u->tx_list_lock, flags); -} - - -/** - * Callback for a completed tx USB URB. - * - * TODO: - * - * - FIXME: recover errors more gracefully - * - FIXME: handle NAKs (I dont think they come here) for flow ctl - */ -static -void i1480u_tx_cb(struct urb *urb) -{ - struct i1480u_tx *wtx = urb->context; - struct i1480u *i1480u = wtx->i1480u; - struct net_device *net_dev = i1480u->net_dev; - struct device *dev = &i1480u->usb_iface->dev; - unsigned long flags; - - switch (urb->status) { - case 0: - spin_lock_irqsave(&i1480u->lock, flags); - i1480u->stats.tx_packets++; - i1480u->stats.tx_bytes += urb->actual_length; - spin_unlock_irqrestore(&i1480u->lock, flags); - break; - case -ECONNRESET: /* Not an error, but a controlled situation; */ - case -ENOENT: /* (we killed the URB)...so, no broadcast */ - dev_dbg(dev, "notif endp: reset/noent %d\n", urb->status); - netif_stop_queue(net_dev); - break; - case -ESHUTDOWN: /* going away! */ - dev_dbg(dev, "notif endp: down %d\n", urb->status); - netif_stop_queue(net_dev); - break; - default: - dev_err(dev, "TX: unknown URB status %d\n", urb->status); - if (edc_inc(&i1480u->tx_errors, EDC_MAX_ERRORS, - EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "TX: max acceptable errors exceeded." - "Reset device.\n"); - netif_stop_queue(net_dev); - i1480u_tx_unlink_urbs(i1480u); - wlp_reset_all(&i1480u->wlp); - } - break; - } - i1480u_tx_destroy(i1480u, wtx); - if (atomic_dec_return(&i1480u->tx_inflight.count) - <= i1480u->tx_inflight.threshold - && netif_queue_stopped(net_dev) - && i1480u->tx_inflight.threshold != 0) { - if (d_test(2) && printk_ratelimit()) - d_printf(2, dev, "Restart queue. \n"); - netif_start_queue(net_dev); - atomic_inc(&i1480u->tx_inflight.restart_count); - } - return; -} - - -/** - * Given a buffer that doesn't fit in a single fragment, create an - * scatter/gather structure for delivery to the USB pipe. - * - * Implements functionality of i1480u_tx_create(). - * - * @wtx: tx descriptor - * @skb: skb to send - * @gfp_mask: gfp allocation mask - * @returns: Pointer to @wtx if ok, NULL on error. - * - * Sorry, TOO LONG a function, but breaking it up is kind of hard - * - * This will break the buffer in chunks smaller than - * i1480u_MAX_FRG_SIZE (including the header) and add proper headers - * to each: - * - * 1st header \ - * i1480 tx header | fragment 1 - * fragment data / - * nxt header \ fragment 2 - * fragment data / - * .. - * .. - * last header \ fragment 3 - * last fragment data / - * - * This does not fill the i1480 TX header, it is left up to the - * caller to do that; you can get it from @wtx->wlp_tx_hdr. - * - * This function consumes the skb unless there is an error. - */ -static -int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb, - gfp_t gfp_mask) -{ - int result; - void *pl; - size_t pl_size; - - void *pl_itr, *buf_itr; - size_t pl_size_left, frgs, pl_size_1st, frg_pl_size = 0; - struct untd_hdr_1st *untd_hdr_1st; - struct wlp_tx_hdr *wlp_tx_hdr; - struct untd_hdr_rst *untd_hdr_rst; - - wtx->skb = NULL; - pl = skb->data; - pl_itr = pl; - pl_size = skb->len; - pl_size_left = pl_size; /* payload size */ - /* First fragment; fits as much as i1480u_MAX_FRG_SIZE minus - * the headers */ - pl_size_1st = i1480u_MAX_FRG_SIZE - - sizeof(struct untd_hdr_1st) - sizeof(struct wlp_tx_hdr); - BUG_ON(pl_size_1st > pl_size); - pl_size_left -= pl_size_1st; - /* The rest have an smaller header (no i1480 TX header). We - * need to break up the payload in blocks smaller than - * i1480u_MAX_PL_SIZE (payload excluding header). */ - frgs = (pl_size_left + i1480u_MAX_PL_SIZE - 1) / i1480u_MAX_PL_SIZE; - /* Allocate space for the new buffer. In this new buffer we'll - * place the headers followed by the data fragment, headers, - * data fragments, etc.. - */ - result = -ENOMEM; - wtx->buf_size = sizeof(*untd_hdr_1st) - + sizeof(*wlp_tx_hdr) - + frgs * sizeof(*untd_hdr_rst) - + pl_size; - wtx->buf = kmalloc(wtx->buf_size, gfp_mask); - if (wtx->buf == NULL) - goto error_buf_alloc; - - buf_itr = wtx->buf; /* We got the space, let's fill it up */ - /* Fill 1st fragment */ - untd_hdr_1st = buf_itr; - buf_itr += sizeof(*untd_hdr_1st); - untd_hdr_set_type(&untd_hdr_1st->hdr, i1480u_PKT_FRAG_1ST); - untd_hdr_set_rx_tx(&untd_hdr_1st->hdr, 0); - untd_hdr_1st->hdr.len = cpu_to_le16(pl_size + sizeof(*wlp_tx_hdr)); - untd_hdr_1st->fragment_len = - cpu_to_le16(pl_size_1st + sizeof(*wlp_tx_hdr)); - memset(untd_hdr_1st->padding, 0, sizeof(untd_hdr_1st->padding)); - /* Set up i1480 header info */ - wlp_tx_hdr = wtx->wlp_tx_hdr = buf_itr; - buf_itr += sizeof(*wlp_tx_hdr); - /* Copy the first fragment */ - memcpy(buf_itr, pl_itr, pl_size_1st); - pl_itr += pl_size_1st; - buf_itr += pl_size_1st; - - /* Now do each remaining fragment */ - result = -EINVAL; - while (pl_size_left > 0) { - d_printf(5, NULL, "ITR HDR: pl_size_left %zu buf_itr %zu\n", - pl_size_left, buf_itr - wtx->buf); - if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf - > wtx->buf_size) { - printk(KERN_ERR "BUG: no space for header\n"); - goto error_bug; - } - d_printf(5, NULL, "ITR HDR 2: pl_size_left %zu buf_itr %zu\n", - pl_size_left, buf_itr - wtx->buf); - untd_hdr_rst = buf_itr; - buf_itr += sizeof(*untd_hdr_rst); - if (pl_size_left > i1480u_MAX_PL_SIZE) { - frg_pl_size = i1480u_MAX_PL_SIZE; - untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_NXT); - } else { - frg_pl_size = pl_size_left; - untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST); - } - d_printf(5, NULL, - "ITR PL: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n", - pl_size_left, buf_itr - wtx->buf, frg_pl_size); - untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0); - untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size); - untd_hdr_rst->padding = 0; - if (buf_itr + frg_pl_size - wtx->buf - > wtx->buf_size) { - printk(KERN_ERR "BUG: no space for payload\n"); - goto error_bug; - } - memcpy(buf_itr, pl_itr, frg_pl_size); - buf_itr += frg_pl_size; - pl_itr += frg_pl_size; - pl_size_left -= frg_pl_size; - d_printf(5, NULL, - "ITR PL 2: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n", - pl_size_left, buf_itr - wtx->buf, frg_pl_size); - } - dev_kfree_skb_irq(skb); - return 0; - -error_bug: - printk(KERN_ERR - "BUG: skb %u bytes\n" - "BUG: frg_pl_size %zd i1480u_MAX_FRG_SIZE %u\n" - "BUG: buf_itr %zu buf_size %zu pl_size_left %zu\n", - skb->len, - frg_pl_size, i1480u_MAX_FRG_SIZE, - buf_itr - wtx->buf, wtx->buf_size, pl_size_left); - - kfree(wtx->buf); -error_buf_alloc: - return result; -} - - -/** - * Given a buffer that fits in a single fragment, fill out a @wtx - * struct for transmitting it down the USB pipe. - * - * Uses the fact that we have space reserved in front of the skbuff - * for hardware headers :] - * - * This does not fill the i1480 TX header, it is left up to the - * caller to do that; you can get it from @wtx->wlp_tx_hdr. - * - * @pl: pointer to payload data - * @pl_size: size of the payuload - * - * This function does not consume the @skb. - */ -static -int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb, - gfp_t gfp_mask) -{ - struct untd_hdr_cmp *untd_hdr_cmp; - struct wlp_tx_hdr *wlp_tx_hdr; - - wtx->buf = NULL; - wtx->skb = skb; - BUG_ON(skb_headroom(skb) < sizeof(*wlp_tx_hdr)); - wlp_tx_hdr = (void *) __skb_push(skb, sizeof(*wlp_tx_hdr)); - wtx->wlp_tx_hdr = wlp_tx_hdr; - BUG_ON(skb_headroom(skb) < sizeof(*untd_hdr_cmp)); - untd_hdr_cmp = (void *) __skb_push(skb, sizeof(*untd_hdr_cmp)); - - untd_hdr_set_type(&untd_hdr_cmp->hdr, i1480u_PKT_FRAG_CMP); - untd_hdr_set_rx_tx(&untd_hdr_cmp->hdr, 0); - untd_hdr_cmp->hdr.len = cpu_to_le16(skb->len - sizeof(*untd_hdr_cmp)); - untd_hdr_cmp->padding = 0; - return 0; -} - - -/** - * Given a skb to transmit, massage it to become palatable for the TX pipe - * - * This will break the buffer in chunks smaller than - * i1480u_MAX_FRG_SIZE and add proper headers to each. - * - * 1st header \ - * i1480 tx header | fragment 1 - * fragment data / - * nxt header \ fragment 2 - * fragment data / - * .. - * .. - * last header \ fragment 3 - * last fragment data / - * - * Each fragment will be always smaller or equal to i1480u_MAX_FRG_SIZE. - * - * If the first fragment is smaller than i1480u_MAX_FRG_SIZE, then the - * following is composed: - * - * complete header \ - * i1480 tx header | single fragment - * packet data / - * - * We were going to use s/g support, but because the interface is - * synch and at the end there is plenty of overhead to do it, it - * didn't seem that worth for data that is going to be smaller than - * one page. - */ -static -struct i1480u_tx *i1480u_tx_create(struct i1480u *i1480u, - struct sk_buff *skb, gfp_t gfp_mask) -{ - int result; - struct usb_endpoint_descriptor *epd; - int usb_pipe; - unsigned long flags; - - struct i1480u_tx *wtx; - const size_t pl_max_size = - i1480u_MAX_FRG_SIZE - sizeof(struct untd_hdr_cmp) - - sizeof(struct wlp_tx_hdr); - - wtx = kmalloc(sizeof(*wtx), gfp_mask); - if (wtx == NULL) - goto error_wtx_alloc; - wtx->urb = usb_alloc_urb(0, gfp_mask); - if (wtx->urb == NULL) - goto error_urb_alloc; - epd = &i1480u->usb_iface->cur_altsetting->endpoint[2].desc; - usb_pipe = usb_sndbulkpipe(i1480u->usb_dev, epd->bEndpointAddress); - /* Fits in a single complete packet or need to split? */ - if (skb->len > pl_max_size) { - result = i1480u_tx_create_n(wtx, skb, gfp_mask); - if (result < 0) - goto error_create; - usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe, - wtx->buf, wtx->buf_size, i1480u_tx_cb, wtx); - } else { - result = i1480u_tx_create_1(wtx, skb, gfp_mask); - if (result < 0) - goto error_create; - usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe, - skb->data, skb->len, i1480u_tx_cb, wtx); - } - spin_lock_irqsave(&i1480u->tx_list_lock, flags); - list_add(&wtx->list_node, &i1480u->tx_list); - spin_unlock_irqrestore(&i1480u->tx_list_lock, flags); - return wtx; - -error_create: - kfree(wtx->urb); -error_urb_alloc: - kfree(wtx); -error_wtx_alloc: - return NULL; -} - -/** - * Actual fragmentation and transmission of frame - * - * @wlp: WLP substack data structure - * @skb: To be transmitted - * @dst: Device address of destination - * @returns: 0 on success, <0 on failure - * - * This function can also be called directly (not just from - * hard_start_xmit), so we also check here if the interface is up before - * taking sending anything. - */ -int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb, - struct uwb_dev_addr *dst) -{ - int result = -ENXIO; - struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); - struct device *dev = &i1480u->usb_iface->dev; - struct net_device *net_dev = i1480u->net_dev; - struct i1480u_tx *wtx; - struct wlp_tx_hdr *wlp_tx_hdr; - static unsigned char dev_bcast[2] = { 0xff, 0xff }; -#if 0 - int lockup = 50; -#endif - - d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len, - net_dev); - BUG_ON(i1480u->wlp.rc == NULL); - if ((net_dev->flags & IFF_UP) == 0) - goto out; - result = -EBUSY; - if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) { - if (d_test(2) && printk_ratelimit()) - d_printf(2, dev, "Max frames in flight " - "stopping queue.\n"); - netif_stop_queue(net_dev); - goto error_max_inflight; - } - result = -ENOMEM; - wtx = i1480u_tx_create(i1480u, skb, GFP_ATOMIC); - if (unlikely(wtx == NULL)) { - if (printk_ratelimit()) - dev_err(dev, "TX: no memory for WLP TX URB," - "dropping packet (in flight %d)\n", - atomic_read(&i1480u->tx_inflight.count)); - netif_stop_queue(net_dev); - goto error_wtx_alloc; - } - wtx->i1480u = i1480u; - /* Fill out the i1480 header; @i1480u->def_tx_hdr read without - * locking. We do so because they are kind of orthogonal to - * each other (and thus not changed in an atomic batch). - * The ETH header is right after the WLP TX header. */ - wlp_tx_hdr = wtx->wlp_tx_hdr; - *wlp_tx_hdr = i1480u->options.def_tx_hdr; - wlp_tx_hdr->dstaddr = *dst; - if (!memcmp(&wlp_tx_hdr->dstaddr, dev_bcast, sizeof(dev_bcast)) - && (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)) { - /*Broadcast message directed to DRP host. Send as best effort - * on PCA. */ - wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority); - } - -#if 0 - dev_info(dev, "TX delivering skb -> USB, %zu bytes\n", skb->len); - dump_bytes(dev, skb->data, skb->len > 72 ? 72 : skb->len); -#endif -#if 0 - /* simulates a device lockup after every lockup# packets */ - if (lockup && ((i1480u->stats.tx_packets + 1) % lockup) == 0) { - /* Simulate a dropped transmit interrupt */ - net_dev->trans_start = jiffies; - netif_stop_queue(net_dev); - dev_err(dev, "Simulate lockup at %ld\n", jiffies); - return result; - } -#endif - - result = usb_submit_urb(wtx->urb, GFP_ATOMIC); /* Go baby */ - if (result < 0) { - dev_err(dev, "TX: cannot submit URB: %d\n", result); - /* We leave the freeing of skb to calling function */ - wtx->skb = NULL; - goto error_tx_urb_submit; - } - atomic_inc(&i1480u->tx_inflight.count); - net_dev->trans_start = jiffies; - d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, - net_dev, result); - return result; - -error_tx_urb_submit: - i1480u_tx_destroy(i1480u, wtx); -error_wtx_alloc: -error_max_inflight: -out: - d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, - net_dev, result); - return result; -} - - -/** - * Transmit an skb Called when an skbuf has to be transmitted - * - * The skb is first passed to WLP substack to ensure this is a valid - * frame. If valid the device address of destination will be filled and - * the WLP header prepended to the skb. If this step fails we fake sending - * the frame, if we return an error the network stack will just keep trying. - * - * Broadcast frames inside a WSS needs to be treated special as multicast is - * not supported. A broadcast frame is sent as unicast to each member of the - * WSS - this is done by the WLP substack when it finds a broadcast frame. - * So, we test if the WLP substack took over the skb and only transmit it - * if it has not (been taken over). - * - * @net_dev->xmit_lock is held - */ -int i1480u_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) -{ - int result; - struct i1480u *i1480u = netdev_priv(net_dev); - struct device *dev = &i1480u->usb_iface->dev; - struct uwb_dev_addr dst; - - d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len, - net_dev); - BUG_ON(i1480u->wlp.rc == NULL); - if ((net_dev->flags & IFF_UP) == 0) - goto error; - result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst); - if (result < 0) { - dev_err(dev, "WLP verification of TX frame failed (%d). " - "Dropping packet.\n", result); - goto error; - } else if (result == 1) { - d_printf(6, dev, "WLP will transmit frame. \n"); - /* trans_start time will be set when WLP actually transmits - * the frame */ - goto out; - } - d_printf(6, dev, "Transmitting frame. \n"); - result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst); - if (result < 0) { - dev_err(dev, "Frame TX failed (%d).\n", result); - goto error; - } - d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, - net_dev, result); - return NETDEV_TX_OK; -error: - dev_kfree_skb_any(skb); - i1480u->stats.tx_dropped++; -out: - d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, - net_dev, result); - return NETDEV_TX_OK; -} - - -/** - * Called when a pkt transmission doesn't complete in a reasonable period - * Device reset may sleep - do it outside of interrupt context (delayed) - */ -void i1480u_tx_timeout(struct net_device *net_dev) -{ - struct i1480u *i1480u = netdev_priv(net_dev); - - wlp_reset_all(&i1480u->wlp); -} - - -void i1480u_tx_release(struct i1480u *i1480u) -{ - unsigned long flags; - struct i1480u_tx *wtx, *next; - int count = 0, empty; - - spin_lock_irqsave(&i1480u->tx_list_lock, flags); - list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) { - count++; - usb_unlink_urb(wtx->urb); - } - spin_unlock_irqrestore(&i1480u->tx_list_lock, flags); - count = count*10; /* i1480ut 200ms per unlinked urb (intervals of 20ms) */ - /* - * We don't like this sollution too much (dirty as it is), but - * it is cheaper than putting a refcount on each i1480u_tx and - * i1480uting for all of them to go away... - * - * Called when no more packets can be added to tx_list - * so can i1480ut for it to be empty. - */ - while (1) { - spin_lock_irqsave(&i1480u->tx_list_lock, flags); - empty = list_empty(&i1480u->tx_list); - spin_unlock_irqrestore(&i1480u->tx_list_lock, flags); - if (empty) - break; - count--; - BUG_ON(count == 0); - msleep(20); - } -} diff --git a/trunk/drivers/uwb/ie.c b/trunk/drivers/uwb/ie.c deleted file mode 100644 index cf6f3d152b9d..000000000000 --- a/trunk/drivers/uwb/ie.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Ultra Wide Band - * Information Element Handling - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include "uwb-internal.h" -#define D_LOCAL 0 -#include - -/** - * uwb_ie_next - get the next IE in a buffer - * @ptr: start of the buffer containing the IE data - * @len: length of the buffer - * - * Both @ptr and @len are updated so subsequent calls to uwb_ie_next() - * will get the next IE. - * - * NULL is returned (and @ptr and @len will not be updated) if there - * are no more IEs in the buffer or the buffer is too short. - */ -struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len) -{ - struct uwb_ie_hdr *hdr; - size_t ie_len; - - if (*len < sizeof(struct uwb_ie_hdr)) - return NULL; - - hdr = *ptr; - ie_len = sizeof(struct uwb_ie_hdr) + hdr->length; - - if (*len < ie_len) - return NULL; - - *ptr += ie_len; - *len -= ie_len; - - return hdr; -} -EXPORT_SYMBOL_GPL(uwb_ie_next); - -/** - * Get the IEs that a radio controller is sending in its beacon - * - * @uwb_rc: UWB Radio Controller - * @returns: Size read from the system - * - * We don't need to lock the uwb_rc's mutex because we don't modify - * anything. Once done with the iedata buffer, call - * uwb_rc_ie_release(iedata). Don't call kfree on it. - */ -ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) -{ - ssize_t result; - struct device *dev = &uwb_rc->uwb_dev.dev; - struct uwb_rccb *cmd = NULL; - struct uwb_rceb *reply = NULL; - struct uwb_rc_evt_get_ie *get_ie; - - d_fnstart(3, dev, "(%p, %p)\n", uwb_rc, pget_ie); - result = -ENOMEM; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - goto error_kzalloc; - cmd->bCommandType = UWB_RC_CET_GENERAL; - cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); - result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), - UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, - &reply); - if (result < 0) - goto error_cmd; - get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); - if (result < sizeof(*get_ie)) { - dev_err(dev, "not enough data returned for decoding GET IE " - "(%zu bytes received vs %zu needed)\n", - result, sizeof(*get_ie)); - result = -EINVAL; - } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { - dev_err(dev, "not enough data returned for decoding GET IE " - "payload (%zu bytes received vs %zu needed)\n", result, - sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); - result = -EINVAL; - } else - *pget_ie = get_ie; -error_cmd: - kfree(cmd); -error_kzalloc: - d_fnend(3, dev, "(%p, %p) = %d\n", uwb_rc, pget_ie, (int)result); - return result; -} -EXPORT_SYMBOL_GPL(uwb_rc_get_ie); - - -/* - * Given a pointer to an IE, print it in ASCII/hex followed by a new line - * - * @ie_hdr: pointer to the IE header. Length is in there, and it is - * guaranteed that the ie_hdr->length bytes following it are - * safely accesible. - * - * @_data: context data passed from uwb_ie_for_each(), an struct output_ctx - */ -int uwb_ie_dump_hex(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, - size_t offset, void *_ctx) -{ - struct uwb_buf_ctx *ctx = _ctx; - const u8 *pl = (void *)(ie_hdr + 1); - u8 pl_itr; - - ctx->bytes += scnprintf(ctx->buf + ctx->bytes, ctx->size - ctx->bytes, - "%02x %02x ", (unsigned) ie_hdr->element_id, - (unsigned) ie_hdr->length); - pl_itr = 0; - while (pl_itr < ie_hdr->length && ctx->bytes < ctx->size) - ctx->bytes += scnprintf(ctx->buf + ctx->bytes, - ctx->size - ctx->bytes, - "%02x ", (unsigned) pl[pl_itr++]); - if (ctx->bytes < ctx->size) - ctx->buf[ctx->bytes++] = '\n'; - return 0; -} -EXPORT_SYMBOL_GPL(uwb_ie_dump_hex); - - -/** - * Verify that a pointer in a buffer points to valid IE - * - * @start: pointer to start of buffer in which IE appears - * @itr: pointer to IE inside buffer that will be verified - * @top: pointer to end of buffer - * - * @returns: 0 if IE is valid, <0 otherwise - * - * Verification involves checking that the buffer can contain a - * header and the amount of data reported in the IE header can be found in - * the buffer. - */ -static -int uwb_rc_ie_verify(struct uwb_dev *uwb_dev, const void *start, - const void *itr, const void *top) -{ - struct device *dev = &uwb_dev->dev; - const struct uwb_ie_hdr *ie_hdr; - - if (top - itr < sizeof(*ie_hdr)) { - dev_err(dev, "Bad IE: no data to decode header " - "(%zu bytes left vs %zu needed) at offset %zu\n", - top - itr, sizeof(*ie_hdr), itr - start); - return -EINVAL; - } - ie_hdr = itr; - itr += sizeof(*ie_hdr); - if (top - itr < ie_hdr->length) { - dev_err(dev, "Bad IE: not enough data for payload " - "(%zu bytes left vs %zu needed) at offset %zu\n", - top - itr, (size_t)ie_hdr->length, - (void *)ie_hdr - start); - return -EINVAL; - } - return 0; -} - - -/** - * Walk a buffer filled with consecutive IE's a buffer - * - * @uwb_dev: UWB device this IEs belong to (for err messages mainly) - * - * @fn: function to call with each IE; if it returns 0, we keep - * traversing the buffer. If it returns !0, we'll stop and return - * that value. - * - * @data: pointer passed to @fn - * - * @buf: buffer where the consecutive IEs are located - * - * @size: size of @buf - * - * Each IE is checked for basic correctness (there is space left for - * the header and the payload). If that test is failed, we stop - * processing. For every good IE, @fn is called. - */ -ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, - const void *buf, size_t size) -{ - ssize_t result = 0; - const struct uwb_ie_hdr *ie_hdr; - const void *itr = buf, *top = itr + size; - - while (itr < top) { - if (uwb_rc_ie_verify(uwb_dev, buf, itr, top) != 0) - break; - ie_hdr = itr; - itr += sizeof(*ie_hdr) + ie_hdr->length; - result = fn(uwb_dev, ie_hdr, itr - buf, data); - if (result != 0) - break; - } - return result; -} -EXPORT_SYMBOL_GPL(uwb_ie_for_each); - - -/** - * Replace all IEs currently being transmitted by a device - * - * @cmd: pointer to the SET-IE command with the IEs to set - * @size: size of @buf - */ -int uwb_rc_set_ie(struct uwb_rc *rc, struct uwb_rc_cmd_set_ie *cmd) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_evt_set_ie reply; - - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_SET_IE; - result = uwb_rc_cmd(rc, "SET-IE", &cmd->rccb, - sizeof(*cmd) + le16_to_cpu(cmd->wIELength), - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - else if (result != sizeof(reply)) { - dev_err(dev, "SET-IE: not enough data to decode reply " - "(%d bytes received vs %zu needed)\n", - result, sizeof(reply)); - result = -EIO; - } else if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(dev, "SET-IE: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply.bResultCode), reply.bResultCode); - result = -EIO; - } else - result = 0; -error_cmd: - return result; -} - -/** - * Determine by IE id if IE is host settable - * WUSB 1.0 [8.6.2.8 Table 8.85] - * - * EXCEPTION: - * All but UWB_IE_WLP appears in Table 8.85 from WUSB 1.0. Setting this IE - * is required for the WLP substack to perform association with its WSS so - * we hope that the WUSB spec will be changed to reflect this. - */ -static -int uwb_rc_ie_is_host_settable(enum uwb_ie element_id) -{ - if (element_id == UWB_PCA_AVAILABILITY || - element_id == UWB_BP_SWITCH_IE || - element_id == UWB_MAC_CAPABILITIES_IE || - element_id == UWB_PHY_CAPABILITIES_IE || - element_id == UWB_APP_SPEC_PROBE_IE || - element_id == UWB_IDENTIFICATION_IE || - element_id == UWB_MASTER_KEY_ID_IE || - element_id == UWB_IE_WLP || - element_id == UWB_APP_SPEC_IE) - return 1; - return 0; -} - - -/** - * Extract Host Settable IEs from IE - * - * @ie_data: pointer to buffer containing all IEs - * @size: size of buffer - * - * @returns: length of buffer that only includes host settable IEs - * - * Given a buffer of IEs we move all Host Settable IEs to front of buffer - * by overwriting the IEs that are not Host Settable. - * Buffer length is adjusted accordingly. - */ -static -ssize_t uwb_rc_parse_host_settable_ie(struct uwb_dev *uwb_dev, - void *ie_data, size_t size) -{ - size_t new_len = size; - struct uwb_ie_hdr *ie_hdr; - size_t ie_length; - void *itr = ie_data, *top = itr + size; - - while (itr < top) { - if (uwb_rc_ie_verify(uwb_dev, ie_data, itr, top) != 0) - break; - ie_hdr = itr; - ie_length = sizeof(*ie_hdr) + ie_hdr->length; - if (uwb_rc_ie_is_host_settable(ie_hdr->element_id)) { - itr += ie_length; - } else { - memmove(itr, itr + ie_length, top - (itr + ie_length)); - new_len -= ie_length; - top -= ie_length; - } - } - return new_len; -} - - -/* Cleanup the whole IE management subsystem */ -void uwb_rc_ie_init(struct uwb_rc *uwb_rc) -{ - mutex_init(&uwb_rc->ies_mutex); -} - - -/** - * Set up cache for host settable IEs currently being transmitted - * - * First we just call GET-IE to get the current IEs being transmitted - * (or we workaround and pretend we did) and (because the format is - * the same) reuse that as the IE cache (with the command prefix, as - * explained in 'struct uwb_rc'). - * - * @returns: size of cache created - */ -ssize_t uwb_rc_ie_setup(struct uwb_rc *uwb_rc) -{ - struct device *dev = &uwb_rc->uwb_dev.dev; - ssize_t result; - size_t capacity; - struct uwb_rc_evt_get_ie *ie_info; - - d_fnstart(3, dev, "(%p)\n", uwb_rc); - mutex_lock(&uwb_rc->ies_mutex); - result = uwb_rc_get_ie(uwb_rc, &ie_info); - if (result < 0) - goto error_get_ie; - capacity = result; - d_printf(5, dev, "Got IEs %zu bytes (%zu long at %p)\n", result, - (size_t)le16_to_cpu(ie_info->wIELength), ie_info); - - /* Remove IEs that host should not set. */ - result = uwb_rc_parse_host_settable_ie(&uwb_rc->uwb_dev, - ie_info->IEData, le16_to_cpu(ie_info->wIELength)); - if (result < 0) - goto error_parse; - d_printf(5, dev, "purged non-settable IEs to %zu bytes\n", result); - uwb_rc->ies = (void *) ie_info; - uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL; - uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE); - uwb_rc->ies_capacity = capacity; - d_printf(5, dev, "IE cache at %p %zu bytes, %zu capacity\n", - ie_info, result, capacity); - result = 0; -error_parse: -error_get_ie: - mutex_unlock(&uwb_rc->ies_mutex); - d_fnend(3, dev, "(%p) = %zu\n", uwb_rc, result); - return result; -} - - -/* Cleanup the whole IE management subsystem */ -void uwb_rc_ie_release(struct uwb_rc *uwb_rc) -{ - kfree(uwb_rc->ies); - uwb_rc->ies = NULL; - uwb_rc->ies_capacity = 0; -} - - -static -int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, - size_t offset, void *_ctx) -{ - size_t *acc_size = _ctx; - *acc_size += sizeof(*ie_hdr) + ie_hdr->length; - d_printf(6, &uwb_dev->dev, "new acc size %zu\n", *acc_size); - return 0; -} - - -/** - * Add a new IE to IEs currently being transmitted by device - * - * @ies: the buffer containing the new IE or IEs to be added to - * the device's beacon. The buffer will be verified for - * consistence (meaning the headers should be right) and - * consistent with the buffer size. - * @size: size of @ies (in bytes, total buffer size) - * @returns: 0 if ok, <0 errno code on error - * - * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB - * after the device sent the first beacon that includes the IEs specified - * in the SET IE command. We thus cannot send this command if the device is - * not beaconing. Instead, a SET IE command will be sent later right after - * we start beaconing. - * - * Setting an IE on the device will overwrite all current IEs in device. So - * we take the current IEs being transmitted by the device, append the - * new one, and call SET IE with all the IEs needed. - * - * The local IE cache will only be updated with the new IE if SET IE - * completed successfully. - */ -int uwb_rc_ie_add(struct uwb_rc *uwb_rc, - const struct uwb_ie_hdr *ies, size_t size) -{ - int result = 0; - struct device *dev = &uwb_rc->uwb_dev.dev; - struct uwb_rc_cmd_set_ie *new_ies; - size_t ies_size, total_size, acc_size = 0; - - if (uwb_rc->ies == NULL) - return -ESHUTDOWN; - uwb_ie_for_each(&uwb_rc->uwb_dev, __acc_size, &acc_size, ies, size); - if (acc_size != size) { - dev_err(dev, "BUG: bad IEs, misconstructed headers " - "[%zu bytes reported vs %zu calculated]\n", - size, acc_size); - WARN_ON(1); - return -EINVAL; - } - mutex_lock(&uwb_rc->ies_mutex); - ies_size = le16_to_cpu(uwb_rc->ies->wIELength); - total_size = sizeof(*uwb_rc->ies) + ies_size; - if (total_size + size > uwb_rc->ies_capacity) { - d_printf(4, dev, "Reallocating IE cache from %p capacity %zu " - "to capacity %zu\n", uwb_rc->ies, uwb_rc->ies_capacity, - total_size + size); - new_ies = kzalloc(total_size + size, GFP_KERNEL); - if (new_ies == NULL) { - dev_err(dev, "No memory for adding new IE\n"); - result = -ENOMEM; - goto error_alloc; - } - memcpy(new_ies, uwb_rc->ies, total_size); - uwb_rc->ies_capacity = total_size + size; - kfree(uwb_rc->ies); - uwb_rc->ies = new_ies; - d_printf(4, dev, "New IE cache at %p capacity %zu\n", - uwb_rc->ies, uwb_rc->ies_capacity); - } - memcpy((void *)uwb_rc->ies + total_size, ies, size); - uwb_rc->ies->wIELength = cpu_to_le16(ies_size + size); - if (uwb_rc->beaconing != -1) { - result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); - if (result < 0) { - dev_err(dev, "Cannot set new IE on device: %d\n", - result); - uwb_rc->ies->wIELength = cpu_to_le16(ies_size); - } else - result = 0; - } - d_printf(4, dev, "IEs now occupy %hu bytes of %zu capacity at %p\n", - le16_to_cpu(uwb_rc->ies->wIELength), uwb_rc->ies_capacity, - uwb_rc->ies); -error_alloc: - mutex_unlock(&uwb_rc->ies_mutex); - return result; -} -EXPORT_SYMBOL_GPL(uwb_rc_ie_add); - - -/* - * Remove an IE from internal cache - * - * We are dealing with our internal IE cache so no need to verify that the - * IEs are valid (it has been done already). - * - * Should be called with ies_mutex held - * - * We do not break out once an IE is found in the cache. It is currently - * possible to have more than one IE with the same ID included in the - * beacon. We don't reallocate, we just mark the size smaller. - */ -static -int uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) -{ - struct uwb_ie_hdr *ie_hdr; - size_t new_len = le16_to_cpu(uwb_rc->ies->wIELength); - void *itr = uwb_rc->ies->IEData; - void *top = itr + new_len; - - while (itr < top) { - ie_hdr = itr; - if (ie_hdr->element_id != to_remove) { - itr += sizeof(*ie_hdr) + ie_hdr->length; - } else { - int ie_length; - ie_length = sizeof(*ie_hdr) + ie_hdr->length; - if (top - itr != ie_length) - memmove(itr, itr + ie_length, top - itr + ie_length); - top -= ie_length; - new_len -= ie_length; - } - } - uwb_rc->ies->wIELength = cpu_to_le16(new_len); - return 0; -} - - -/** - * Remove an IE currently being transmitted by device - * - * @element_id: id of IE to be removed from device's beacon - */ -int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) -{ - struct device *dev = &uwb_rc->uwb_dev.dev; - int result; - - if (uwb_rc->ies == NULL) - return -ESHUTDOWN; - mutex_lock(&uwb_rc->ies_mutex); - result = uwb_rc_ie_cache_rm(uwb_rc, element_id); - if (result < 0) - dev_err(dev, "Cannot remove IE from cache.\n"); - if (uwb_rc->beaconing != -1) { - result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); - if (result < 0) - dev_err(dev, "Cannot set new IE on device.\n"); - } - mutex_unlock(&uwb_rc->ies_mutex); - return result; -} -EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); diff --git a/trunk/drivers/uwb/lc-dev.c b/trunk/drivers/uwb/lc-dev.c deleted file mode 100644 index 15f856c9689a..000000000000 --- a/trunk/drivers/uwb/lc-dev.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Ultra Wide Band - * Life cycle of devices - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#include -#include -#include -#include -#include "uwb-internal.h" - -#define D_LOCAL 1 -#include - - -/* We initialize addresses to 0xff (invalid, as it is bcast) */ -static inline void uwb_dev_addr_init(struct uwb_dev_addr *addr) -{ - memset(&addr->data, 0xff, sizeof(addr->data)); -} - -static inline void uwb_mac_addr_init(struct uwb_mac_addr *addr) -{ - memset(&addr->data, 0xff, sizeof(addr->data)); -} - -/* @returns !0 if a device @addr is a broadcast address */ -static inline int uwb_dev_addr_bcast(const struct uwb_dev_addr *addr) -{ - static const struct uwb_dev_addr bcast = { .data = { 0xff, 0xff } }; - return !uwb_dev_addr_cmp(addr, &bcast); -} - -/* - * Add callback @new to be called when an event occurs in @rc. - */ -int uwb_notifs_register(struct uwb_rc *rc, struct uwb_notifs_handler *new) -{ - if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) - return -ERESTARTSYS; - list_add(&new->list_node, &rc->notifs_chain.list); - mutex_unlock(&rc->notifs_chain.mutex); - return 0; -} -EXPORT_SYMBOL_GPL(uwb_notifs_register); - -/* - * Remove event handler (callback) - */ -int uwb_notifs_deregister(struct uwb_rc *rc, struct uwb_notifs_handler *entry) -{ - if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) - return -ERESTARTSYS; - list_del(&entry->list_node); - mutex_unlock(&rc->notifs_chain.mutex); - return 0; -} -EXPORT_SYMBOL_GPL(uwb_notifs_deregister); - -/* - * Notify all event handlers of a given event on @rc - * - * We are called with a valid reference to the device, or NULL if the - * event is not for a particular event (e.g., a BG join event). - */ -void uwb_notify(struct uwb_rc *rc, struct uwb_dev *uwb_dev, enum uwb_notifs event) -{ - struct uwb_notifs_handler *handler; - if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) - return; - if (!list_empty(&rc->notifs_chain.list)) { - list_for_each_entry(handler, &rc->notifs_chain.list, list_node) { - handler->cb(handler->data, uwb_dev, event); - } - } - mutex_unlock(&rc->notifs_chain.mutex); -} - -/* - * Release the backing device of a uwb_dev that has been dynamically allocated. - */ -static void uwb_dev_sys_release(struct device *dev) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - - d_fnstart(4, NULL, "(dev %p uwb_dev %p)\n", dev, uwb_dev); - uwb_bce_put(uwb_dev->bce); - d_printf(0, &uwb_dev->dev, "uwb_dev %p freed\n", uwb_dev); - memset(uwb_dev, 0x69, sizeof(*uwb_dev)); - kfree(uwb_dev); - d_fnend(4, NULL, "(dev %p uwb_dev %p) = void\n", dev, uwb_dev); -} - -/* - * Initialize a UWB device instance - * - * Alloc, zero and call this function. - */ -void uwb_dev_init(struct uwb_dev *uwb_dev) -{ - mutex_init(&uwb_dev->mutex); - device_initialize(&uwb_dev->dev); - uwb_dev->dev.release = uwb_dev_sys_release; - uwb_dev_addr_init(&uwb_dev->dev_addr); - uwb_mac_addr_init(&uwb_dev->mac_addr); - bitmap_fill(uwb_dev->streams, UWB_NUM_GLOBAL_STREAMS); -} - -static ssize_t uwb_dev_EUI_48_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - char addr[UWB_ADDR_STRSIZE]; - - uwb_mac_addr_print(addr, sizeof(addr), &uwb_dev->mac_addr); - return sprintf(buf, "%s\n", addr); -} -static DEVICE_ATTR(EUI_48, S_IRUGO, uwb_dev_EUI_48_show, NULL); - -static ssize_t uwb_dev_DevAddr_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - char addr[UWB_ADDR_STRSIZE]; - - uwb_dev_addr_print(addr, sizeof(addr), &uwb_dev->dev_addr); - return sprintf(buf, "%s\n", addr); -} -static DEVICE_ATTR(DevAddr, S_IRUGO, uwb_dev_DevAddr_show, NULL); - -/* - * Show the BPST of this device. - * - * Calculated from the receive time of the device's beacon and it's - * slot number. - */ -static ssize_t uwb_dev_BPST_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_beca_e *bce; - struct uwb_beacon_frame *bf; - u16 bpst; - - bce = uwb_dev->bce; - mutex_lock(&bce->mutex); - bf = (struct uwb_beacon_frame *)bce->be->BeaconInfo; - bpst = bce->be->wBPSTOffset - - (u16)(bf->Beacon_Slot_Number * UWB_BEACON_SLOT_LENGTH_US); - mutex_unlock(&bce->mutex); - - return sprintf(buf, "%d\n", bpst); -} -static DEVICE_ATTR(BPST, S_IRUGO, uwb_dev_BPST_show, NULL); - -/* - * Show the IEs a device is beaconing - * - * We need to access the beacon cache, so we just lock it really - * quick, print the IEs and unlock. - * - * We have a reference on the cache entry, so that should be - * quite safe. - */ -static ssize_t uwb_dev_IEs_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - - return uwb_bce_print_IEs(uwb_dev, uwb_dev->bce, buf, PAGE_SIZE); -} -static DEVICE_ATTR(IEs, S_IRUGO | S_IWUSR, uwb_dev_IEs_show, NULL); - -static ssize_t uwb_dev_LQE_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_beca_e *bce = uwb_dev->bce; - size_t result; - - mutex_lock(&bce->mutex); - result = stats_show(&uwb_dev->bce->lqe_stats, buf); - mutex_unlock(&bce->mutex); - return result; -} - -static ssize_t uwb_dev_LQE_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_beca_e *bce = uwb_dev->bce; - ssize_t result; - - mutex_lock(&bce->mutex); - result = stats_store(&uwb_dev->bce->lqe_stats, buf, size); - mutex_unlock(&bce->mutex); - return result; -} -static DEVICE_ATTR(LQE, S_IRUGO | S_IWUSR, uwb_dev_LQE_show, uwb_dev_LQE_store); - -static ssize_t uwb_dev_RSSI_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_beca_e *bce = uwb_dev->bce; - size_t result; - - mutex_lock(&bce->mutex); - result = stats_show(&uwb_dev->bce->rssi_stats, buf); - mutex_unlock(&bce->mutex); - return result; -} - -static ssize_t uwb_dev_RSSI_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_beca_e *bce = uwb_dev->bce; - ssize_t result; - - mutex_lock(&bce->mutex); - result = stats_store(&uwb_dev->bce->rssi_stats, buf, size); - mutex_unlock(&bce->mutex); - return result; -} -static DEVICE_ATTR(RSSI, S_IRUGO | S_IWUSR, uwb_dev_RSSI_show, uwb_dev_RSSI_store); - - -static struct attribute *dev_attrs[] = { - &dev_attr_EUI_48.attr, - &dev_attr_DevAddr.attr, - &dev_attr_BPST.attr, - &dev_attr_IEs.attr, - &dev_attr_LQE.attr, - &dev_attr_RSSI.attr, - NULL, -}; - -static struct attribute_group dev_attr_group = { - .attrs = dev_attrs, -}; - -static struct attribute_group *groups[] = { - &dev_attr_group, - NULL, -}; - -/** - * Device SYSFS registration - * - * - */ -static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) -{ - int result; - struct device *dev; - - d_fnstart(4, NULL, "(uwb_dev %p parent_dev %p)\n", uwb_dev, parent_dev); - BUG_ON(parent_dev == NULL); - - dev = &uwb_dev->dev; - /* Device sysfs files are only useful for neighbor devices not - local radio controllers. */ - if (&uwb_dev->rc->uwb_dev != uwb_dev) - dev->groups = groups; - dev->parent = parent_dev; - dev_set_drvdata(dev, uwb_dev); - - result = device_add(dev); - d_fnend(4, NULL, "(uwb_dev %p parent_dev %p) = %d\n", uwb_dev, parent_dev, result); - return result; -} - - -static void __uwb_dev_sys_rm(struct uwb_dev *uwb_dev) -{ - d_fnstart(4, NULL, "(uwb_dev %p)\n", uwb_dev); - dev_set_drvdata(&uwb_dev->dev, NULL); - device_del(&uwb_dev->dev); - d_fnend(4, NULL, "(uwb_dev %p) = void\n", uwb_dev); -} - - -/** - * Register and initialize a new UWB device - * - * Did you call uwb_dev_init() on it? - * - * @parent_rc: is the parent radio controller who has the link to the - * device. When registering the UWB device that is a UWB - * Radio Controller, we point back to it. - * - * If registering the device that is part of a radio, caller has set - * rc->uwb_dev->dev. Otherwise it is to be left NULL--a new one will - * be allocated. - */ -int uwb_dev_add(struct uwb_dev *uwb_dev, struct device *parent_dev, - struct uwb_rc *parent_rc) -{ - int result; - struct device *dev; - - BUG_ON(uwb_dev == NULL); - BUG_ON(parent_dev == NULL); - BUG_ON(parent_rc == NULL); - - mutex_lock(&uwb_dev->mutex); - dev = &uwb_dev->dev; - uwb_dev->rc = parent_rc; - result = __uwb_dev_sys_add(uwb_dev, parent_dev); - if (result < 0) - printk(KERN_ERR "UWB: unable to register dev %s with sysfs: %d\n", - dev_name(dev), result); - mutex_unlock(&uwb_dev->mutex); - return result; -} - - -void uwb_dev_rm(struct uwb_dev *uwb_dev) -{ - mutex_lock(&uwb_dev->mutex); - __uwb_dev_sys_rm(uwb_dev); - mutex_unlock(&uwb_dev->mutex); -} - - -static -int __uwb_dev_try_get(struct device *dev, void *__target_uwb_dev) -{ - struct uwb_dev *target_uwb_dev = __target_uwb_dev; - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - if (uwb_dev == target_uwb_dev) { - uwb_dev_get(uwb_dev); - return 1; - } else - return 0; -} - - -/** - * Given a UWB device descriptor, validate and refcount it - * - * @returns NULL if the device does not exist or is quiescing; the ptr to - * it otherwise. - */ -struct uwb_dev *uwb_dev_try_get(struct uwb_rc *rc, struct uwb_dev *uwb_dev) -{ - if (uwb_dev_for_each(rc, __uwb_dev_try_get, uwb_dev)) - return uwb_dev; - else - return NULL; -} -EXPORT_SYMBOL_GPL(uwb_dev_try_get); - - -/** - * Remove a device from the system [grunt for other functions] - */ -int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) -{ - struct device *dev = &uwb_dev->dev; - char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; - - d_fnstart(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p)\n", dev, uwb_dev, rc); - uwb_mac_addr_print(macbuf, sizeof(macbuf), &uwb_dev->mac_addr); - uwb_dev_addr_print(devbuf, sizeof(devbuf), &uwb_dev->dev_addr); - dev_info(dev, "uwb device (mac %s dev %s) disconnected from %s %s\n", - macbuf, devbuf, - rc ? rc->uwb_dev.dev.parent->bus->name : "n/a", - rc ? dev_name(rc->uwb_dev.dev.parent) : ""); - uwb_dev_rm(uwb_dev); - uwb_dev_put(uwb_dev); /* for the creation in _onair() */ - d_fnend(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p) = 0\n", dev, uwb_dev, rc); - return 0; -} - - -/** - * A device went off the air, clean up after it! - * - * This is called by the UWB Daemon (through the beacon purge function - * uwb_bcn_cache_purge) when it is detected that a device has been in - * radio silence for a while. - * - * If this device is actually a local radio controller we don't need - * to go through the offair process, as it is not registered as that. - * - * NOTE: uwb_bcn_cache.mutex is held! - */ -void uwbd_dev_offair(struct uwb_beca_e *bce) -{ - struct uwb_dev *uwb_dev; - - uwb_dev = bce->uwb_dev; - if (uwb_dev) { - uwb_notify(uwb_dev->rc, uwb_dev, UWB_NOTIF_OFFAIR); - __uwb_dev_offair(uwb_dev, uwb_dev->rc); - } -} - - -/** - * A device went on the air, start it up! - * - * This is called by the UWB Daemon when it is detected that a device - * has popped up in the radio range of the radio controller. - * - * It will just create the freaking device, register the beacon and - * stuff and yatla, done. - * - * - * NOTE: uwb_beca.mutex is held, bce->mutex is held - */ -void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_dev *uwb_dev; - char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; - - uwb_mac_addr_print(macbuf, sizeof(macbuf), bce->mac_addr); - uwb_dev_addr_print(devbuf, sizeof(devbuf), &bce->dev_addr); - uwb_dev = kzalloc(sizeof(struct uwb_dev), GFP_KERNEL); - if (uwb_dev == NULL) { - dev_err(dev, "new device %s: Cannot allocate memory\n", - macbuf); - return; - } - uwb_dev_init(uwb_dev); /* This sets refcnt to one, we own it */ - uwb_dev->mac_addr = *bce->mac_addr; - uwb_dev->dev_addr = bce->dev_addr; - dev_set_name(&uwb_dev->dev, macbuf); - result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); - if (result < 0) { - dev_err(dev, "new device %s: cannot instantiate device\n", - macbuf); - goto error_dev_add; - } - /* plug the beacon cache */ - bce->uwb_dev = uwb_dev; - uwb_dev->bce = bce; - uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ - dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", - macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, - dev_name(rc->uwb_dev.dev.parent)); - uwb_notify(rc, uwb_dev, UWB_NOTIF_ONAIR); - return; - -error_dev_add: - kfree(uwb_dev); - return; -} - -/** - * Iterate over the list of UWB devices, calling a @function on each - * - * See docs for bus_for_each().... - * - * @rc: radio controller for the devices. - * @function: function to call. - * @priv: data to pass to @function. - * @returns: 0 if no invocation of function() returned a value - * different to zero. That value otherwise. - */ -int uwb_dev_for_each(struct uwb_rc *rc, uwb_dev_for_each_f function, void *priv) -{ - return device_for_each_child(&rc->uwb_dev.dev, priv, function); -} -EXPORT_SYMBOL_GPL(uwb_dev_for_each); diff --git a/trunk/drivers/uwb/lc-rc.c b/trunk/drivers/uwb/lc-rc.c deleted file mode 100644 index ee5772f00d42..000000000000 --- a/trunk/drivers/uwb/lc-rc.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Ultra Wide Band - * Life cycle of radio controllers - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * A UWB radio controller is also a UWB device, so it embeds one... - * - * List of RCs comes from the 'struct class uwb_rc_class'. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define D_LOCAL 1 -#include -#include "uwb-internal.h" - -static int uwb_rc_index_match(struct device *dev, void *data) -{ - int *index = data; - struct uwb_rc *rc = dev_get_drvdata(dev); - - if (rc->index == *index) - return 1; - return 0; -} - -static struct uwb_rc *uwb_rc_find_by_index(int index) -{ - struct device *dev; - struct uwb_rc *rc = NULL; - - dev = class_find_device(&uwb_rc_class, NULL, &index, uwb_rc_index_match); - if (dev) - rc = dev_get_drvdata(dev); - return rc; -} - -static int uwb_rc_new_index(void) -{ - int index = 0; - - for (;;) { - if (!uwb_rc_find_by_index(index)) - return index; - if (++index < 0) - index = 0; - } -} - -/** - * Release the backing device of a uwb_rc that has been dynamically allocated. - */ -static void uwb_rc_sys_release(struct device *dev) -{ - struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); - struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); - - uwb_rc_neh_destroy(rc); - uwb_rc_ie_release(rc); - d_printf(1, dev, "freed uwb_rc %p\n", rc); - kfree(rc); -} - - -void uwb_rc_init(struct uwb_rc *rc) -{ - struct uwb_dev *uwb_dev = &rc->uwb_dev; - - uwb_dev_init(uwb_dev); - rc->uwb_dev.dev.class = &uwb_rc_class; - rc->uwb_dev.dev.release = uwb_rc_sys_release; - uwb_rc_neh_create(rc); - rc->beaconing = -1; - rc->scan_type = UWB_SCAN_DISABLED; - INIT_LIST_HEAD(&rc->notifs_chain.list); - mutex_init(&rc->notifs_chain.mutex); - uwb_drp_avail_init(rc); - uwb_rc_ie_init(rc); - uwb_rsv_init(rc); - uwb_rc_pal_init(rc); -} -EXPORT_SYMBOL_GPL(uwb_rc_init); - - -struct uwb_rc *uwb_rc_alloc(void) -{ - struct uwb_rc *rc; - rc = kzalloc(sizeof(*rc), GFP_KERNEL); - if (rc == NULL) - return NULL; - uwb_rc_init(rc); - return rc; -} -EXPORT_SYMBOL_GPL(uwb_rc_alloc); - -static struct attribute *rc_attrs[] = { - &dev_attr_mac_address.attr, - &dev_attr_scan.attr, - &dev_attr_beacon.attr, - NULL, -}; - -static struct attribute_group rc_attr_group = { - .attrs = rc_attrs, -}; - -/* - * Registration of sysfs specific stuff - */ -static int uwb_rc_sys_add(struct uwb_rc *rc) -{ - return sysfs_create_group(&rc->uwb_dev.dev.kobj, &rc_attr_group); -} - - -static void __uwb_rc_sys_rm(struct uwb_rc *rc) -{ - sysfs_remove_group(&rc->uwb_dev.dev.kobj, &rc_attr_group); -} - -/** - * uwb_rc_mac_addr_setup - get an RC's EUI-48 address or set it - * @rc: the radio controller. - * - * If the EUI-48 address is 00:00:00:00:00:00 or FF:FF:FF:FF:FF:FF - * then a random locally administered EUI-48 is generated and set on - * the device. The probability of address collisions is sufficiently - * unlikely (1/2^40 = 9.1e-13) that they're not checked for. - */ -static -int uwb_rc_mac_addr_setup(struct uwb_rc *rc) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_dev *uwb_dev = &rc->uwb_dev; - char devname[UWB_ADDR_STRSIZE]; - struct uwb_mac_addr addr; - - result = uwb_rc_mac_addr_get(rc, &addr); - if (result < 0) { - dev_err(dev, "cannot retrieve UWB EUI-48 address: %d\n", result); - return result; - } - - if (uwb_mac_addr_unset(&addr) || uwb_mac_addr_bcast(&addr)) { - addr.data[0] = 0x02; /* locally adminstered and unicast */ - get_random_bytes(&addr.data[1], sizeof(addr.data)-1); - - result = uwb_rc_mac_addr_set(rc, &addr); - if (result < 0) { - uwb_mac_addr_print(devname, sizeof(devname), &addr); - dev_err(dev, "cannot set EUI-48 address %s: %d\n", - devname, result); - return result; - } - } - uwb_dev->mac_addr = addr; - return 0; -} - - - -static int uwb_rc_setup(struct uwb_rc *rc) -{ - int result; - struct device *dev = &rc->uwb_dev.dev; - - result = uwb_rc_reset(rc); - if (result < 0) { - dev_err(dev, "cannot reset UWB radio: %d\n", result); - goto error; - } - result = uwb_rc_mac_addr_setup(rc); - if (result < 0) { - dev_err(dev, "cannot setup UWB MAC address: %d\n", result); - goto error; - } - result = uwb_rc_dev_addr_assign(rc); - if (result < 0) { - dev_err(dev, "cannot assign UWB DevAddr: %d\n", result); - goto error; - } - result = uwb_rc_ie_setup(rc); - if (result < 0) { - dev_err(dev, "cannot setup IE subsystem: %d\n", result); - goto error_ie_setup; - } - result = uwb_rsv_setup(rc); - if (result < 0) { - dev_err(dev, "cannot setup reservation subsystem: %d\n", result); - goto error_rsv_setup; - } - uwb_dbg_add_rc(rc); - return 0; - -error_rsv_setup: - uwb_rc_ie_release(rc); -error_ie_setup: -error: - return result; -} - - -/** - * Register a new UWB radio controller - * - * Did you call uwb_rc_init() on your rc? - * - * We assume that this is being called with a > 0 refcount on - * it [through ops->{get|put}_device(). We'll take our own, though. - * - * @parent_dev is our real device, the one that provides the actual UWB device - */ -int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) -{ - int result; - struct device *dev; - char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; - - rc->index = uwb_rc_new_index(); - - dev = &rc->uwb_dev.dev; - dev_set_name(dev, "uwb%d", rc->index); - - rc->priv = priv; - - result = rc->start(rc); - if (result < 0) - goto error_rc_start; - - result = uwb_rc_setup(rc); - if (result < 0) { - dev_err(dev, "cannot setup UWB radio controller: %d\n", result); - goto error_rc_setup; - } - - result = uwb_dev_add(&rc->uwb_dev, parent_dev, rc); - if (result < 0 && result != -EADDRNOTAVAIL) - goto error_dev_add; - - result = uwb_rc_sys_add(rc); - if (result < 0) { - dev_err(parent_dev, "cannot register UWB radio controller " - "dev attributes: %d\n", result); - goto error_sys_add; - } - - uwb_mac_addr_print(macbuf, sizeof(macbuf), &rc->uwb_dev.mac_addr); - uwb_dev_addr_print(devbuf, sizeof(devbuf), &rc->uwb_dev.dev_addr); - dev_info(dev, - "new uwb radio controller (mac %s dev %s) on %s %s\n", - macbuf, devbuf, parent_dev->bus->name, dev_name(parent_dev)); - rc->ready = 1; - return 0; - -error_sys_add: - uwb_dev_rm(&rc->uwb_dev); -error_dev_add: -error_rc_setup: - rc->stop(rc); - uwbd_flush(rc); -error_rc_start: - return result; -} -EXPORT_SYMBOL_GPL(uwb_rc_add); - - -static int uwb_dev_offair_helper(struct device *dev, void *priv) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - - return __uwb_dev_offair(uwb_dev, uwb_dev->rc); -} - -/* - * Remove a Radio Controller; stop beaconing/scanning, disconnect all children - */ -void uwb_rc_rm(struct uwb_rc *rc) -{ - rc->ready = 0; - - uwb_dbg_del_rc(rc); - uwb_rsv_cleanup(rc); - uwb_rc_ie_rm(rc, UWB_IDENTIFICATION_IE); - if (rc->beaconing >= 0) - uwb_rc_beacon(rc, -1, 0); - if (rc->scan_type != UWB_SCAN_DISABLED) - uwb_rc_scan(rc, rc->scanning, UWB_SCAN_DISABLED, 0); - uwb_rc_reset(rc); - - rc->stop(rc); - uwbd_flush(rc); - - uwb_dev_lock(&rc->uwb_dev); - rc->priv = NULL; - rc->cmd = NULL; - uwb_dev_unlock(&rc->uwb_dev); - mutex_lock(&uwb_beca.mutex); - uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); - __uwb_rc_sys_rm(rc); - mutex_unlock(&uwb_beca.mutex); - uwb_dev_rm(&rc->uwb_dev); -} -EXPORT_SYMBOL_GPL(uwb_rc_rm); - -static int find_rc_try_get(struct device *dev, void *data) -{ - struct uwb_rc *target_rc = data; - struct uwb_rc *rc = dev_get_drvdata(dev); - - if (rc == NULL) { - WARN_ON(1); - return 0; - } - if (rc == target_rc) { - if (rc->ready == 0) - return 0; - else - return 1; - } - return 0; -} - -/** - * Given a radio controller descriptor, validate and refcount it - * - * @returns NULL if the rc does not exist or is quiescing; the ptr to - * it otherwise. - */ -struct uwb_rc *__uwb_rc_try_get(struct uwb_rc *target_rc) -{ - struct device *dev; - struct uwb_rc *rc = NULL; - - dev = class_find_device(&uwb_rc_class, NULL, target_rc, - find_rc_try_get); - if (dev) { - rc = dev_get_drvdata(dev); - __uwb_rc_get(rc); - } - return rc; -} -EXPORT_SYMBOL_GPL(__uwb_rc_try_get); - -/* - * RC get for external refcount acquirers... - * - * Increments the refcount of the device and it's backend modules - */ -static inline struct uwb_rc *uwb_rc_get(struct uwb_rc *rc) -{ - if (rc->ready == 0) - return NULL; - uwb_dev_get(&rc->uwb_dev); - return rc; -} - -static int find_rc_grandpa(struct device *dev, void *data) -{ - struct device *grandpa_dev = data; - struct uwb_rc *rc = dev_get_drvdata(dev); - - if (rc->uwb_dev.dev.parent->parent == grandpa_dev) { - rc = uwb_rc_get(rc); - return 1; - } - return 0; -} - -/** - * Locate and refcount a radio controller given a common grand-parent - * - * @grandpa_dev Pointer to the 'grandparent' device structure. - * @returns NULL If the rc does not exist or is quiescing; the ptr to - * it otherwise, properly referenced. - * - * The Radio Control interface (or the UWB Radio Controller) is always - * an interface of a device. The parent is the interface, the - * grandparent is the device that encapsulates the interface. - * - * There is no need to lock around as the "grandpa" would be - * refcounted by the target, and to remove the referemes, the - * uwb_rc_class->sem would have to be taken--we hold it, ergo we - * should be safe. - */ -struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *grandpa_dev) -{ - struct device *dev; - struct uwb_rc *rc = NULL; - - dev = class_find_device(&uwb_rc_class, NULL, (void *)grandpa_dev, - find_rc_grandpa); - if (dev) - rc = dev_get_drvdata(dev); - return rc; -} -EXPORT_SYMBOL_GPL(uwb_rc_get_by_grandpa); - -/** - * Find a radio controller by device address - * - * @returns the pointer to the radio controller, properly referenced - */ -static int find_rc_dev(struct device *dev, void *data) -{ - struct uwb_dev_addr *addr = data; - struct uwb_rc *rc = dev_get_drvdata(dev); - - if (rc == NULL) { - WARN_ON(1); - return 0; - } - if (!uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, addr)) { - rc = uwb_rc_get(rc); - return 1; - } - return 0; -} - -struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *addr) -{ - struct device *dev; - struct uwb_rc *rc = NULL; - - dev = class_find_device(&uwb_rc_class, NULL, (void *)addr, - find_rc_dev); - if (dev) - rc = dev_get_drvdata(dev); - - return rc; -} -EXPORT_SYMBOL_GPL(uwb_rc_get_by_dev); - -/** - * Drop a reference on a radio controller - * - * This is the version that should be done by entities external to the - * UWB Radio Control stack (ie: clients of the API). - */ -void uwb_rc_put(struct uwb_rc *rc) -{ - __uwb_rc_put(rc); -} -EXPORT_SYMBOL_GPL(uwb_rc_put); - -/* - * - * - */ -ssize_t uwb_rc_print_IEs(struct uwb_rc *uwb_rc, char *buf, size_t size) -{ - ssize_t result; - struct uwb_rc_evt_get_ie *ie_info; - struct uwb_buf_ctx ctx; - - result = uwb_rc_get_ie(uwb_rc, &ie_info); - if (result < 0) - goto error_get_ie; - ctx.buf = buf; - ctx.size = size; - ctx.bytes = 0; - uwb_ie_for_each(&uwb_rc->uwb_dev, uwb_ie_dump_hex, &ctx, - ie_info->IEData, result - sizeof(*ie_info)); - result = ctx.bytes; - kfree(ie_info); -error_get_ie: - return result; -} - diff --git a/trunk/drivers/uwb/neh.c b/trunk/drivers/uwb/neh.c deleted file mode 100644 index 9b4eb64327ac..000000000000 --- a/trunk/drivers/uwb/neh.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * WUSB Wire Adapter: Radio Control Interface (WUSB[8]) - * Notification and Event Handling - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * The RC interface of the Host Wire Adapter (USB dongle) or WHCI PCI - * card delivers a stream of notifications and events to the - * notification end event endpoint or area. This code takes care of - * getting a buffer with that data, breaking it up in separate - * notifications and events and then deliver those. - * - * Events are answers to commands and they carry a context ID that - * associates them to the command. Notifications are that, - * notifications, they come out of the blue and have a context ID of - * zero. Think of the context ID kind of like a handler. The - * uwb_rc_neh_* code deals with managing context IDs. - * - * This is why you require a handle to operate on a UWB host. When you - * open a handle a context ID is assigned to you. - * - * So, as it is done is: - * - * 1. Add an event handler [uwb_rc_neh_add()] (assigns a ctx id) - * 2. Issue command [rc->cmd(rc, ...)] - * 3. Arm the timeout timer [uwb_rc_neh_arm()] - * 4, Release the reference to the neh [uwb_rc_neh_put()] - * 5. Wait for the callback - * 6. Command result (RCEB) is passed to the callback - * - * If (2) fails, you should remove the handle [uwb_rc_neh_rm()] - * instead of arming the timer. - * - * Handles are for using in *serialized* code, single thread. - * - * When the notification/event comes, the IRQ handler/endpoint - * callback passes the data read to uwb_rc_neh_grok() which will break - * it up in a discrete series of events, look up who is listening for - * them and execute the pertinent callbacks. - * - * If the reader detects an error while reading the data stream, call - * uwb_rc_neh_error(). - * - * CONSTRAINTS/ASSUMPTIONS: - * - * - Most notifications/events are small (less thank .5k), copying - * around is ok. - * - * - Notifications/events are ALWAYS smaller than PAGE_SIZE - * - * - Notifications/events always come in a single piece (ie: a buffer - * will always contain entire notifications/events). - * - * - we cannot know in advance how long each event is (because they - * lack a length field in their header--smart move by the standards - * body, btw). So we need a facility to get the event size given the - * header. This is what the EST code does (notif/Event Size - * Tables), check nest.c--as well, you can associate the size to - * the handle [w/ neh->extra_size()]. - * - * - Most notifications/events are fixed size; only a few are variable - * size (NEST takes care of that). - * - * - Listeners of events expect them, so they usually provide a - * buffer, as they know the size. Listeners to notifications don't, - * so we allocate their buffers dynamically. - */ -#include -#include -#include - -#include "uwb-internal.h" -#define D_LOCAL 0 -#include - -/* - * UWB Radio Controller Notification/Event Handle - * - * Represents an entity waiting for an event coming from the UWB Radio - * Controller with a given context id (context) and type (evt_type and - * evt). On reception of the notification/event, the callback (cb) is - * called with the event. - * - * If the timer expires before the event is received, the callback is - * called with -ETIMEDOUT as the event size. - */ -struct uwb_rc_neh { - struct kref kref; - - struct uwb_rc *rc; - u8 evt_type; - __le16 evt; - u8 context; - uwb_rc_cmd_cb_f cb; - void *arg; - - struct timer_list timer; - struct list_head list_node; -}; - -static void uwb_rc_neh_timer(unsigned long arg); - -static void uwb_rc_neh_release(struct kref *kref) -{ - struct uwb_rc_neh *neh = container_of(kref, struct uwb_rc_neh, kref); - - kfree(neh); -} - -static void uwb_rc_neh_get(struct uwb_rc_neh *neh) -{ - kref_get(&neh->kref); -} - -/** - * uwb_rc_neh_put - release reference to a neh - * @neh: the neh - */ -void uwb_rc_neh_put(struct uwb_rc_neh *neh) -{ - kref_put(&neh->kref, uwb_rc_neh_release); -} - - -/** - * Assigns @neh a context id from @rc's pool - * - * @rc: UWB Radio Controller descriptor; @rc->neh_lock taken - * @neh: Notification/Event Handle - * @returns 0 if context id was assigned ok; < 0 errno on error (if - * all the context IDs are taken). - * - * (assumes @wa is locked). - * - * NOTE: WUSB spec reserves context ids 0x00 for notifications and - * 0xff is invalid, so they must not be used. Initialization - * fills up those two in the bitmap so they are not allocated. - * - * We spread the allocation around to reduce the posiblity of two - * consecutive opened @neh's getting the same context ID assigned (to - * avoid surprises with late events that timed out long time ago). So - * first we search from where @rc->ctx_roll is, if not found, we - * search from zero. - */ -static -int __uwb_rc_ctx_get(struct uwb_rc *rc, struct uwb_rc_neh *neh) -{ - int result; - result = find_next_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX, - rc->ctx_roll++); - if (result < UWB_RC_CTX_MAX) - goto found; - result = find_first_zero_bit(rc->ctx_bm, UWB_RC_CTX_MAX); - if (result < UWB_RC_CTX_MAX) - goto found; - return -ENFILE; -found: - set_bit(result, rc->ctx_bm); - neh->context = result; - return 0; -} - - -/** Releases @neh's context ID back to @rc (@rc->neh_lock is locked). */ -static -void __uwb_rc_ctx_put(struct uwb_rc *rc, struct uwb_rc_neh *neh) -{ - struct device *dev = &rc->uwb_dev.dev; - if (neh->context == 0) - return; - if (test_bit(neh->context, rc->ctx_bm) == 0) { - dev_err(dev, "context %u not set in bitmap\n", - neh->context); - WARN_ON(1); - } - clear_bit(neh->context, rc->ctx_bm); - neh->context = 0; -} - -/** - * uwb_rc_neh_add - add a neh for a radio controller command - * @rc: the radio controller - * @cmd: the radio controller command - * @expected_type: the type of the expected response event - * @expected_event: the expected event ID - * @cb: callback for when the event is received - * @arg: argument for the callback - * - * Creates a neh and adds it to the list of those waiting for an - * event. A context ID will be assigned to the command. - */ -struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd, - u8 expected_type, u16 expected_event, - uwb_rc_cmd_cb_f cb, void *arg) -{ - int result; - unsigned long flags; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_neh *neh; - - neh = kzalloc(sizeof(*neh), GFP_KERNEL); - if (neh == NULL) { - result = -ENOMEM; - goto error_kzalloc; - } - - kref_init(&neh->kref); - INIT_LIST_HEAD(&neh->list_node); - init_timer(&neh->timer); - neh->timer.function = uwb_rc_neh_timer; - neh->timer.data = (unsigned long)neh; - - neh->rc = rc; - neh->evt_type = expected_type; - neh->evt = cpu_to_le16(expected_event); - neh->cb = cb; - neh->arg = arg; - - spin_lock_irqsave(&rc->neh_lock, flags); - result = __uwb_rc_ctx_get(rc, neh); - if (result >= 0) { - cmd->bCommandContext = neh->context; - list_add_tail(&neh->list_node, &rc->neh_list); - uwb_rc_neh_get(neh); - } - spin_unlock_irqrestore(&rc->neh_lock, flags); - if (result < 0) - goto error_ctx_get; - - return neh; - -error_ctx_get: - kfree(neh); -error_kzalloc: - dev_err(dev, "cannot open handle to radio controller: %d\n", result); - return ERR_PTR(result); -} - -static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) -{ - del_timer(&neh->timer); - __uwb_rc_ctx_put(rc, neh); - list_del(&neh->list_node); -} - -/** - * uwb_rc_neh_rm - remove a neh. - * @rc: the radio controller - * @neh: the neh to remove - * - * Remove an active neh immediately instead of waiting for the event - * (or a time out). - */ -void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) -{ - unsigned long flags; - - spin_lock_irqsave(&rc->neh_lock, flags); - __uwb_rc_neh_rm(rc, neh); - spin_unlock_irqrestore(&rc->neh_lock, flags); - - uwb_rc_neh_put(neh); -} - -/** - * uwb_rc_neh_arm - arm an event handler timeout timer - * - * @rc: UWB Radio Controller - * @neh: Notification/event handler for @rc - * - * The timer is only armed if the neh is active. - */ -void uwb_rc_neh_arm(struct uwb_rc *rc, struct uwb_rc_neh *neh) -{ - unsigned long flags; - - spin_lock_irqsave(&rc->neh_lock, flags); - if (neh->context) - mod_timer(&neh->timer, - jiffies + msecs_to_jiffies(UWB_RC_CMD_TIMEOUT_MS)); - spin_unlock_irqrestore(&rc->neh_lock, flags); -} - -static void uwb_rc_neh_cb(struct uwb_rc_neh *neh, struct uwb_rceb *rceb, size_t size) -{ - (*neh->cb)(neh->rc, neh->arg, rceb, size); - uwb_rc_neh_put(neh); -} - -static bool uwb_rc_neh_match(struct uwb_rc_neh *neh, const struct uwb_rceb *rceb) -{ - return neh->evt_type == rceb->bEventType - && neh->evt == rceb->wEvent - && neh->context == rceb->bEventContext; -} - -/** - * Find the handle waiting for a RC Radio Control Event - * - * @rc: UWB Radio Controller - * @rceb: Pointer to the RCEB buffer - * @event_size: Pointer to the size of the RCEB buffer. Might be - * adjusted to take into account the @neh->extra_size - * settings. - * - * If the listener has no buffer (NULL buffer), one is allocated for - * the right size (the amount of data received). @neh->ptr will point - * to the event payload, which always starts with a 'struct - * uwb_rceb'. kfree() it when done. - */ -static -struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc, - const struct uwb_rceb *rceb) -{ - struct uwb_rc_neh *neh = NULL, *h; - unsigned long flags; - - spin_lock_irqsave(&rc->neh_lock, flags); - - list_for_each_entry(h, &rc->neh_list, list_node) { - if (uwb_rc_neh_match(h, rceb)) { - neh = h; - break; - } - } - - if (neh) - __uwb_rc_neh_rm(rc, neh); - - spin_unlock_irqrestore(&rc->neh_lock, flags); - - return neh; -} - - -/** - * Process notifications coming from the radio control interface - * - * @rc: UWB Radio Control Interface descriptor - * @neh: Notification/Event Handler @neh->ptr points to - * @uwb_evt->buffer. - * - * This function is called by the event/notif handling subsystem when - * notifications arrive (hwarc_probe() arms a notification/event handle - * that calls back this function for every received notification; this - * function then will rearm itself). - * - * Notification data buffers are dynamically allocated by the NEH - * handling code in neh.c [uwb_rc_neh_lookup()]. What is actually - * allocated is space to contain the notification data. - * - * Buffers are prefixed with a Radio Control Event Block (RCEB) as - * defined by the WUSB Wired-Adapter Radio Control interface. We - * just use it for the notification code. - * - * On each case statement we just transcode endianess of the different - * fields. We declare a pointer to a RCI definition of an event, and - * then to a UWB definition of the same event (which are the same, - * remember). Event if we use different pointers - */ -static -void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size) -{ - struct device *dev = &rc->uwb_dev.dev; - struct uwb_event *uwb_evt; - - if (size == -ESHUTDOWN) - return; - if (size < 0) { - dev_err(dev, "ignoring event with error code %zu\n", - size); - return; - } - - uwb_evt = kzalloc(sizeof(*uwb_evt), GFP_ATOMIC); - if (unlikely(uwb_evt == NULL)) { - dev_err(dev, "no memory to queue event 0x%02x/%04x/%02x\n", - rceb->bEventType, le16_to_cpu(rceb->wEvent), - rceb->bEventContext); - return; - } - uwb_evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */ - uwb_evt->ts_jiffies = jiffies; - uwb_evt->type = UWB_EVT_TYPE_NOTIF; - uwb_evt->notif.size = size; - uwb_evt->notif.rceb = rceb; - - switch (le16_to_cpu(rceb->wEvent)) { - /* Trap some vendor specific events - * - * FIXME: move this to handling in ptc-est, where we - * register a NULL event handler for these two guys - * using the Intel IDs. - */ - case 0x0103: - dev_info(dev, "FIXME: DEVICE ADD\n"); - return; - case 0x0104: - dev_info(dev, "FIXME: DEVICE RM\n"); - return; - default: - break; - } - - uwbd_event_queue(uwb_evt); -} - -static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size_t size) -{ - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_neh *neh; - struct uwb_rceb *notif; - - if (rceb->bEventContext == 0) { - notif = kmalloc(size, GFP_ATOMIC); - if (notif) { - memcpy(notif, rceb, size); - uwb_rc_notif(rc, notif, size); - } else - dev_err(dev, "event 0x%02x/%04x/%02x (%zu bytes): no memory\n", - rceb->bEventType, le16_to_cpu(rceb->wEvent), - rceb->bEventContext, size); - } else { - neh = uwb_rc_neh_lookup(rc, rceb); - if (neh) - uwb_rc_neh_cb(neh, rceb, size); - else - dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", - rceb->bEventType, le16_to_cpu(rceb->wEvent), - rceb->bEventContext, size); - } -} - -/** - * Given a buffer with one or more UWB RC events/notifications, break - * them up and dispatch them. - * - * @rc: UWB Radio Controller - * @buf: Buffer with the stream of notifications/events - * @buf_size: Amount of data in the buffer - * - * Note each notification/event starts always with a 'struct - * uwb_rceb', so the minimum size if 4 bytes. - * - * The device may pass us events formatted differently than expected. - * These are first filtered, potentially creating a new event in a new - * memory location. If a new event is created by the filter it is also - * freed here. - * - * For each notif/event, tries to guess the size looking at the EST - * tables, then looks for a neh that is waiting for that event and if - * found, copies the payload to the neh's buffer and calls it back. If - * not, the data is ignored. - * - * Note that if we can't find a size description in the EST tables, we - * still might find a size in the 'neh' handle in uwb_rc_neh_lookup(). - * - * Assumptions: - * - * @rc->neh_lock is NOT taken - * - * We keep track of various sizes here: - * size: contains the size of the buffer that is processed for the - * incoming event. this buffer may contain events that are not - * formatted as WHCI. - * real_size: the actual space taken by this event in the buffer. - * We need to keep track of the real size of an event to be able to - * advance the buffer correctly. - * event_size: the size of the event as expected by the core layer - * [OR] the size of the event after filtering. if the filtering - * created a new event in a new memory location then this is - * effectively the size of a new event buffer - */ -void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) -{ - struct device *dev = &rc->uwb_dev.dev; - void *itr; - struct uwb_rceb *rceb; - size_t size, real_size, event_size; - int needtofree; - - d_fnstart(3, dev, "(rc %p buf %p %zu buf_size)\n", rc, buf, buf_size); - d_printf(2, dev, "groking event block: %zu bytes\n", buf_size); - itr = buf; - size = buf_size; - while (size > 0) { - if (size < sizeof(*rceb)) { - dev_err(dev, "not enough data in event buffer to " - "process incoming events (%zu left, minimum is " - "%zu)\n", size, sizeof(*rceb)); - break; - } - - rceb = itr; - if (rc->filter_event) { - needtofree = rc->filter_event(rc, &rceb, size, - &real_size, &event_size); - if (needtofree < 0 && needtofree != -ENOANO) { - dev_err(dev, "BUG: Unable to filter event " - "(0x%02x/%04x/%02x) from " - "device. \n", rceb->bEventType, - le16_to_cpu(rceb->wEvent), - rceb->bEventContext); - break; - } - } else - needtofree = -ENOANO; - /* do real processing if there was no filtering or the - * filtering didn't act */ - if (needtofree == -ENOANO) { - ssize_t ret = uwb_est_find_size(rc, rceb, size); - if (ret < 0) - break; - if (ret > size) { - dev_err(dev, "BUG: hw sent incomplete event " - "0x%02x/%04x/%02x (%zd bytes), only got " - "%zu bytes. We don't handle that.\n", - rceb->bEventType, le16_to_cpu(rceb->wEvent), - rceb->bEventContext, ret, size); - break; - } - real_size = event_size = ret; - } - uwb_rc_neh_grok_event(rc, rceb, event_size); - - if (needtofree == 1) - kfree(rceb); - - itr += real_size; - size -= real_size; - d_printf(2, dev, "consumed %zd bytes, %zu left\n", - event_size, size); - } - d_fnend(3, dev, "(rc %p buf %p %zu buf_size) = void\n", rc, buf, buf_size); -} -EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); - - -/** - * The entity that reads from the device notification/event channel has - * detected an error. - * - * @rc: UWB Radio Controller - * @error: Errno error code - * - */ -void uwb_rc_neh_error(struct uwb_rc *rc, int error) -{ - struct uwb_rc_neh *neh, *next; - unsigned long flags; - - BUG_ON(error >= 0); - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { - __uwb_rc_neh_rm(rc, neh); - uwb_rc_neh_cb(neh, NULL, error); - } - spin_unlock_irqrestore(&rc->neh_lock, flags); -} -EXPORT_SYMBOL_GPL(uwb_rc_neh_error); - - -static void uwb_rc_neh_timer(unsigned long arg) -{ - struct uwb_rc_neh *neh = (struct uwb_rc_neh *)arg; - struct uwb_rc *rc = neh->rc; - unsigned long flags; - - spin_lock_irqsave(&rc->neh_lock, flags); - __uwb_rc_neh_rm(rc, neh); - spin_unlock_irqrestore(&rc->neh_lock, flags); - - uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); -} - -/** Initializes the @rc's neh subsystem - */ -void uwb_rc_neh_create(struct uwb_rc *rc) -{ - spin_lock_init(&rc->neh_lock); - INIT_LIST_HEAD(&rc->neh_list); - set_bit(0, rc->ctx_bm); /* 0 is reserved (see [WUSB] table 8-65) */ - set_bit(0xff, rc->ctx_bm); /* and 0xff is invalid */ - rc->ctx_roll = 1; -} - - -/** Release's the @rc's neh subsystem */ -void uwb_rc_neh_destroy(struct uwb_rc *rc) -{ - unsigned long flags; - struct uwb_rc_neh *neh, *next; - - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { - __uwb_rc_neh_rm(rc, neh); - uwb_rc_neh_put(neh); - } - spin_unlock_irqrestore(&rc->neh_lock, flags); -} diff --git a/trunk/drivers/uwb/pal.c b/trunk/drivers/uwb/pal.c deleted file mode 100644 index 1afb38eacb9a..000000000000 --- a/trunk/drivers/uwb/pal.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * UWB PAL support. - * - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include - -#include "uwb-internal.h" - -/** - * uwb_pal_init - initialize a UWB PAL - * @pal: the PAL to initialize - */ -void uwb_pal_init(struct uwb_pal *pal) -{ - INIT_LIST_HEAD(&pal->node); -} -EXPORT_SYMBOL_GPL(uwb_pal_init); - -/** - * uwb_pal_register - register a UWB PAL - * @rc: the radio controller the PAL will be using - * @pal: the PAL - * - * The PAL must be initialized with uwb_pal_init(). - */ -int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) -{ - int ret; - - if (pal->device) { - ret = sysfs_create_link(&pal->device->kobj, - &rc->uwb_dev.dev.kobj, "uwb_rc"); - if (ret < 0) - return ret; - ret = sysfs_create_link(&rc->uwb_dev.dev.kobj, - &pal->device->kobj, pal->name); - if (ret < 0) { - sysfs_remove_link(&pal->device->kobj, "uwb_rc"); - return ret; - } - } - - spin_lock(&rc->pal_lock); - list_add(&pal->node, &rc->pals); - spin_unlock(&rc->pal_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(uwb_pal_register); - -/** - * uwb_pal_register - unregister a UWB PAL - * @rc: the radio controller the PAL was using - * @pal: the PAL - */ -void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal) -{ - spin_lock(&rc->pal_lock); - list_del(&pal->node); - spin_unlock(&rc->pal_lock); - - if (pal->device) { - sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); - sysfs_remove_link(&pal->device->kobj, "uwb_rc"); - } -} -EXPORT_SYMBOL_GPL(uwb_pal_unregister); - -/** - * uwb_rc_pal_init - initialize the PAL related parts of a radio controller - * @rc: the radio controller - */ -void uwb_rc_pal_init(struct uwb_rc *rc) -{ - spin_lock_init(&rc->pal_lock); - INIT_LIST_HEAD(&rc->pals); -} diff --git a/trunk/drivers/uwb/reset.c b/trunk/drivers/uwb/reset.c deleted file mode 100644 index 8de856fa7958..000000000000 --- a/trunk/drivers/uwb/reset.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Ultra Wide Band - * UWB basic command support and radio reset - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: - * - * - docs - * - * - Now we are serializing (using the uwb_dev->mutex) the command - * execution; it should be parallelized as much as possible some - * day. - */ -#include -#include - -#include "uwb-internal.h" -#define D_LOCAL 0 -#include - -/** - * Command result codes (WUSB1.0[T8-69]) - */ -static -const char *__strerror[] = { - "success", - "failure", - "hardware failure", - "no more slots", - "beacon is too large", - "invalid parameter", - "unsupported power level", - "time out (wa) or invalid ie data (whci)", - "beacon size exceeded", - "cancelled", - "invalid state", - "invalid size", - "ack not recieved", - "no more asie notification", -}; - - -/** Return a string matching the given error code */ -const char *uwb_rc_strerror(unsigned code) -{ - if (code == 255) - return "time out"; - if (code >= ARRAY_SIZE(__strerror)) - return "unknown error"; - return __strerror[code]; -} - -int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - uwb_rc_cmd_cb_f cb, void *arg) -{ - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_neh *neh; - int needtofree = 0; - int result; - - uwb_dev_lock(&rc->uwb_dev); /* Protect against rc->priv being removed */ - if (rc->priv == NULL) { - uwb_dev_unlock(&rc->uwb_dev); - return -ESHUTDOWN; - } - - if (rc->filter_cmd) { - needtofree = rc->filter_cmd(rc, &cmd, &cmd_size); - if (needtofree < 0 && needtofree != -ENOANO) { - dev_err(dev, "%s: filter error: %d\n", - cmd_name, needtofree); - uwb_dev_unlock(&rc->uwb_dev); - return needtofree; - } - } - - neh = uwb_rc_neh_add(rc, cmd, expected_type, expected_event, cb, arg); - if (IS_ERR(neh)) { - result = PTR_ERR(neh); - goto out; - } - - result = rc->cmd(rc, cmd, cmd_size); - uwb_dev_unlock(&rc->uwb_dev); - if (result < 0) - uwb_rc_neh_rm(rc, neh); - else - uwb_rc_neh_arm(rc, neh); - uwb_rc_neh_put(neh); -out: - if (needtofree == 1) - kfree(cmd); - return result < 0 ? result : 0; -} -EXPORT_SYMBOL_GPL(uwb_rc_cmd_async); - -struct uwb_rc_cmd_done_params { - struct completion completion; - struct uwb_rceb *reply; - ssize_t reply_size; -}; - -static void uwb_rc_cmd_done(struct uwb_rc *rc, void *arg, - struct uwb_rceb *reply, ssize_t reply_size) -{ - struct uwb_rc_cmd_done_params *p = (struct uwb_rc_cmd_done_params *)arg; - - if (reply_size > 0) { - if (p->reply) - reply_size = min(p->reply_size, reply_size); - else - p->reply = kmalloc(reply_size, GFP_ATOMIC); - - if (p->reply) - memcpy(p->reply, reply, reply_size); - else - reply_size = -ENOMEM; - } - p->reply_size = reply_size; - complete(&p->completion); -} - - -/** - * Generic function for issuing commands to the Radio Control Interface - * - * @rc: UWB Radio Control descriptor - * @cmd_name: Name of the command being issued (for error messages) - * @cmd: Pointer to rccb structure containing the command; - * normally you embed this structure as the first member of - * the full command structure. - * @cmd_size: Size of the whole command buffer pointed to by @cmd. - * @reply: Pointer to where to store the reply - * @reply_size: @reply's size - * @expected_type: Expected type in the return event - * @expected_event: Expected event code in the return event - * @preply: Here a pointer to where the event data is received will - * be stored. Once done with the data, free with kfree(). - * - * This function is generic; it works for commands that return a fixed - * and known size or for commands that return a variable amount of data. - * - * If a buffer is provided, that is used, although it could be chopped - * to the maximum size of the buffer. If the buffer is NULL, then one - * be allocated in *preply with the whole contents of the reply. - * - * @rc needs to be referenced - */ -static -ssize_t __uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - struct uwb_rceb *reply, size_t reply_size, - u8 expected_type, u16 expected_event, - struct uwb_rceb **preply) -{ - ssize_t result = 0; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_rc_cmd_done_params params; - - init_completion(¶ms.completion); - params.reply = reply; - params.reply_size = reply_size; - - result = uwb_rc_cmd_async(rc, cmd_name, cmd, cmd_size, - expected_type, expected_event, - uwb_rc_cmd_done, ¶ms); - if (result) - return result; - - wait_for_completion(¶ms.completion); - - if (preply) - *preply = params.reply; - - if (params.reply_size < 0) - dev_err(dev, "%s: confirmation event 0x%02x/%04x/%02x " - "reception failed: %d\n", cmd_name, - expected_type, expected_event, cmd->bCommandContext, - (int)params.reply_size); - return params.reply_size; -} - - -/** - * Generic function for issuing commands to the Radio Control Interface - * - * @rc: UWB Radio Control descriptor - * @cmd_name: Name of the command being issued (for error messages) - * @cmd: Pointer to rccb structure containing the command; - * normally you embed this structure as the first member of - * the full command structure. - * @cmd_size: Size of the whole command buffer pointed to by @cmd. - * @reply: Pointer to the beginning of the confirmation event - * buffer. Normally bigger than an 'struct hwarc_rceb'. - * You need to fill out reply->bEventType and reply->wEvent (in - * cpu order) as the function will use them to verify the - * confirmation event. - * @reply_size: Size of the reply buffer - * - * The function checks that the length returned in the reply is at - * least as big as @reply_size; if not, it will be deemed an error and - * -EIO returned. - * - * @rc needs to be referenced - */ -ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - struct uwb_rceb *reply, size_t reply_size) -{ - struct device *dev = &rc->uwb_dev.dev; - ssize_t result; - - result = __uwb_rc_cmd(rc, cmd_name, - cmd, cmd_size, reply, reply_size, - reply->bEventType, reply->wEvent, NULL); - - if (result > 0 && result < reply_size) { - dev_err(dev, "%s: not enough data returned for decoding reply " - "(%zu bytes received vs at least %zu needed)\n", - cmd_name, result, reply_size); - result = -EIO; - } - return result; -} -EXPORT_SYMBOL_GPL(uwb_rc_cmd); - - -/** - * Generic function for issuing commands to the Radio Control - * Interface that return an unknown amount of data - * - * @rc: UWB Radio Control descriptor - * @cmd_name: Name of the command being issued (for error messages) - * @cmd: Pointer to rccb structure containing the command; - * normally you embed this structure as the first member of - * the full command structure. - * @cmd_size: Size of the whole command buffer pointed to by @cmd. - * @expected_type: Expected type in the return event - * @expected_event: Expected event code in the return event - * @preply: Here a pointer to where the event data is received will - * be stored. Once done with the data, free with kfree(). - * - * The function checks that the length returned in the reply is at - * least as big as a 'struct uwb_rceb *'; if not, it will be deemed an - * error and -EIO returned. - * - * @rc needs to be referenced - */ -ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - struct uwb_rceb **preply) -{ - return __uwb_rc_cmd(rc, cmd_name, cmd, cmd_size, NULL, 0, - expected_type, expected_event, preply); -} -EXPORT_SYMBOL_GPL(uwb_rc_vcmd); - - -/** - * Reset a UWB Host Controller (and all radio settings) - * - * @rc: Host Controller descriptor - * @returns: 0 if ok, < 0 errno code on error - * - * We put the command on kmalloc'ed memory as some arches cannot do - * USB from the stack. The reply event is copied from an stage buffer, - * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. - */ -int uwb_rc_reset(struct uwb_rc *rc) -{ - int result = -ENOMEM; - struct uwb_rc_evt_confirm reply; - struct uwb_rccb *cmd; - size_t cmd_size = sizeof(*cmd); - - mutex_lock(&rc->uwb_dev.mutex); - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - goto error_kzalloc; - cmd->bCommandType = UWB_RC_CET_GENERAL; - cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET); - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_RESET; - result = uwb_rc_cmd(rc, "RESET", cmd, cmd_size, - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, - "RESET: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply.bResultCode), reply.bResultCode); - result = -EIO; - } -error_cmd: - kfree(cmd); -error_kzalloc: - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -int uwbd_msg_handle_reset(struct uwb_event *evt) -{ - struct uwb_rc *rc = evt->rc; - int ret; - - /* Need to prevent the RC hardware module going away while in - the rc->reset() call. */ - if (!try_module_get(rc->owner)) - return 0; - - dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); - ret = rc->reset(rc); - if (ret) - dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); - - module_put(rc->owner); - return ret; -} - -/** - * uwb_rc_reset_all - request a reset of the radio controller and PALs - * @rc: the radio controller of the hardware device to be reset. - * - * The full hardware reset of the radio controller and all the PALs - * will be scheduled. - */ -void uwb_rc_reset_all(struct uwb_rc *rc) -{ - struct uwb_event *evt; - - evt = kzalloc(sizeof(struct uwb_event), GFP_ATOMIC); - if (unlikely(evt == NULL)) - return; - - evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */ - evt->ts_jiffies = jiffies; - evt->type = UWB_EVT_TYPE_MSG; - evt->message = UWB_EVT_MSG_RESET; - - uwbd_event_queue(evt); -} -EXPORT_SYMBOL_GPL(uwb_rc_reset_all); diff --git a/trunk/drivers/uwb/rsv.c b/trunk/drivers/uwb/rsv.c deleted file mode 100644 index bae16204576d..000000000000 --- a/trunk/drivers/uwb/rsv.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * UWB reservation management. - * - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include - -#include "uwb-internal.h" - -static void uwb_rsv_timer(unsigned long arg); - -static const char *rsv_states[] = { - [UWB_RSV_STATE_NONE] = "none", - [UWB_RSV_STATE_O_INITIATED] = "initiated", - [UWB_RSV_STATE_O_PENDING] = "pending", - [UWB_RSV_STATE_O_MODIFIED] = "modified", - [UWB_RSV_STATE_O_ESTABLISHED] = "established", - [UWB_RSV_STATE_T_ACCEPTED] = "accepted", - [UWB_RSV_STATE_T_DENIED] = "denied", - [UWB_RSV_STATE_T_PENDING] = "pending", -}; - -static const char *rsv_types[] = { - [UWB_DRP_TYPE_ALIEN_BP] = "alien-bp", - [UWB_DRP_TYPE_HARD] = "hard", - [UWB_DRP_TYPE_SOFT] = "soft", - [UWB_DRP_TYPE_PRIVATE] = "private", - [UWB_DRP_TYPE_PCA] = "pca", -}; - -/** - * uwb_rsv_state_str - return a string for a reservation state - * @state: the reservation state. - */ -const char *uwb_rsv_state_str(enum uwb_rsv_state state) -{ - if (state < UWB_RSV_STATE_NONE || state >= UWB_RSV_STATE_LAST) - return "unknown"; - return rsv_states[state]; -} -EXPORT_SYMBOL_GPL(uwb_rsv_state_str); - -/** - * uwb_rsv_type_str - return a string for a reservation type - * @type: the reservation type - */ -const char *uwb_rsv_type_str(enum uwb_drp_type type) -{ - if (type < UWB_DRP_TYPE_ALIEN_BP || type > UWB_DRP_TYPE_PCA) - return "invalid"; - return rsv_types[type]; -} -EXPORT_SYMBOL_GPL(uwb_rsv_type_str); - -static void uwb_rsv_dump(struct uwb_rsv *rsv) -{ - struct device *dev = &rsv->rc->uwb_dev.dev; - struct uwb_dev_addr devaddr; - char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; - - uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); - if (rsv->target.type == UWB_RSV_TARGET_DEV) - devaddr = rsv->target.dev->dev_addr; - else - devaddr = rsv->target.devaddr; - uwb_dev_addr_print(target, sizeof(target), &devaddr); - - dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); -} - -/* - * Get a free stream index for a reservation. - * - * If the target is a DevAddr (e.g., a WUSB cluster reservation) then - * the stream is allocated from a pool of per-RC stream indexes, - * otherwise a unique stream index for the target is selected. - */ -static int uwb_rsv_get_stream(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - unsigned long *streams_bm; - int stream; - - switch (rsv->target.type) { - case UWB_RSV_TARGET_DEV: - streams_bm = rsv->target.dev->streams; - break; - case UWB_RSV_TARGET_DEVADDR: - streams_bm = rc->uwb_dev.streams; - break; - default: - return -EINVAL; - } - - stream = find_first_zero_bit(streams_bm, UWB_NUM_STREAMS); - if (stream >= UWB_NUM_STREAMS) - return -EBUSY; - - rsv->stream = stream; - set_bit(stream, streams_bm); - - return 0; -} - -static void uwb_rsv_put_stream(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - unsigned long *streams_bm; - - switch (rsv->target.type) { - case UWB_RSV_TARGET_DEV: - streams_bm = rsv->target.dev->streams; - break; - case UWB_RSV_TARGET_DEVADDR: - streams_bm = rc->uwb_dev.streams; - break; - default: - return; - } - - clear_bit(rsv->stream, streams_bm); -} - -/* - * Generate a MAS allocation with a single row component. - */ -static void uwb_rsv_gen_alloc_row(struct uwb_mas_bm *mas, - int first_mas, int mas_per_zone, - int zs, int ze) -{ - struct uwb_mas_bm col; - int z; - - bitmap_zero(mas->bm, UWB_NUM_MAS); - bitmap_zero(col.bm, UWB_NUM_MAS); - bitmap_fill(col.bm, mas_per_zone); - bitmap_shift_left(col.bm, col.bm, first_mas + zs * UWB_MAS_PER_ZONE, UWB_NUM_MAS); - - for (z = zs; z <= ze; z++) { - bitmap_or(mas->bm, mas->bm, col.bm, UWB_NUM_MAS); - bitmap_shift_left(col.bm, col.bm, UWB_MAS_PER_ZONE, UWB_NUM_MAS); - } -} - -/* - * Allocate some MAS for this reservation based on current local - * availability, the reservation parameters (max_mas, min_mas, - * sparsity), and the WiMedia rules for MAS allocations. - * - * Returns -EBUSY is insufficient free MAS are available. - * - * FIXME: to simplify this, only safe reservations with a single row - * component in zones 1 to 15 are tried (zone 0 is skipped to avoid - * problems with the MAS reserved for the BP). - * - * [ECMA-368] section B.2. - */ -static int uwb_rsv_alloc_mas(struct uwb_rsv *rsv) -{ - static const int safe_mas_in_row[UWB_NUM_ZONES] = { - 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, - }; - int n, r; - struct uwb_mas_bm mas; - bool found = false; - - /* - * Search all valid safe allocations until either: too few MAS - * are available; or the smallest allocation with sufficient - * MAS is found. - * - * The top of the zones are preferred, so space for larger - * allocations is available in the bottom of the zone (e.g., a - * 15 MAS allocation should start in row 14 leaving space for - * a 120 MAS allocation at row 0). - */ - for (n = safe_mas_in_row[0]; n >= 1; n--) { - int num_mas; - - num_mas = n * (UWB_NUM_ZONES - 1); - if (num_mas < rsv->min_mas) - break; - if (found && num_mas < rsv->max_mas) - break; - - for (r = UWB_MAS_PER_ZONE-1; r >= 0; r--) { - if (safe_mas_in_row[r] < n) - continue; - uwb_rsv_gen_alloc_row(&mas, r, n, 1, UWB_NUM_ZONES); - if (uwb_drp_avail_reserve_pending(rsv->rc, &mas) == 0) { - found = true; - break; - } - } - } - - if (!found) - return -EBUSY; - - bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS); - return 0; -} - -static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) -{ - int sframes = UWB_MAX_LOST_BEACONS; - - /* - * Multicast reservations can become established within 1 - * super frame and should not be terminated if no response is - * received. - */ - if (rsv->is_multicast) { - if (rsv->state == UWB_RSV_STATE_O_INITIATED) - sframes = 1; - if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED) - sframes = 0; - } - - rsv->expired = false; - if (sframes > 0) { - /* - * Add an additional 2 superframes to account for the - * time to send the SET DRP IE command. - */ - unsigned timeout_us = (sframes + 2) * UWB_SUPERFRAME_LENGTH_US; - mod_timer(&rsv->timer, jiffies + usecs_to_jiffies(timeout_us)); - } else - del_timer(&rsv->timer); -} - -/* - * Update a reservations state, and schedule an update of the - * transmitted DRP IEs. - */ -static void uwb_rsv_state_update(struct uwb_rsv *rsv, - enum uwb_rsv_state new_state) -{ - rsv->state = new_state; - rsv->ie_valid = false; - - uwb_rsv_dump(rsv); - - uwb_rsv_stroke_timer(rsv); - uwb_rsv_sched_update(rsv->rc); -} - -static void uwb_rsv_callback(struct uwb_rsv *rsv) -{ - if (rsv->callback) - rsv->callback(rsv); -} - -void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) -{ - if (rsv->state == new_state) { - switch (rsv->state) { - case UWB_RSV_STATE_O_ESTABLISHED: - case UWB_RSV_STATE_T_ACCEPTED: - case UWB_RSV_STATE_NONE: - uwb_rsv_stroke_timer(rsv); - break; - default: - /* Expecting a state transition so leave timer - as-is. */ - break; - } - return; - } - - switch (new_state) { - case UWB_RSV_STATE_NONE: - uwb_drp_avail_release(rsv->rc, &rsv->mas); - uwb_rsv_put_stream(rsv); - uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); - uwb_rsv_callback(rsv); - break; - case UWB_RSV_STATE_O_INITIATED: - uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_INITIATED); - break; - case UWB_RSV_STATE_O_PENDING: - uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_PENDING); - break; - case UWB_RSV_STATE_O_ESTABLISHED: - uwb_drp_avail_reserve(rsv->rc, &rsv->mas); - uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_ESTABLISHED); - uwb_rsv_callback(rsv); - break; - case UWB_RSV_STATE_T_ACCEPTED: - uwb_drp_avail_reserve(rsv->rc, &rsv->mas); - uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_ACCEPTED); - uwb_rsv_callback(rsv); - break; - case UWB_RSV_STATE_T_DENIED: - uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_DENIED); - break; - default: - dev_err(&rsv->rc->uwb_dev.dev, "unhandled state: %s (%d)\n", - uwb_rsv_state_str(new_state), new_state); - } -} - -static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) -{ - struct uwb_rsv *rsv; - - rsv = kzalloc(sizeof(struct uwb_rsv), GFP_KERNEL); - if (!rsv) - return NULL; - - INIT_LIST_HEAD(&rsv->rc_node); - INIT_LIST_HEAD(&rsv->pal_node); - init_timer(&rsv->timer); - rsv->timer.function = uwb_rsv_timer; - rsv->timer.data = (unsigned long)rsv; - - rsv->rc = rc; - - return rsv; -} - -static void uwb_rsv_free(struct uwb_rsv *rsv) -{ - uwb_dev_put(rsv->owner); - if (rsv->target.type == UWB_RSV_TARGET_DEV) - uwb_dev_put(rsv->target.dev); - kfree(rsv); -} - -/** - * uwb_rsv_create - allocate and initialize a UWB reservation structure - * @rc: the radio controller - * @cb: callback to use when the reservation completes or terminates - * @pal_priv: data private to the PAL to be passed in the callback - * - * The callback is called when the state of the reservation changes from: - * - * - pending to accepted - * - pending to denined - * - accepted to terminated - * - pending to terminated - */ -struct uwb_rsv *uwb_rsv_create(struct uwb_rc *rc, uwb_rsv_cb_f cb, void *pal_priv) -{ - struct uwb_rsv *rsv; - - rsv = uwb_rsv_alloc(rc); - if (!rsv) - return NULL; - - rsv->callback = cb; - rsv->pal_priv = pal_priv; - - return rsv; -} -EXPORT_SYMBOL_GPL(uwb_rsv_create); - -void uwb_rsv_remove(struct uwb_rsv *rsv) -{ - if (rsv->state != UWB_RSV_STATE_NONE) - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); - del_timer_sync(&rsv->timer); - list_del(&rsv->rc_node); - uwb_rsv_free(rsv); -} - -/** - * uwb_rsv_destroy - free a UWB reservation structure - * @rsv: the reservation to free - * - * The reservation will be terminated if it is pending or established. - */ -void uwb_rsv_destroy(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - - mutex_lock(&rc->rsvs_mutex); - uwb_rsv_remove(rsv); - mutex_unlock(&rc->rsvs_mutex); -} -EXPORT_SYMBOL_GPL(uwb_rsv_destroy); - -/** - * usb_rsv_establish - start a reservation establishment - * @rsv: the reservation - * - * The PAL should fill in @rsv's owner, target, type, max_mas, - * min_mas, sparsity and is_multicast fields. If the target is a - * uwb_dev it must be referenced. - * - * The reservation's callback will be called when the reservation is - * accepted, denied or times out. - */ -int uwb_rsv_establish(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - int ret; - - mutex_lock(&rc->rsvs_mutex); - - ret = uwb_rsv_get_stream(rsv); - if (ret) - goto out; - - ret = uwb_rsv_alloc_mas(rsv); - if (ret) { - uwb_rsv_put_stream(rsv); - goto out; - } - - list_add_tail(&rsv->rc_node, &rc->reservations); - rsv->owner = &rc->uwb_dev; - uwb_dev_get(rsv->owner); - uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_INITIATED); -out: - mutex_unlock(&rc->rsvs_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(uwb_rsv_establish); - -/** - * uwb_rsv_modify - modify an already established reservation - * @rsv: the reservation to modify - * @max_mas: new maximum MAS to reserve - * @min_mas: new minimum MAS to reserve - * @sparsity: new sparsity to use - * - * FIXME: implement this once there are PALs that use it. - */ -int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int sparsity) -{ - return -ENOSYS; -} -EXPORT_SYMBOL_GPL(uwb_rsv_modify); - -/** - * uwb_rsv_terminate - terminate an established reservation - * @rsv: the reservation to terminate - * - * A reservation is terminated by removing the DRP IE from the beacon, - * the other end will consider the reservation to be terminated when - * it does not see the DRP IE for at least mMaxLostBeacons. - * - * If applicable, the reference to the target uwb_dev will be released. - */ -void uwb_rsv_terminate(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - - mutex_lock(&rc->rsvs_mutex); - - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); - - mutex_unlock(&rc->rsvs_mutex); -} -EXPORT_SYMBOL_GPL(uwb_rsv_terminate); - -/** - * uwb_rsv_accept - accept a new reservation from a peer - * @rsv: the reservation - * @cb: call back for reservation changes - * @pal_priv: data to be passed in the above call back - * - * Reservation requests from peers are denied unless a PAL accepts it - * by calling this function. - */ -void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) -{ - rsv->callback = cb; - rsv->pal_priv = pal_priv; - rsv->state = UWB_RSV_STATE_T_ACCEPTED; -} -EXPORT_SYMBOL_GPL(uwb_rsv_accept); - -/* - * Is a received DRP IE for this reservation? - */ -static bool uwb_rsv_match(struct uwb_rsv *rsv, struct uwb_dev *src, - struct uwb_ie_drp *drp_ie) -{ - struct uwb_dev_addr *rsv_src; - int stream; - - stream = uwb_ie_drp_stream_index(drp_ie); - - if (rsv->stream != stream) - return false; - - switch (rsv->target.type) { - case UWB_RSV_TARGET_DEVADDR: - return rsv->stream == stream; - case UWB_RSV_TARGET_DEV: - if (uwb_ie_drp_owner(drp_ie)) - rsv_src = &rsv->owner->dev_addr; - else - rsv_src = &rsv->target.dev->dev_addr; - return uwb_dev_addr_cmp(&src->dev_addr, rsv_src) == 0; - } - return false; -} - -static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, - struct uwb_dev *src, - struct uwb_ie_drp *drp_ie) -{ - struct uwb_rsv *rsv; - struct uwb_pal *pal; - enum uwb_rsv_state state; - - rsv = uwb_rsv_alloc(rc); - if (!rsv) - return NULL; - - rsv->rc = rc; - rsv->owner = src; - uwb_dev_get(rsv->owner); - rsv->target.type = UWB_RSV_TARGET_DEV; - rsv->target.dev = &rc->uwb_dev; - rsv->type = uwb_ie_drp_type(drp_ie); - rsv->stream = uwb_ie_drp_stream_index(drp_ie); - set_bit(rsv->stream, rsv->owner->streams); - uwb_drp_ie_to_bm(&rsv->mas, drp_ie); - - /* - * See if any PALs are interested in this reservation. If not, - * deny the request. - */ - rsv->state = UWB_RSV_STATE_T_DENIED; - spin_lock(&rc->pal_lock); - list_for_each_entry(pal, &rc->pals, node) { - if (pal->new_rsv) - pal->new_rsv(rsv); - if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) - break; - } - spin_unlock(&rc->pal_lock); - - list_add_tail(&rsv->rc_node, &rc->reservations); - state = rsv->state; - rsv->state = UWB_RSV_STATE_NONE; - uwb_rsv_set_state(rsv, state); - - return rsv; -} - -/** - * uwb_rsv_find - find a reservation for a received DRP IE. - * @rc: the radio controller - * @src: source of the DRP IE - * @drp_ie: the DRP IE - * - * If the reservation cannot be found and the DRP IE is from a peer - * attempting to establish a new reservation, create a new reservation - * and add it to the list. - */ -struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src, - struct uwb_ie_drp *drp_ie) -{ - struct uwb_rsv *rsv; - - list_for_each_entry(rsv, &rc->reservations, rc_node) { - if (uwb_rsv_match(rsv, src, drp_ie)) - return rsv; - } - - if (uwb_ie_drp_owner(drp_ie)) - return uwb_rsv_new_target(rc, src, drp_ie); - - return NULL; -} - -/* - * Go through all the reservations and check for timeouts and (if - * necessary) update their DRP IEs. - * - * FIXME: look at building the SET_DRP_IE command here rather than - * having to rescan the list in uwb_rc_send_all_drp_ie(). - */ -static bool uwb_rsv_update_all(struct uwb_rc *rc) -{ - struct uwb_rsv *rsv, *t; - bool ie_updated = false; - - list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { - if (rsv->expired) - uwb_drp_handle_timeout(rsv); - if (!rsv->ie_valid) { - uwb_drp_ie_update(rsv); - ie_updated = true; - } - } - - return ie_updated; -} - -void uwb_rsv_sched_update(struct uwb_rc *rc) -{ - queue_work(rc->rsv_workq, &rc->rsv_update_work); -} - -/* - * Update DRP IEs and, if necessary, the DRP Availability IE and send - * the updated IEs to the radio controller. - */ -static void uwb_rsv_update_work(struct work_struct *work) -{ - struct uwb_rc *rc = container_of(work, struct uwb_rc, rsv_update_work); - bool ie_updated; - - mutex_lock(&rc->rsvs_mutex); - - ie_updated = uwb_rsv_update_all(rc); - - if (!rc->drp_avail.ie_valid) { - uwb_drp_avail_ie_update(rc); - ie_updated = true; - } - - if (ie_updated) - uwb_rc_send_all_drp_ie(rc); - - mutex_unlock(&rc->rsvs_mutex); -} - -static void uwb_rsv_timer(unsigned long arg) -{ - struct uwb_rsv *rsv = (struct uwb_rsv *)arg; - - rsv->expired = true; - uwb_rsv_sched_update(rsv->rc); -} - -void uwb_rsv_init(struct uwb_rc *rc) -{ - INIT_LIST_HEAD(&rc->reservations); - mutex_init(&rc->rsvs_mutex); - INIT_WORK(&rc->rsv_update_work, uwb_rsv_update_work); - - bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS); -} - -int uwb_rsv_setup(struct uwb_rc *rc) -{ - char name[16]; - - snprintf(name, sizeof(name), "%s_rsvd", dev_name(&rc->uwb_dev.dev)); - rc->rsv_workq = create_singlethread_workqueue(name); - if (rc->rsv_workq == NULL) - return -ENOMEM; - - return 0; -} - -void uwb_rsv_cleanup(struct uwb_rc *rc) -{ - struct uwb_rsv *rsv, *t; - - mutex_lock(&rc->rsvs_mutex); - list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { - uwb_rsv_remove(rsv); - } - mutex_unlock(&rc->rsvs_mutex); - - cancel_work_sync(&rc->rsv_update_work); - destroy_workqueue(rc->rsv_workq); -} diff --git a/trunk/drivers/uwb/scan.c b/trunk/drivers/uwb/scan.c deleted file mode 100644 index 2d270748f32b..000000000000 --- a/trunk/drivers/uwb/scan.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Ultra Wide Band - * Scanning management - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * - * FIXME: docs - * FIXME: there are issues here on how BEACON and SCAN on USB RCI deal - * with each other. Currently seems that START_BEACON while - * SCAN_ONLY will cancel the scan, so we need to update the - * state here. Clarification request sent by email on - * 10/05/2005. - * 10/28/2005 No clear answer heard--maybe we'll hack the API - * so that when we start beaconing, if the HC is - * scanning in a mode not compatible with beaconing - * we just fail. - */ - -#include -#include -#include "uwb-internal.h" - - -/** - * Start/stop scanning in a radio controller - * - * @rc: UWB Radio Controlller - * @channel: Channel to scan; encodings in WUSB1.0[Table 5.12] - * @type: Type of scanning to do. - * @bpst_offset: value at which to start scanning (if type == - * UWB_SCAN_ONLY_STARTTIME) - * @returns: 0 if ok, < 0 errno code on error - * - * We put the command on kmalloc'ed memory as some arches cannot do - * USB from the stack. The reply event is copied from an stage buffer, - * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. - */ -int uwb_rc_scan(struct uwb_rc *rc, - unsigned channel, enum uwb_scan_type type, - unsigned bpst_offset) -{ - int result; - struct uwb_rc_cmd_scan *cmd; - struct uwb_rc_evt_confirm reply; - - result = -ENOMEM; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - goto error_kzalloc; - mutex_lock(&rc->uwb_dev.mutex); - cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; - cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SCAN); - cmd->bChannelNumber = channel; - cmd->bScanState = type; - cmd->wStartTime = cpu_to_le16(bpst_offset); - reply.rceb.bEventType = UWB_RC_CET_GENERAL; - reply.rceb.wEvent = UWB_RC_CMD_SCAN; - result = uwb_rc_cmd(rc, "SCAN", &cmd->rccb, sizeof(*cmd), - &reply.rceb, sizeof(reply)); - if (result < 0) - goto error_cmd; - if (reply.bResultCode != UWB_RC_RES_SUCCESS) { - dev_err(&rc->uwb_dev.dev, - "SCAN: command execution failed: %s (%d)\n", - uwb_rc_strerror(reply.bResultCode), reply.bResultCode); - result = -EIO; - goto error_cmd; - } - rc->scanning = channel; - rc->scan_type = type; -error_cmd: - mutex_unlock(&rc->uwb_dev.mutex); - kfree(cmd); -error_kzalloc: - return result; -} - -/* - * Print scanning state - */ -static ssize_t uwb_rc_scan_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - ssize_t result; - - mutex_lock(&rc->uwb_dev.mutex); - result = sprintf(buf, "%d %d\n", rc->scanning, rc->scan_type); - mutex_unlock(&rc->uwb_dev.mutex); - return result; -} - -/* - * - */ -static ssize_t uwb_rc_scan_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - struct uwb_rc *rc = uwb_dev->rc; - unsigned channel; - unsigned type; - unsigned bpst_offset = 0; - ssize_t result = -EINVAL; - - result = sscanf(buf, "%u %u %u\n", &channel, &type, &bpst_offset); - if (result >= 2 && type < UWB_SCAN_TOP) - result = uwb_rc_scan(rc, channel, type, bpst_offset); - - return result < 0 ? result : size; -} - -/** Radio Control sysfs interface (declaration) */ -DEVICE_ATTR(scan, S_IRUGO | S_IWUSR, uwb_rc_scan_show, uwb_rc_scan_store); diff --git a/trunk/drivers/uwb/umc-bus.c b/trunk/drivers/uwb/umc-bus.c deleted file mode 100644 index 2d8d62d9f53e..000000000000 --- a/trunk/drivers/uwb/umc-bus.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Bus for UWB Multi-interface Controller capabilities. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * This file is released under the GNU GPL v2. - */ -#include -#include -#include -#include -#include - -static int umc_bus_unbind_helper(struct device *dev, void *data) -{ - struct device *parent = data; - - if (dev->parent == parent && dev->driver) - device_release_driver(dev); - return 0; -} - -/** - * umc_controller_reset - reset the whole UMC controller - * @umc: the UMC device for the radio controller. - * - * Drivers will be unbound from all UMC devices belonging to the - * controller and then the radio controller will be rebound. The - * radio controller is expected to do a full hardware reset when it is - * probed. - * - * If this is called while a probe() or remove() is in progress it - * will return -EAGAIN and not perform the reset. - */ -int umc_controller_reset(struct umc_dev *umc) -{ - struct device *parent = umc->dev.parent; - int ret; - - if (down_trylock(&parent->sem)) - return -EAGAIN; - bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); - ret = device_attach(&umc->dev); - if (ret == 1) - ret = 0; - up(&parent->sem); - - return ret; -} -EXPORT_SYMBOL_GPL(umc_controller_reset); - -/** - * umc_match_pci_id - match a UMC driver to a UMC device's parent PCI device. - * @umc_drv: umc driver with match_data pointing to a zero-terminated - * table of pci_device_id's. - * @umc: umc device whose parent is to be matched. - */ -int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc) -{ - const struct pci_device_id *id_table = umc_drv->match_data; - struct pci_dev *pci; - - if (umc->dev.parent->bus != &pci_bus_type) - return 0; - - pci = to_pci_dev(umc->dev.parent); - return pci_match_id(id_table, pci) != NULL; -} -EXPORT_SYMBOL_GPL(umc_match_pci_id); - -static int umc_bus_rescan_helper(struct device *dev, void *data) -{ - int ret = 0; - - if (!dev->driver) - ret = device_attach(dev); - - return ret < 0 ? ret : 0; -} - -static void umc_bus_rescan(void) -{ - int err; - - /* - * We can't use bus_rescan_devices() here as it deadlocks when - * it tries to retake the dev->parent semaphore. - */ - err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); - if (err < 0) - printk(KERN_WARNING "%s: rescan of bus failed: %d\n", - KBUILD_MODNAME, err); -} - -static int umc_bus_match(struct device *dev, struct device_driver *drv) -{ - struct umc_dev *umc = to_umc_dev(dev); - struct umc_driver *umc_driver = to_umc_driver(drv); - - if (umc->cap_id == umc_driver->cap_id) { - if (umc_driver->match) - return umc_driver->match(umc_driver, umc); - else - return 1; - } - return 0; -} - -static int umc_device_probe(struct device *dev) -{ - struct umc_dev *umc; - struct umc_driver *umc_driver; - int err; - - umc_driver = to_umc_driver(dev->driver); - umc = to_umc_dev(dev); - - get_device(dev); - err = umc_driver->probe(umc); - if (err) - put_device(dev); - else - umc_bus_rescan(); - - return err; -} - -static int umc_device_remove(struct device *dev) -{ - struct umc_dev *umc; - struct umc_driver *umc_driver; - - umc_driver = to_umc_driver(dev->driver); - umc = to_umc_dev(dev); - - umc_driver->remove(umc); - put_device(dev); - return 0; -} - -static int umc_device_suspend(struct device *dev, pm_message_t state) -{ - struct umc_dev *umc; - struct umc_driver *umc_driver; - int err = 0; - - umc = to_umc_dev(dev); - - if (dev->driver) { - umc_driver = to_umc_driver(dev->driver); - if (umc_driver->suspend) - err = umc_driver->suspend(umc, state); - } - return err; -} - -static int umc_device_resume(struct device *dev) -{ - struct umc_dev *umc; - struct umc_driver *umc_driver; - int err = 0; - - umc = to_umc_dev(dev); - - if (dev->driver) { - umc_driver = to_umc_driver(dev->driver); - if (umc_driver->resume) - err = umc_driver->resume(umc); - } - return err; -} - -static ssize_t capability_id_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct umc_dev *umc = to_umc_dev(dev); - - return sprintf(buf, "0x%02x\n", umc->cap_id); -} - -static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct umc_dev *umc = to_umc_dev(dev); - - return sprintf(buf, "0x%04x\n", umc->version); -} - -static struct device_attribute umc_dev_attrs[] = { - __ATTR_RO(capability_id), - __ATTR_RO(version), - __ATTR_NULL, -}; - -struct bus_type umc_bus_type = { - .name = "umc", - .match = umc_bus_match, - .probe = umc_device_probe, - .remove = umc_device_remove, - .suspend = umc_device_suspend, - .resume = umc_device_resume, - .dev_attrs = umc_dev_attrs, -}; -EXPORT_SYMBOL_GPL(umc_bus_type); - -static int __init umc_bus_init(void) -{ - return bus_register(&umc_bus_type); -} -module_init(umc_bus_init); - -static void __exit umc_bus_exit(void) -{ - bus_unregister(&umc_bus_type); -} -module_exit(umc_bus_exit); - -MODULE_DESCRIPTION("UWB Multi-interface Controller capability bus"); -MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/umc-dev.c b/trunk/drivers/uwb/umc-dev.c deleted file mode 100644 index aa44e1c1a102..000000000000 --- a/trunk/drivers/uwb/umc-dev.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * UWB Multi-interface Controller device management. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * This file is released under the GNU GPL v2. - */ -#include -#include -#define D_LOCAL 0 -#include - -static void umc_device_release(struct device *dev) -{ - struct umc_dev *umc = to_umc_dev(dev); - - kfree(umc); -} - -/** - * umc_device_create - allocate a child UMC device - * @parent: parent of the new UMC device. - * @n: index of the new device. - * - * The new UMC device will have a bus ID of the parent with '-n' - * appended. - */ -struct umc_dev *umc_device_create(struct device *parent, int n) -{ - struct umc_dev *umc; - - umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); - if (umc) { - snprintf(umc->dev.bus_id, sizeof(umc->dev.bus_id), "%s-%d", - parent->bus_id, n); - umc->dev.parent = parent; - umc->dev.bus = &umc_bus_type; - umc->dev.release = umc_device_release; - - umc->dev.dma_mask = parent->dma_mask; - } - return umc; -} -EXPORT_SYMBOL_GPL(umc_device_create); - -/** - * umc_device_register - register a UMC device - * @umc: pointer to the UMC device - * - * The memory resource for the UMC device is acquired and the device - * registered with the system. - */ -int umc_device_register(struct umc_dev *umc) -{ - int err; - - d_fnstart(3, &umc->dev, "(umc_dev %p)\n", umc); - - err = request_resource(umc->resource.parent, &umc->resource); - if (err < 0) { - dev_err(&umc->dev, "can't allocate resource range " - "%016Lx to %016Lx: %d\n", - (unsigned long long)umc->resource.start, - (unsigned long long)umc->resource.end, - err); - goto error_request_resource; - } - - err = device_register(&umc->dev); - if (err < 0) - goto error_device_register; - d_fnend(3, &umc->dev, "(umc_dev %p) = 0\n", umc); - return 0; - -error_device_register: - release_resource(&umc->resource); -error_request_resource: - d_fnend(3, &umc->dev, "(umc_dev %p) = %d\n", umc, err); - return err; -} -EXPORT_SYMBOL_GPL(umc_device_register); - -/** - * umc_device_unregister - unregister a UMC device - * @umc: pointer to the UMC device - * - * First we unregister the device, make sure the driver can do it's - * resource release thing and then we try to release any left over - * resources. We take a ref to the device, to make sure it doesn't - * dissapear under our feet. - */ -void umc_device_unregister(struct umc_dev *umc) -{ - struct device *dev; - if (!umc) - return; - dev = get_device(&umc->dev); - d_fnstart(3, dev, "(umc_dev %p)\n", umc); - device_unregister(&umc->dev); - release_resource(&umc->resource); - d_fnend(3, dev, "(umc_dev %p) = void\n", umc); - put_device(dev); -} -EXPORT_SYMBOL_GPL(umc_device_unregister); diff --git a/trunk/drivers/uwb/umc-drv.c b/trunk/drivers/uwb/umc-drv.c deleted file mode 100644 index 367b5eb85d60..000000000000 --- a/trunk/drivers/uwb/umc-drv.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * UWB Multi-interface Controller driver management. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * This file is released under the GNU GPL v2. - */ -#include -#include - -int __umc_driver_register(struct umc_driver *umc_drv, struct module *module, - const char *mod_name) -{ - umc_drv->driver.name = umc_drv->name; - umc_drv->driver.owner = module; - umc_drv->driver.mod_name = mod_name; - umc_drv->driver.bus = &umc_bus_type; - - return driver_register(&umc_drv->driver); -} -EXPORT_SYMBOL_GPL(__umc_driver_register); - -/** - * umc_driver_register - unregister a UMC capabiltity driver. - * @umc_drv: pointer to the driver. - */ -void umc_driver_unregister(struct umc_driver *umc_drv) -{ - driver_unregister(&umc_drv->driver); -} -EXPORT_SYMBOL_GPL(umc_driver_unregister); diff --git a/trunk/drivers/uwb/uwb-debug.c b/trunk/drivers/uwb/uwb-debug.c deleted file mode 100644 index 6d232c35d07d..000000000000 --- a/trunk/drivers/uwb/uwb-debug.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Ultra Wide Band - * Debug support - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: doc - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define D_LOCAL 0 -#include - -#include "uwb-internal.h" - -void dump_bytes(struct device *dev, const void *_buf, size_t rsize) -{ - const char *buf = _buf; - char line[32]; - size_t offset = 0; - int cnt, cnt2; - for (cnt = 0; cnt < rsize; cnt += 8) { - size_t rtop = rsize - cnt < 8 ? rsize - cnt : 8; - for (offset = cnt2 = 0; cnt2 < rtop; cnt2++) { - offset += scnprintf(line + offset, sizeof(line) - offset, - "%02x ", buf[cnt + cnt2] & 0xff); - } - if (dev) - dev_info(dev, "%s\n", line); - else - printk(KERN_INFO "%s\n", line); - } -} -EXPORT_SYMBOL_GPL(dump_bytes); - -/* - * Debug interface - * - * Per radio controller debugfs files (in uwb/uwbN/): - * - * command: Flexible command interface (see ). - * - * reservations: information on reservations. - * - * accept: Set to true (Y or 1) to accept reservation requests from - * peers. - * - * drp_avail: DRP availability information. - */ - -struct uwb_dbg { - struct uwb_pal pal; - - u32 accept; - struct list_head rsvs; - - struct dentry *root_d; - struct dentry *command_f; - struct dentry *reservations_f; - struct dentry *accept_f; - struct dentry *drp_avail_f; -}; - -static struct dentry *root_dir; - -static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_dev_addr devaddr; - char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; - - uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); - if (rsv->target.type == UWB_RSV_TARGET_DEV) - devaddr = rsv->target.dev->dev_addr; - else - devaddr = rsv->target.devaddr; - uwb_dev_addr_print(target, sizeof(target), &devaddr); - - dev_dbg(dev, "debug: rsv %s -> %s: %s\n", - owner, target, uwb_rsv_state_str(rsv->state)); -} - -static int cmd_rsv_establish(struct uwb_rc *rc, - struct uwb_dbg_cmd_rsv_establish *cmd) -{ - struct uwb_mac_addr macaddr; - struct uwb_rsv *rsv; - struct uwb_dev *target; - int ret; - - memcpy(&macaddr, cmd->target, sizeof(macaddr)); - target = uwb_dev_get_by_macaddr(rc, &macaddr); - if (target == NULL) - return -ENODEV; - - rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, NULL); - if (rsv == NULL) { - uwb_dev_put(target); - return -ENOMEM; - } - - rsv->owner = &rc->uwb_dev; - rsv->target.type = UWB_RSV_TARGET_DEV; - rsv->target.dev = target; - rsv->type = cmd->type; - rsv->max_mas = cmd->max_mas; - rsv->min_mas = cmd->min_mas; - rsv->sparsity = cmd->sparsity; - - ret = uwb_rsv_establish(rsv); - if (ret) - uwb_rsv_destroy(rsv); - else - list_add_tail(&rsv->pal_node, &rc->dbg->rsvs); - - return ret; -} - -static int cmd_rsv_terminate(struct uwb_rc *rc, - struct uwb_dbg_cmd_rsv_terminate *cmd) -{ - struct uwb_rsv *rsv, *found = NULL; - int i = 0; - - list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) { - if (i == cmd->index) { - found = rsv; - break; - } - } - if (!found) - return -EINVAL; - - list_del(&found->pal_node); - uwb_rsv_terminate(found); - - return 0; -} - -static int command_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - -static ssize_t command_write(struct file *file, const char __user *buf, - size_t len, loff_t *off) -{ - struct uwb_rc *rc = file->private_data; - struct uwb_dbg_cmd cmd; - int ret; - - if (len != sizeof(struct uwb_dbg_cmd)) - return -EINVAL; - - if (copy_from_user(&cmd, buf, len) != 0) - return -EFAULT; - - switch (cmd.type) { - case UWB_DBG_CMD_RSV_ESTABLISH: - ret = cmd_rsv_establish(rc, &cmd.rsv_establish); - break; - case UWB_DBG_CMD_RSV_TERMINATE: - ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); - break; - default: - return -EINVAL; - } - - return ret < 0 ? ret : len; -} - -static struct file_operations command_fops = { - .open = command_open, - .write = command_write, - .read = NULL, - .llseek = no_llseek, - .owner = THIS_MODULE, -}; - -static int reservations_print(struct seq_file *s, void *p) -{ - struct uwb_rc *rc = s->private; - struct uwb_rsv *rsv; - - mutex_lock(&rc->rsvs_mutex); - - list_for_each_entry(rsv, &rc->reservations, rc_node) { - struct uwb_dev_addr devaddr; - char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; - bool is_owner; - char buf[72]; - - uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); - if (rsv->target.type == UWB_RSV_TARGET_DEV) { - devaddr = rsv->target.dev->dev_addr; - is_owner = &rc->uwb_dev == rsv->owner; - } else { - devaddr = rsv->target.devaddr; - is_owner = true; - } - uwb_dev_addr_print(target, sizeof(target), &devaddr); - - seq_printf(s, "%c %s -> %s: %s\n", - is_owner ? 'O' : 'T', - owner, target, uwb_rsv_state_str(rsv->state)); - seq_printf(s, " stream: %d type: %s\n", - rsv->stream, uwb_rsv_type_str(rsv->type)); - bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS); - seq_printf(s, " %s\n", buf); - } - - mutex_unlock(&rc->rsvs_mutex); - - return 0; -} - -static int reservations_open(struct inode *inode, struct file *file) -{ - return single_open(file, reservations_print, inode->i_private); -} - -static struct file_operations reservations_fops = { - .open = reservations_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int drp_avail_print(struct seq_file *s, void *p) -{ - struct uwb_rc *rc = s->private; - char buf[72]; - - bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.global, UWB_NUM_MAS); - seq_printf(s, "global: %s\n", buf); - bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.local, UWB_NUM_MAS); - seq_printf(s, "local: %s\n", buf); - bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.pending, UWB_NUM_MAS); - seq_printf(s, "pending: %s\n", buf); - - return 0; -} - -static int drp_avail_open(struct inode *inode, struct file *file) -{ - return single_open(file, drp_avail_print, inode->i_private); -} - -static struct file_operations drp_avail_fops = { - .open = drp_avail_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void uwb_dbg_new_rsv(struct uwb_rsv *rsv) -{ - struct uwb_rc *rc = rsv->rc; - - if (rc->dbg->accept) - uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL); -} - -/** - * uwb_dbg_add_rc - add a debug interface for a radio controller - * @rc: the radio controller - */ -void uwb_dbg_add_rc(struct uwb_rc *rc) -{ - rc->dbg = kzalloc(sizeof(struct uwb_dbg), GFP_KERNEL); - if (rc->dbg == NULL) - return; - - INIT_LIST_HEAD(&rc->dbg->rsvs); - - uwb_pal_init(&rc->dbg->pal); - rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; - uwb_pal_register(rc, &rc->dbg->pal); - if (root_dir) { - rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), - root_dir); - rc->dbg->command_f = debugfs_create_file("command", 0200, - rc->dbg->root_d, rc, - &command_fops); - rc->dbg->reservations_f = debugfs_create_file("reservations", 0444, - rc->dbg->root_d, rc, - &reservations_fops); - rc->dbg->accept_f = debugfs_create_bool("accept", 0644, - rc->dbg->root_d, - &rc->dbg->accept); - rc->dbg->drp_avail_f = debugfs_create_file("drp_avail", 0444, - rc->dbg->root_d, rc, - &drp_avail_fops); - } -} - -/** - * uwb_dbg_add_rc - remove a radio controller's debug interface - * @rc: the radio controller - */ -void uwb_dbg_del_rc(struct uwb_rc *rc) -{ - struct uwb_rsv *rsv, *t; - - if (rc->dbg == NULL) - return; - - list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { - uwb_rsv_destroy(rsv); - } - - uwb_pal_unregister(rc, &rc->dbg->pal); - - if (root_dir) { - debugfs_remove(rc->dbg->drp_avail_f); - debugfs_remove(rc->dbg->accept_f); - debugfs_remove(rc->dbg->reservations_f); - debugfs_remove(rc->dbg->command_f); - debugfs_remove(rc->dbg->root_d); - } -} - -/** - * uwb_dbg_exit - initialize the debug interface sub-module - */ -void uwb_dbg_init(void) -{ - root_dir = debugfs_create_dir("uwb", NULL); -} - -/** - * uwb_dbg_exit - clean-up the debug interface sub-module - */ -void uwb_dbg_exit(void) -{ - debugfs_remove(root_dir); -} diff --git a/trunk/drivers/uwb/uwb-internal.h b/trunk/drivers/uwb/uwb-internal.h deleted file mode 100644 index 2ad307d12961..000000000000 --- a/trunk/drivers/uwb/uwb-internal.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Ultra Wide Band - * UWB internal API - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * This contains most of the internal API for UWB. This is stuff used - * across the stack that of course, is of no interest to the rest. - * - * Some parts might end up going public (like uwb_rc_*())... - */ - -#ifndef __UWB_INTERNAL_H__ -#define __UWB_INTERNAL_H__ - -#include -#include -#include -#include -#include - -struct uwb_beca_e; - -/* General device API */ -extern void uwb_dev_init(struct uwb_dev *uwb_dev); -extern int __uwb_dev_offair(struct uwb_dev *, struct uwb_rc *); -extern int uwb_dev_add(struct uwb_dev *uwb_dev, struct device *parent_dev, - struct uwb_rc *parent_rc); -extern void uwb_dev_rm(struct uwb_dev *uwb_dev); -extern void uwbd_dev_onair(struct uwb_rc *, struct uwb_beca_e *); -extern void uwbd_dev_offair(struct uwb_beca_e *); -void uwb_notify(struct uwb_rc *rc, struct uwb_dev *uwb_dev, enum uwb_notifs event); - -/* General UWB Radio Controller Internal API */ -extern struct uwb_rc *__uwb_rc_try_get(struct uwb_rc *); -static inline struct uwb_rc *__uwb_rc_get(struct uwb_rc *rc) -{ - uwb_dev_get(&rc->uwb_dev); - return rc; -} - -static inline void __uwb_rc_put(struct uwb_rc *rc) -{ - uwb_dev_put(&rc->uwb_dev); -} - -extern int uwb_rc_reset(struct uwb_rc *rc); -extern int uwb_rc_beacon(struct uwb_rc *rc, - int channel, unsigned bpst_offset); -extern int uwb_rc_scan(struct uwb_rc *rc, - unsigned channel, enum uwb_scan_type type, - unsigned bpst_offset); -extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); -extern ssize_t uwb_rc_print_IEs(struct uwb_rc *rc, char *, size_t); -extern void uwb_rc_ie_init(struct uwb_rc *); -extern void uwb_rc_ie_init(struct uwb_rc *); -extern ssize_t uwb_rc_ie_setup(struct uwb_rc *); -extern void uwb_rc_ie_release(struct uwb_rc *); -extern int uwb_rc_ie_add(struct uwb_rc *, - const struct uwb_ie_hdr *, size_t); -extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); - -extern const char *uwb_rc_strerror(unsigned code); - -/* - * Time to wait for a response to an RC command. - * - * Some commands can take a long time to response. e.g., START_BEACON - * may scan for several superframes before joining an existing beacon - * group and this can take around 600 ms. - */ -#define UWB_RC_CMD_TIMEOUT_MS 1000 /* ms */ - -/* - * Notification/Event Handlers - */ - -struct uwb_rc_neh; - -void uwb_rc_neh_create(struct uwb_rc *rc); -void uwb_rc_neh_destroy(struct uwb_rc *rc); - -struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd, - u8 expected_type, u16 expected_event, - uwb_rc_cmd_cb_f cb, void *arg); -void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh); -void uwb_rc_neh_arm(struct uwb_rc *rc, struct uwb_rc_neh *neh); -void uwb_rc_neh_put(struct uwb_rc_neh *neh); - -/* Event size tables */ -extern int uwb_est_create(void); -extern void uwb_est_destroy(void); - - -/* - * UWB Events & management daemon - */ - -/** - * enum uwb_event_type - types of UWB management daemon events - * - * The UWB management daemon (uwbd) can receive two types of events: - * UWB_EVT_TYPE_NOTIF - notification from the radio controller. - * UWB_EVT_TYPE_MSG - a simple message. - */ -enum uwb_event_type { - UWB_EVT_TYPE_NOTIF, - UWB_EVT_TYPE_MSG, -}; - -/** - * struct uwb_event_notif - an event for a radio controller notification - * @size: Size of the buffer (ie: Guaranteed to contain at least - * a full 'struct uwb_rceb') - * @rceb: Pointer to a kmalloced() event payload - */ -struct uwb_event_notif { - size_t size; - struct uwb_rceb *rceb; -}; - -/** - * enum uwb_event_message - an event for a message for asynchronous processing - * - * UWB_EVT_MSG_RESET - reset the radio controller and all PAL hardware. - */ -enum uwb_event_message { - UWB_EVT_MSG_RESET, -}; - -/** - * UWB Event - * @rc: Radio controller that emitted the event (referenced) - * @ts_jiffies: Timestamp, when was it received - * @type: This event's type. - */ -struct uwb_event { - struct list_head list_node; - struct uwb_rc *rc; - unsigned long ts_jiffies; - enum uwb_event_type type; - union { - struct uwb_event_notif notif; - enum uwb_event_message message; - }; -}; - -extern void uwbd_start(void); -extern void uwbd_stop(void); -extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); -extern void uwbd_event_queue(struct uwb_event *); -void uwbd_flush(struct uwb_rc *rc); - -/* UWB event handlers */ -extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); -extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); -extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); -extern int uwbd_evt_handle_rc_bp_slot_change(struct uwb_event *); -extern int uwbd_evt_handle_rc_drp(struct uwb_event *); -extern int uwbd_evt_handle_rc_drp_avail(struct uwb_event *); - -int uwbd_msg_handle_reset(struct uwb_event *evt); - - -/* - * Address management - */ -int uwb_rc_dev_addr_assign(struct uwb_rc *rc); -int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); - -/* - * UWB Beacon Cache - * - * Each beacon we received is kept in a cache--when we receive that - * beacon consistently, that means there is a new device that we have - * to add to the system. - */ - -extern unsigned long beacon_timeout_ms; - -/** Beacon cache list */ -struct uwb_beca { - struct list_head list; - size_t entries; - struct mutex mutex; -}; - -extern struct uwb_beca uwb_beca; - -/** - * Beacon cache entry - * - * @jiffies_refresh: last time a beacon was received that refreshed - * this cache entry. - * @uwb_dev: device connected to this beacon. This pointer is not - * safe, you need to get it with uwb_dev_try_get() - * - * @hits: how many time we have seen this beacon since last time we - * cleared it - */ -struct uwb_beca_e { - struct mutex mutex; - struct kref refcnt; - struct list_head node; - struct uwb_mac_addr *mac_addr; - struct uwb_dev_addr dev_addr; - u8 hits; - unsigned long ts_jiffies; - struct uwb_dev *uwb_dev; - struct uwb_rc_evt_beacon *be; - struct stats lqe_stats, rssi_stats; /* radio statistics */ -}; -struct uwb_beacon_frame; -extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, - char *, size_t); -extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, - struct uwb_beacon_frame *, - unsigned long); - -extern void uwb_bce_kfree(struct kref *_bce); -static inline void uwb_bce_get(struct uwb_beca_e *bce) -{ - kref_get(&bce->refcnt); -} -static inline void uwb_bce_put(struct uwb_beca_e *bce) -{ - kref_put(&bce->refcnt, uwb_bce_kfree); -} -extern void uwb_beca_purge(void); -extern void uwb_beca_release(void); - -struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, - const struct uwb_dev_addr *devaddr); -struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, - const struct uwb_mac_addr *macaddr); - -/* -- UWB Sysfs representation */ -extern struct class uwb_rc_class; -extern struct device_attribute dev_attr_mac_address; -extern struct device_attribute dev_attr_beacon; -extern struct device_attribute dev_attr_scan; - -/* -- DRP Bandwidth allocator: bandwidth allocations, reservations, DRP */ -void uwb_rsv_init(struct uwb_rc *rc); -int uwb_rsv_setup(struct uwb_rc *rc); -void uwb_rsv_cleanup(struct uwb_rc *rc); - -void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); -void uwb_rsv_remove(struct uwb_rsv *rsv); -struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src, - struct uwb_ie_drp *drp_ie); -void uwb_rsv_sched_update(struct uwb_rc *rc); - -void uwb_drp_handle_timeout(struct uwb_rsv *rsv); -int uwb_drp_ie_update(struct uwb_rsv *rsv); -void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie); - -void uwb_drp_avail_init(struct uwb_rc *rc); -int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas); -void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas); -void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas); -void uwb_drp_avail_ie_update(struct uwb_rc *rc); - -/* -- PAL support */ -void uwb_rc_pal_init(struct uwb_rc *rc); - -/* -- Misc */ - -extern ssize_t uwb_mac_frame_hdr_print(char *, size_t, - const struct uwb_mac_frame_hdr *); - -/* -- Debug interface */ -void uwb_dbg_init(void); -void uwb_dbg_exit(void); -void uwb_dbg_add_rc(struct uwb_rc *rc); -void uwb_dbg_del_rc(struct uwb_rc *rc); - -/* Workarounds for version specific stuff */ - -static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) -{ - down(&uwb_dev->dev.sem); -} - -static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev) -{ - up(&uwb_dev->dev.sem); -} - -#endif /* #ifndef __UWB_INTERNAL_H__ */ diff --git a/trunk/drivers/uwb/uwbd.c b/trunk/drivers/uwb/uwbd.c deleted file mode 100644 index 78908416e42c..000000000000 --- a/trunk/drivers/uwb/uwbd.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Ultra Wide Band - * Neighborhood Management Daemon - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * This daemon takes care of maintaing information that describes the - * UWB neighborhood that the radios in this machine can see. It also - * keeps a tab of which devices are visible, makes sure each HC sits - * on a different channel to avoid interfering, etc. - * - * Different drivers (radio controller, device, any API in general) - * communicate with this daemon through an event queue. Daemon wakes - * up, takes a list of events and handles them one by one; handling - * function is extracted from a table based on the event's type and - * subtype. Events are freed only if the handling function says so. - * - * . Lock protecting the event list has to be an spinlock and locked - * with IRQSAVE because it might be called from an interrupt - * context (ie: when events arrive and the notification drops - * down from the ISR). - * - * . UWB radio controller drivers queue events to the daemon using - * uwbd_event_queue(). They just get the event, chew it to make it - * look like UWBD likes it and pass it in a buffer allocated with - * uwb_event_alloc(). - * - * EVENTS - * - * Events have a type, a subtype, a lenght, some other stuff and the - * data blob, which depends on the event. The header is 'struct - * uwb_event'; for payloads, see 'struct uwbd_evt_*'. - * - * EVENT HANDLER TABLES - * - * To find a handling function for an event, the type is used to index - * a subtype-table in the type-table. The subtype-table is indexed - * with the subtype to get the function that handles the event. Start - * with the main type-table 'uwbd_evt_type_handler'. - * - * DEVICES - * - * Devices are created when a bunch of beacons have been received and - * it is stablished that the device has stable radio presence. CREATED - * only, not configured. Devices are ONLY configured when an - * Application-Specific IE Probe is receieved, in which the device - * declares which Protocol ID it groks. Then the device is CONFIGURED - * (and the driver->probe() stuff of the device model is invoked). - * - * Devices are considered disconnected when a certain number of - * beacons are not received in an amount of time. - * - * Handler functions are called normally uwbd_evt_handle_*(). - */ - -#include -#include -#include -#include "uwb-internal.h" - -#define D_LOCAL 1 -#include - - -/** - * UWBD Event handler function signature - * - * Return !0 if the event needs not to be freed (ie the handler - * takes/took care of it). 0 means the daemon code will free the - * event. - * - * @evt->rc is already referenced and guaranteed to exist. See - * uwb_evt_handle(). - */ -typedef int (*uwbd_evt_handler_f)(struct uwb_event *); - -/** - * Properties of a UWBD event - * - * @handler: the function that will handle this event - * @name: text name of event - */ -struct uwbd_event { - uwbd_evt_handler_f handler; - const char *name; -}; - -/** Table of handlers for and properties of the UWBD Radio Control Events */ -static -struct uwbd_event uwbd_events[] = { - [UWB_RC_EVT_BEACON] = { - .handler = uwbd_evt_handle_rc_beacon, - .name = "BEACON_RECEIVED" - }, - [UWB_RC_EVT_BEACON_SIZE] = { - .handler = uwbd_evt_handle_rc_beacon_size, - .name = "BEACON_SIZE_CHANGE" - }, - [UWB_RC_EVT_BPOIE_CHANGE] = { - .handler = uwbd_evt_handle_rc_bpoie_change, - .name = "BPOIE_CHANGE" - }, - [UWB_RC_EVT_BP_SLOT_CHANGE] = { - .handler = uwbd_evt_handle_rc_bp_slot_change, - .name = "BP_SLOT_CHANGE" - }, - [UWB_RC_EVT_DRP_AVAIL] = { - .handler = uwbd_evt_handle_rc_drp_avail, - .name = "DRP_AVAILABILITY_CHANGE" - }, - [UWB_RC_EVT_DRP] = { - .handler = uwbd_evt_handle_rc_drp, - .name = "DRP" - }, - [UWB_RC_EVT_DEV_ADDR_CONFLICT] = { - .handler = uwbd_evt_handle_rc_dev_addr_conflict, - .name = "DEV_ADDR_CONFLICT", - }, -}; - - - -struct uwbd_evt_type_handler { - const char *name; - struct uwbd_event *uwbd_events; - size_t size; -}; - -#define UWBD_EVT_TYPE_HANDLER(n,a) { \ - .name = (n), \ - .uwbd_events = (a), \ - .size = sizeof(a)/sizeof((a)[0]) \ -} - - -/** Table of handlers for each UWBD Event type. */ -static -struct uwbd_evt_type_handler uwbd_evt_type_handlers[] = { - [UWB_RC_CET_GENERAL] = UWBD_EVT_TYPE_HANDLER("RC", uwbd_events) -}; - -static const -size_t uwbd_evt_type_handlers_len = - sizeof(uwbd_evt_type_handlers) / sizeof(uwbd_evt_type_handlers[0]); - -static const struct uwbd_event uwbd_message_handlers[] = { - [UWB_EVT_MSG_RESET] = { - .handler = uwbd_msg_handle_reset, - .name = "reset", - }, -}; - -static DEFINE_MUTEX(uwbd_event_mutex); - -/** - * Handle an URC event passed to the UWB Daemon - * - * @evt: the event to handle - * @returns: 0 if the event can be kfreed, !0 on the contrary - * (somebody else took ownership) [coincidentally, returning - * a <0 errno code will free it :)]. - * - * Looks up the two indirection tables (one for the type, one for the - * subtype) to decide which function handles it and then calls the - * handler. - * - * The event structure passed to the event handler has the radio - * controller in @evt->rc referenced. The reference will be dropped - * once the handler returns, so if it needs it for longer (async), - * it'll need to take another one. - */ -static -int uwbd_event_handle_urc(struct uwb_event *evt) -{ - struct uwbd_evt_type_handler *type_table; - uwbd_evt_handler_f handler; - u8 type, context; - u16 event; - - type = evt->notif.rceb->bEventType; - event = le16_to_cpu(evt->notif.rceb->wEvent); - context = evt->notif.rceb->bEventContext; - - if (type > uwbd_evt_type_handlers_len) { - printk(KERN_ERR "UWBD: event type %u: unknown (too high)\n", type); - return -EINVAL; - } - type_table = &uwbd_evt_type_handlers[type]; - if (type_table->uwbd_events == NULL) { - printk(KERN_ERR "UWBD: event type %u: unknown\n", type); - return -EINVAL; - } - if (event > type_table->size) { - printk(KERN_ERR "UWBD: event %s[%u]: unknown (too high)\n", - type_table->name, event); - return -EINVAL; - } - handler = type_table->uwbd_events[event].handler; - if (handler == NULL) { - printk(KERN_ERR "UWBD: event %s[%u]: unknown\n", type_table->name, event); - return -EINVAL; - } - return (*handler)(evt); -} - -static void uwbd_event_handle_message(struct uwb_event *evt) -{ - struct uwb_rc *rc; - int result; - - rc = evt->rc; - - if (evt->message < 0 || evt->message >= ARRAY_SIZE(uwbd_message_handlers)) { - dev_err(&rc->uwb_dev.dev, "UWBD: invalid message type %d\n", evt->message); - return; - } - - /* If this is a reset event we need to drop the - * uwbd_event_mutex or it deadlocks when the reset handler - * attempts to flush the uwbd events. */ - if (evt->message == UWB_EVT_MSG_RESET) - mutex_unlock(&uwbd_event_mutex); - - result = uwbd_message_handlers[evt->message].handler(evt); - if (result < 0) - dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", - uwbd_message_handlers[evt->message].name, result); - - if (evt->message == UWB_EVT_MSG_RESET) - mutex_lock(&uwbd_event_mutex); -} - -static void uwbd_event_handle(struct uwb_event *evt) -{ - struct uwb_rc *rc; - int should_keep; - - rc = evt->rc; - - if (rc->ready) { - switch (evt->type) { - case UWB_EVT_TYPE_NOTIF: - should_keep = uwbd_event_handle_urc(evt); - if (should_keep <= 0) - kfree(evt->notif.rceb); - break; - case UWB_EVT_TYPE_MSG: - uwbd_event_handle_message(evt); - break; - default: - dev_err(&rc->uwb_dev.dev, "UWBD: invalid event type %d\n", evt->type); - break; - } - } - - __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ -} -/* The UWB Daemon */ - - -/** Daemon's PID: used to decide if we can queue or not */ -static int uwbd_pid; -/** Daemon's task struct for managing the kthread */ -static struct task_struct *uwbd_task; -/** Daemon's waitqueue for waiting for new events */ -static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); -/** Daemon's list of events; we queue/dequeue here */ -static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); -/** Daemon's list lock to protect concurent access */ -static DEFINE_SPINLOCK(uwbd_event_list_lock); - - -/** - * UWB Daemon - * - * Listens to all UWB notifications and takes care to track the state - * of the UWB neighboorhood for the kernel. When we do a run, we - * spinlock, move the list to a private copy and release the - * lock. Hold it as little as possible. Not a conflict: it is - * guaranteed we own the events in the private list. - * - * FIXME: should change so we don't have a 1HZ timer all the time, but - * only if there are devices. - */ -static int uwbd(void *unused) -{ - unsigned long flags; - struct list_head list = LIST_HEAD_INIT(list); - struct uwb_event *evt, *nxt; - int should_stop = 0; - while (1) { - wait_event_interruptible_timeout( - uwbd_wq, - !list_empty(&uwbd_event_list) - || (should_stop = kthread_should_stop()), - HZ); - if (should_stop) - break; - try_to_freeze(); - - mutex_lock(&uwbd_event_mutex); - spin_lock_irqsave(&uwbd_event_list_lock, flags); - list_splice_init(&uwbd_event_list, &list); - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); - list_for_each_entry_safe(evt, nxt, &list, list_node) { - list_del(&evt->list_node); - uwbd_event_handle(evt); - kfree(evt); - } - mutex_unlock(&uwbd_event_mutex); - - uwb_beca_purge(); /* Purge devices that left */ - } - return 0; -} - - -/** Start the UWB daemon */ -void uwbd_start(void) -{ - uwbd_task = kthread_run(uwbd, NULL, "uwbd"); - if (uwbd_task == NULL) - printk(KERN_ERR "UWB: Cannot start management daemon; " - "UWB won't work\n"); - else - uwbd_pid = uwbd_task->pid; -} - -/* Stop the UWB daemon and free any unprocessed events */ -void uwbd_stop(void) -{ - unsigned long flags; - struct uwb_event *evt, *nxt; - kthread_stop(uwbd_task); - spin_lock_irqsave(&uwbd_event_list_lock, flags); - uwbd_pid = 0; - list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { - if (evt->type == UWB_EVT_TYPE_NOTIF) - kfree(evt->notif.rceb); - kfree(evt); - } - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); - uwb_beca_release(); -} - -/* - * Queue an event for the management daemon - * - * When some lower layer receives an event, it uses this function to - * push it forward to the UWB daemon. - * - * Once you pass the event, you don't own it any more, but the daemon - * does. It will uwb_event_free() it when done, so make sure you - * uwb_event_alloc()ed it or bad things will happen. - * - * If the daemon is not running, we just free the event. - */ -void uwbd_event_queue(struct uwb_event *evt) -{ - unsigned long flags; - spin_lock_irqsave(&uwbd_event_list_lock, flags); - if (uwbd_pid != 0) { - list_add(&evt->list_node, &uwbd_event_list); - wake_up_all(&uwbd_wq); - } else { - __uwb_rc_put(evt->rc); - if (evt->type == UWB_EVT_TYPE_NOTIF) - kfree(evt->notif.rceb); - kfree(evt); - } - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); - return; -} - -void uwbd_flush(struct uwb_rc *rc) -{ - struct uwb_event *evt, *nxt; - - mutex_lock(&uwbd_event_mutex); - - spin_lock_irq(&uwbd_event_list_lock); - list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { - if (evt->rc == rc) { - __uwb_rc_put(rc); - list_del(&evt->list_node); - if (evt->type == UWB_EVT_TYPE_NOTIF) - kfree(evt->notif.rceb); - kfree(evt); - } - } - spin_unlock_irq(&uwbd_event_list_lock); - - mutex_unlock(&uwbd_event_mutex); -} diff --git a/trunk/drivers/uwb/whc-rc.c b/trunk/drivers/uwb/whc-rc.c deleted file mode 100644 index 1711deadb114..000000000000 --- a/trunk/drivers/uwb/whc-rc.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Wireless Host Controller: Radio Control Interface (WHCI v0.95[2.3]) - * Radio Control command/event transport to the UWB stack - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Initialize and hook up the Radio Control interface. - * - * For each device probed, creates an 'struct whcrc' which contains - * just the representation of the UWB Radio Controller, and the logic - * for reading notifications and passing them to the UWB Core. - * - * So we initialize all of those, register the UWB Radio Controller - * and setup the notification/event handle to pipe the notifications - * to the UWB management Daemon. - * - * Once uwb_rc_add() is called, the UWB stack takes control, resets - * the radio and readies the device to take commands the UWB - * API/user-space. - * - * Note this driver is just a transport driver; the commands are - * formed at the UWB stack and given to this driver who will deliver - * them to the hw and transfer the replies/notifications back to the - * UWB stack through the UWB daemon (UWBD). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "uwb-internal.h" - -#define D_LOCAL 0 -#include - -/** - * Descriptor for an instance of the UWB Radio Control Driver that - * attaches to the URC interface of the WHCI PCI card. - * - * Unless there is a lock specific to the 'data members', all access - * is protected by uwb_rc->mutex. - */ -struct whcrc { - struct umc_dev *umc_dev; - struct uwb_rc *uwb_rc; /* UWB host controller */ - - unsigned long area; - void __iomem *rc_base; - size_t rc_len; - spinlock_t irq_lock; - - void *evt_buf, *cmd_buf; - dma_addr_t evt_dma_buf, cmd_dma_buf; - wait_queue_head_t cmd_wq; - struct work_struct event_work; -}; - -/** - * Execute an UWB RC command on WHCI/RC - * - * @rc: Instance of a Radio Controller that is a whcrc - * @cmd: Buffer containing the RCCB and payload to execute - * @cmd_size: Size of the command buffer. - * - * We copy the command into whcrc->cmd_buf (as it is pretty and - * aligned`and physically contiguous) and then press the right keys in - * the controller's URCCMD register to get it to read it. We might - * have to wait for the cmd_sem to be open to us. - * - * NOTE: rc's mutex has to be locked - */ -static int whcrc_cmd(struct uwb_rc *uwb_rc, - const struct uwb_rccb *cmd, size_t cmd_size) -{ - int result = 0; - struct whcrc *whcrc = uwb_rc->priv; - struct device *dev = &whcrc->umc_dev->dev; - u32 urccmd; - - d_fnstart(3, dev, "(%p, %p, %zu)\n", uwb_rc, cmd, cmd_size); - might_sleep(); - - if (cmd_size >= 4096) { - result = -E2BIG; - goto error; - } - - /* - * If the URC is halted, then the hardware has reset itself. - * Attempt to recover by restarting the device and then return - * an error as it's likely that the current command isn't - * valid for a newly started RC. - */ - if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) { - dev_err(dev, "requesting reset of halted radio controller\n"); - uwb_rc_reset_all(uwb_rc); - result = -EIO; - goto error; - } - - result = wait_event_timeout(whcrc->cmd_wq, - !(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2); - if (result == 0) { - dev_err(dev, "device is not ready to execute commands\n"); - result = -ETIMEDOUT; - goto error; - } - - memmove(whcrc->cmd_buf, cmd, cmd_size); - le_writeq(whcrc->cmd_dma_buf, whcrc->rc_base + URCCMDADDR); - - spin_lock(&whcrc->irq_lock); - urccmd = le_readl(whcrc->rc_base + URCCMD); - urccmd &= ~(URCCMD_EARV | URCCMD_SIZE_MASK); - le_writel(urccmd | URCCMD_ACTIVE | URCCMD_IWR | cmd_size, - whcrc->rc_base + URCCMD); - spin_unlock(&whcrc->irq_lock); - -error: - d_fnend(3, dev, "(%p, %p, %zu) = %d\n", - uwb_rc, cmd, cmd_size, result); - return result; -} - -static int whcrc_reset(struct uwb_rc *rc) -{ - struct whcrc *whcrc = rc->priv; - - return umc_controller_reset(whcrc->umc_dev); -} - -/** - * Reset event reception mechanism and tell hw we are ready to get more - * - * We have read all the events in the event buffer, so we are ready to - * reset it to the beginning. - * - * This is only called during initialization or after an event buffer - * has been retired. This means we can be sure that event processing - * is disabled and it's safe to update the URCEVTADDR register. - * - * There's no need to wait for the event processing to start as the - * URC will not clear URCCMD_ACTIVE until (internal) event buffer - * space is available. - */ -static -void whcrc_enable_events(struct whcrc *whcrc) -{ - struct device *dev = &whcrc->umc_dev->dev; - u32 urccmd; - - d_fnstart(4, dev, "(whcrc %p)\n", whcrc); - - le_writeq(whcrc->evt_dma_buf, whcrc->rc_base + URCEVTADDR); - - spin_lock(&whcrc->irq_lock); - urccmd = le_readl(whcrc->rc_base + URCCMD) & ~URCCMD_ACTIVE; - le_writel(urccmd | URCCMD_EARV, whcrc->rc_base + URCCMD); - spin_unlock(&whcrc->irq_lock); - - d_fnend(4, dev, "(whcrc %p) = void\n", whcrc); -} - -static void whcrc_event_work(struct work_struct *work) -{ - struct whcrc *whcrc = container_of(work, struct whcrc, event_work); - struct device *dev = &whcrc->umc_dev->dev; - size_t size; - u64 urcevtaddr; - - urcevtaddr = le_readq(whcrc->rc_base + URCEVTADDR); - size = urcevtaddr & URCEVTADDR_OFFSET_MASK; - - d_printf(3, dev, "received %zu octet event\n", size); - d_dump(4, dev, whcrc->evt_buf, size > 32 ? 32 : size); - - uwb_rc_neh_grok(whcrc->uwb_rc, whcrc->evt_buf, size); - whcrc_enable_events(whcrc); -} - -/** - * Catch interrupts? - * - * We ack inmediately (and expect the hw to do the right thing and - * raise another IRQ if things have changed :) - */ -static -irqreturn_t whcrc_irq_cb(int irq, void *_whcrc) -{ - struct whcrc *whcrc = _whcrc; - struct device *dev = &whcrc->umc_dev->dev; - u32 urcsts; - - urcsts = le_readl(whcrc->rc_base + URCSTS); - if (!(urcsts & URCSTS_INT_MASK)) - return IRQ_NONE; - le_writel(urcsts & URCSTS_INT_MASK, whcrc->rc_base + URCSTS); - - d_printf(4, dev, "acked 0x%08x, urcsts 0x%08x\n", - le_readl(whcrc->rc_base + URCSTS), urcsts); - - if (urcsts & URCSTS_HSE) { - dev_err(dev, "host system error -- hardware halted\n"); - /* FIXME: do something sensible here */ - goto out; - } - if (urcsts & URCSTS_ER) { - d_printf(3, dev, "ER: event ready\n"); - schedule_work(&whcrc->event_work); - } - if (urcsts & URCSTS_RCI) { - d_printf(3, dev, "RCI: ready to execute another command\n"); - wake_up_all(&whcrc->cmd_wq); - } -out: - return IRQ_HANDLED; -} - - -/** - * Initialize a UMC RC interface: map regions, get (shared) IRQ - */ -static -int whcrc_setup_rc_umc(struct whcrc *whcrc) -{ - int result = 0; - struct device *dev = &whcrc->umc_dev->dev; - struct umc_dev *umc_dev = whcrc->umc_dev; - - whcrc->area = umc_dev->resource.start; - whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1; - result = -EBUSY; - if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) - == NULL) { - dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n", - whcrc->rc_len, whcrc->area, result); - goto error_request_region; - } - - whcrc->rc_base = ioremap_nocache(whcrc->area, whcrc->rc_len); - if (whcrc->rc_base == NULL) { - dev_err(dev, "can't ioremap registers (%zu bytes @ 0x%lx): %d\n", - whcrc->rc_len, whcrc->area, result); - goto error_ioremap_nocache; - } - - result = request_irq(umc_dev->irq, whcrc_irq_cb, IRQF_SHARED, - KBUILD_MODNAME, whcrc); - if (result < 0) { - dev_err(dev, "can't allocate IRQ %d: %d\n", - umc_dev->irq, result); - goto error_request_irq; - } - - result = -ENOMEM; - whcrc->cmd_buf = dma_alloc_coherent(&umc_dev->dev, PAGE_SIZE, - &whcrc->cmd_dma_buf, GFP_KERNEL); - if (whcrc->cmd_buf == NULL) { - dev_err(dev, "Can't allocate cmd transfer buffer\n"); - goto error_cmd_buffer; - } - - whcrc->evt_buf = dma_alloc_coherent(&umc_dev->dev, PAGE_SIZE, - &whcrc->evt_dma_buf, GFP_KERNEL); - if (whcrc->evt_buf == NULL) { - dev_err(dev, "Can't allocate evt transfer buffer\n"); - goto error_evt_buffer; - } - d_printf(3, dev, "UWB RC Interface: %zu bytes at 0x%p, irq %u\n", - whcrc->rc_len, whcrc->rc_base, umc_dev->irq); - return 0; - -error_evt_buffer: - dma_free_coherent(&umc_dev->dev, PAGE_SIZE, whcrc->cmd_buf, - whcrc->cmd_dma_buf); -error_cmd_buffer: - free_irq(umc_dev->irq, whcrc); -error_request_irq: - iounmap(whcrc->rc_base); -error_ioremap_nocache: - release_mem_region(whcrc->area, whcrc->rc_len); -error_request_region: - return result; -} - - -/** - * Release RC's UMC resources - */ -static -void whcrc_release_rc_umc(struct whcrc *whcrc) -{ - struct umc_dev *umc_dev = whcrc->umc_dev; - - dma_free_coherent(&umc_dev->dev, PAGE_SIZE, whcrc->evt_buf, - whcrc->evt_dma_buf); - dma_free_coherent(&umc_dev->dev, PAGE_SIZE, whcrc->cmd_buf, - whcrc->cmd_dma_buf); - free_irq(umc_dev->irq, whcrc); - iounmap(whcrc->rc_base); - release_mem_region(whcrc->area, whcrc->rc_len); -} - - -/** - * whcrc_start_rc - start a WHCI radio controller - * @whcrc: the radio controller to start - * - * Reset the UMC device, start the radio controller, enable events and - * finally enable interrupts. - */ -static int whcrc_start_rc(struct uwb_rc *rc) -{ - struct whcrc *whcrc = rc->priv; - int result = 0; - struct device *dev = &whcrc->umc_dev->dev; - unsigned long start, duration; - - /* Reset the thing */ - le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); - if (d_test(3)) - start = jiffies; - if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, - 5000, "device to reset at init") < 0) { - result = -EBUSY; - goto error; - } else if (d_test(3)) { - duration = jiffies - start; - if (duration > msecs_to_jiffies(40)) - dev_err(dev, "Device took %ums to " - "reset. MAX expected: 40ms\n", - jiffies_to_msecs(duration)); - } - - /* Set the event buffer, start the controller (enable IRQs later) */ - le_writel(0, whcrc->rc_base + URCINTR); - le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); - result = -ETIMEDOUT; - if (d_test(3)) - start = jiffies; - if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, - 5000, "device to start") < 0) - goto error; - if (d_test(3)) { - duration = jiffies - start; - if (duration > msecs_to_jiffies(40)) - dev_err(dev, "Device took %ums to start. " - "MAX expected: 40ms\n", - jiffies_to_msecs(duration)); - } - whcrc_enable_events(whcrc); - result = 0; - le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); -error: - return result; -} - - -/** - * whcrc_stop_rc - stop a WHCI radio controller - * @whcrc: the radio controller to stop - * - * Disable interrupts and cancel any pending event processing work - * before clearing the Run/Stop bit. - */ -static -void whcrc_stop_rc(struct uwb_rc *rc) -{ - struct whcrc *whcrc = rc->priv; - struct umc_dev *umc_dev = whcrc->umc_dev; - - le_writel(0, whcrc->rc_base + URCINTR); - cancel_work_sync(&whcrc->event_work); - - le_writel(0, whcrc->rc_base + URCCMD); - whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, - URCSTS_HALTED, 0, 40, "URCSTS.HALTED"); -} - -static void whcrc_init(struct whcrc *whcrc) -{ - spin_lock_init(&whcrc->irq_lock); - init_waitqueue_head(&whcrc->cmd_wq); - INIT_WORK(&whcrc->event_work, whcrc_event_work); -} - -/** - * Initialize the radio controller. - * - * NOTE: we setup whcrc->uwb_rc before calling uwb_rc_add(); in the - * IRQ handler we use that to determine if the hw is ready to - * handle events. Looks like a race condition, but it really is - * not. - */ -static -int whcrc_probe(struct umc_dev *umc_dev) -{ - int result; - struct uwb_rc *uwb_rc; - struct whcrc *whcrc; - struct device *dev = &umc_dev->dev; - - d_fnstart(3, dev, "(umc_dev %p)\n", umc_dev); - result = -ENOMEM; - uwb_rc = uwb_rc_alloc(); - if (uwb_rc == NULL) { - dev_err(dev, "unable to allocate RC instance\n"); - goto error_rc_alloc; - } - whcrc = kzalloc(sizeof(*whcrc), GFP_KERNEL); - if (whcrc == NULL) { - dev_err(dev, "unable to allocate WHC-RC instance\n"); - goto error_alloc; - } - whcrc_init(whcrc); - whcrc->umc_dev = umc_dev; - - result = whcrc_setup_rc_umc(whcrc); - if (result < 0) { - dev_err(dev, "Can't setup RC UMC interface: %d\n", result); - goto error_setup_rc_umc; - } - whcrc->uwb_rc = uwb_rc; - - uwb_rc->owner = THIS_MODULE; - uwb_rc->cmd = whcrc_cmd; - uwb_rc->reset = whcrc_reset; - uwb_rc->start = whcrc_start_rc; - uwb_rc->stop = whcrc_stop_rc; - - result = uwb_rc_add(uwb_rc, dev, whcrc); - if (result < 0) - goto error_rc_add; - umc_set_drvdata(umc_dev, whcrc); - d_fnend(3, dev, "(umc_dev %p) = 0\n", umc_dev); - return 0; - -error_rc_add: - whcrc_release_rc_umc(whcrc); -error_setup_rc_umc: - kfree(whcrc); -error_alloc: - uwb_rc_put(uwb_rc); -error_rc_alloc: - d_fnend(3, dev, "(umc_dev %p) = %d\n", umc_dev, result); - return result; -} - -/** - * Clean up the radio control resources - * - * When we up the command semaphore, everybody possibly held trying to - * execute a command should be granted entry and then they'll see the - * host is quiescing and up it (so it will chain to the next waiter). - * This should not happen (in any case), as we can only remove when - * there are no handles open... - */ -static void whcrc_remove(struct umc_dev *umc_dev) -{ - struct whcrc *whcrc = umc_get_drvdata(umc_dev); - struct uwb_rc *uwb_rc = whcrc->uwb_rc; - - umc_set_drvdata(umc_dev, NULL); - uwb_rc_rm(uwb_rc); - whcrc_release_rc_umc(whcrc); - kfree(whcrc); - uwb_rc_put(uwb_rc); - d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); -} - -/* PCI device ID's that we handle [so it gets loaded] */ -static struct pci_device_id whcrc_id_table[] = { - { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, - { /* empty last entry */ } -}; -MODULE_DEVICE_TABLE(pci, whcrc_id_table); - -static struct umc_driver whcrc_driver = { - .name = "whc-rc", - .cap_id = UMC_CAP_ID_WHCI_RC, - .probe = whcrc_probe, - .remove = whcrc_remove, -}; - -static int __init whcrc_driver_init(void) -{ - return umc_driver_register(&whcrc_driver); -} -module_init(whcrc_driver_init); - -static void __exit whcrc_driver_exit(void) -{ - umc_driver_unregister(&whcrc_driver); -} -module_exit(whcrc_driver_exit); - -MODULE_AUTHOR("Inaky Perez-Gonzalez "); -MODULE_DESCRIPTION("Wireless Host Controller Radio Control Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/whci.c b/trunk/drivers/uwb/whci.c deleted file mode 100644 index 3df2388f908f..000000000000 --- a/trunk/drivers/uwb/whci.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * WHCI UWB Multi-interface Controller enumerator. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * This file is released under the GNU GPL v2. - */ -#include -#include -#include -#include -#include -#include - -struct whci_card { - struct pci_dev *pci; - void __iomem *uwbbase; - u8 n_caps; - struct umc_dev *devs[0]; -}; - - -/* Fix faulty HW :( */ -static -u64 whci_capdata_quirks(struct whci_card *card, u64 capdata) -{ - u64 capdata_orig = capdata; - struct pci_dev *pci_dev = card->pci; - if (pci_dev->vendor == PCI_VENDOR_ID_INTEL - && (pci_dev->device == 0x0c3b || pci_dev->device == 0004) - && pci_dev->class == 0x0d1010) { - switch (UWBCAPDATA_TO_CAP_ID(capdata)) { - /* WLP capability has 0x100 bytes of aperture */ - case 0x80: - capdata |= 0x40 << 8; break; - /* WUSB capability has 0x80 bytes of aperture - * and ID is 1 */ - case 0x02: - capdata &= ~0xffff; - capdata |= 0x2001; - break; - } - } - if (capdata_orig != capdata) - dev_warn(&pci_dev->dev, - "PCI v%04x d%04x c%06x#%02x: " - "corrected capdata from %016Lx to %016Lx\n", - pci_dev->vendor, pci_dev->device, pci_dev->class, - (unsigned)UWBCAPDATA_TO_CAP_ID(capdata), - (unsigned long long)capdata_orig, - (unsigned long long)capdata); - return capdata; -} - - -/** - * whci_wait_for - wait for a WHCI register to be set - * - * Polls (for at most @max_ms ms) until '*@reg & @mask == @result'. - */ -int whci_wait_for(struct device *dev, u32 __iomem *reg, u32 mask, u32 result, - unsigned long max_ms, const char *tag) -{ - unsigned t = 0; - u32 val; - for (;;) { - val = le_readl(reg); - if ((val & mask) == result) - break; - msleep(10); - if (t >= max_ms) { - dev_err(dev, "timed out waiting for %s ", tag); - return -ETIMEDOUT; - } - t += 10; - } - return 0; -} -EXPORT_SYMBOL_GPL(whci_wait_for); - - -/* - * NOTE: the capinfo and capdata registers are slightly different - * (size and cap-id fields). So for cap #0, we need to fill - * in. Size comes from the size of the register block - * (statically calculated); cap_id comes from nowhere, we use - * zero, that is reserved, for the radio controller, because - * none was defined at the spec level. - */ -static int whci_add_cap(struct whci_card *card, int n) -{ - struct umc_dev *umc; - u64 capdata; - int bar, err; - - umc = umc_device_create(&card->pci->dev, n); - if (umc == NULL) - return -ENOMEM; - - capdata = le_readq(card->uwbbase + UWBCAPDATA(n)); - - bar = UWBCAPDATA_TO_BAR(capdata) << 1; - - capdata = whci_capdata_quirks(card, capdata); - /* Capability 0 is the radio controller. It's size is 32 - * bytes (WHCI0.95[2.3, T2-9]). */ - umc->version = UWBCAPDATA_TO_VERSION(capdata); - umc->cap_id = n == 0 ? 0 : UWBCAPDATA_TO_CAP_ID(capdata); - umc->bar = bar; - umc->resource.start = pci_resource_start(card->pci, bar) - + UWBCAPDATA_TO_OFFSET(capdata); - umc->resource.end = umc->resource.start - + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; - umc->resource.name = umc->dev.bus_id; - umc->resource.flags = card->pci->resource[bar].flags; - umc->resource.parent = &card->pci->resource[bar]; - umc->irq = card->pci->irq; - - err = umc_device_register(umc); - if (err < 0) - goto error; - card->devs[n] = umc; - return 0; - -error: - kfree(umc); - return err; -} - -static void whci_del_cap(struct whci_card *card, int n) -{ - struct umc_dev *umc = card->devs[n]; - - if (umc != NULL) - umc_device_unregister(umc); -} - -static int whci_n_caps(struct pci_dev *pci) -{ - void __iomem *uwbbase; - u64 capinfo; - - uwbbase = pci_iomap(pci, 0, 8); - if (!uwbbase) - return -ENOMEM; - capinfo = le_readq(uwbbase + UWBCAPINFO); - pci_iounmap(pci, uwbbase); - - return UWBCAPINFO_TO_N_CAPS(capinfo); -} - -static int whci_probe(struct pci_dev *pci, const struct pci_device_id *id) -{ - struct whci_card *card; - int err, n_caps, n; - - err = pci_enable_device(pci); - if (err < 0) - goto error; - pci_enable_msi(pci); - pci_set_master(pci); - err = -ENXIO; - if (!pci_set_dma_mask(pci, DMA_64BIT_MASK)) - pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); - else if (!pci_set_dma_mask(pci, DMA_32BIT_MASK)) - pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK); - else - goto error_dma; - - err = n_caps = whci_n_caps(pci); - if (n_caps < 0) - goto error_ncaps; - - err = -ENOMEM; - card = kzalloc(sizeof(struct whci_card) - + sizeof(struct whci_dev *) * (n_caps + 1), - GFP_KERNEL); - if (card == NULL) - goto error_kzalloc; - card->pci = pci; - card->n_caps = n_caps; - - err = -EBUSY; - if (!request_mem_region(pci_resource_start(pci, 0), - UWBCAPDATA_SIZE(card->n_caps), - "whci (capability data)")) - goto error_request_memregion; - err = -ENOMEM; - card->uwbbase = pci_iomap(pci, 0, UWBCAPDATA_SIZE(card->n_caps)); - if (!card->uwbbase) - goto error_iomap; - - /* Add each capability. */ - for (n = 0; n <= card->n_caps; n++) { - err = whci_add_cap(card, n); - if (err < 0 && n == 0) { - dev_err(&pci->dev, "cannot bind UWB radio controller:" - " %d\n", err); - goto error_bind; - } - if (err < 0) - dev_warn(&pci->dev, "warning: cannot bind capability " - "#%u: %d\n", n, err); - } - pci_set_drvdata(pci, card); - return 0; - -error_bind: - pci_iounmap(pci, card->uwbbase); -error_iomap: - release_mem_region(pci_resource_start(pci, 0), UWBCAPDATA_SIZE(card->n_caps)); -error_request_memregion: - kfree(card); -error_kzalloc: -error_ncaps: -error_dma: - pci_disable_msi(pci); - pci_disable_device(pci); -error: - return err; -} - -static void whci_remove(struct pci_dev *pci) -{ - struct whci_card *card = pci_get_drvdata(pci); - int n; - - pci_set_drvdata(pci, NULL); - /* Unregister each capability in reverse (so the master device - * is unregistered last). */ - for (n = card->n_caps; n >= 0 ; n--) - whci_del_cap(card, n); - pci_iounmap(pci, card->uwbbase); - release_mem_region(pci_resource_start(pci, 0), UWBCAPDATA_SIZE(card->n_caps)); - kfree(card); - pci_disable_msi(pci); - pci_disable_device(pci); -} - -static struct pci_device_id whci_id_table[] = { - { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, - { 0 }, -}; -MODULE_DEVICE_TABLE(pci, whci_id_table); - - -static struct pci_driver whci_driver = { - .name = "whci", - .id_table = whci_id_table, - .probe = whci_probe, - .remove = whci_remove, -}; - -static int __init whci_init(void) -{ - return pci_register_driver(&whci_driver); -} - -static void __exit whci_exit(void) -{ - pci_unregister_driver(&whci_driver); -} - -module_init(whci_init); -module_exit(whci_exit); - -MODULE_DESCRIPTION("WHCI UWB Multi-interface Controller enumerator"); -MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/wlp/Makefile b/trunk/drivers/uwb/wlp/Makefile deleted file mode 100644 index c72c11db5b1b..000000000000 --- a/trunk/drivers/uwb/wlp/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-$(CONFIG_UWB_WLP) := wlp.o - -wlp-objs := \ - driver.o \ - eda.o \ - messages.o \ - sysfs.o \ - txrx.o \ - wlp-lc.o \ - wss-lc.o diff --git a/trunk/drivers/uwb/wlp/driver.c b/trunk/drivers/uwb/wlp/driver.c deleted file mode 100644 index cb8d699b6a67..000000000000 --- a/trunk/drivers/uwb/wlp/driver.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Life cycle of WLP substack - * - * FIXME: Docs - */ - -#include - -static int __init wlp_subsys_init(void) -{ - return 0; -} -module_init(wlp_subsys_init); - -static void __exit wlp_subsys_exit(void) -{ - return; -} -module_exit(wlp_subsys_exit); - -MODULE_AUTHOR("Reinette Chatre "); -MODULE_DESCRIPTION("WiMedia Logical Link Control Protocol (WLP)"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/uwb/wlp/eda.c b/trunk/drivers/uwb/wlp/eda.c deleted file mode 100644 index cdfe8dfc4340..000000000000 --- a/trunk/drivers/uwb/wlp/eda.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * WUSB Wire Adapter: WLP interface - * Ethernet to device address cache - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * We need to be able to map ethernet addresses to device addresses - * and back because there is not explicit relationship between the eth - * addresses used in the ETH frames and the device addresses (no, it - * would not have been simpler to force as ETH address the MBOA MAC - * address...no, not at all :). - * - * A device has one MBOA MAC address and one device address. It is possible - * for a device to have more than one virtual MAC address (although a - * virtual address can be the same as the MBOA MAC address). The device - * address is guaranteed to be unique among the devices in the extended - * beacon group (see ECMA 17.1.1). We thus use the device address as index - * to this cache. We do allow searching based on virtual address as this - * is how Ethernet frames will be addressed. - * - * We need to support virtual EUI-48. Although, right now the virtual - * EUI-48 will always be the same as the MAC SAP address. The EDA cache - * entry thus contains a MAC SAP address as well as the virtual address - * (used to map the network stack address to a neighbor). When we move - * to support more than one virtual MAC on a host then this organization - * will have to change. Perhaps a neighbor has a list of WSSs, each with a - * tag and virtual EUI-48. - * - * On data transmission - * it is used to determine if the neighbor is connected and what WSS it - * belongs to. With this we know what tag to add to the WLP frame. Storing - * the WSS in the EDA cache may be overkill because we only support one - * WSS. Hopefully we will support more than one WSS at some point. - * On data reception it is used to determine the WSS based on - * the tag and address of the transmitting neighbor. - */ - -#define D_LOCAL 5 -#include -#include -#include -#include -#include "wlp-internal.h" - - -/* FIXME: cache is not purged, only on device close */ - -/* FIXME: does not scale, change to dynamic array */ - -/* - * Initialize the EDA cache - * - * @returns 0 if ok, < 0 errno code on error - * - * Call when the interface is being brought up - * - * NOTE: Keep it as a separate function as the implementation will - * change and be more complex. - */ -void wlp_eda_init(struct wlp_eda *eda) -{ - INIT_LIST_HEAD(&eda->cache); - spin_lock_init(&eda->lock); -} - -/* - * Release the EDA cache - * - * @returns 0 if ok, < 0 errno code on error - * - * Called when the interface is brought down - */ -void wlp_eda_release(struct wlp_eda *eda) -{ - unsigned long flags; - struct wlp_eda_node *itr, *next; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry_safe(itr, next, &eda->cache, list_node) { - list_del(&itr->list_node); - kfree(itr); - } - spin_unlock_irqrestore(&eda->lock, flags); -} - -/* - * Add an address mapping - * - * @returns 0 if ok, < 0 errno code on error - * - * An address mapping is initially created when the neighbor device is seen - * for the first time (it is "onair"). At this time the neighbor is not - * connected or associated with a WSS so we only populate the Ethernet and - * Device address fields. - * - */ -int wlp_eda_create_node(struct wlp_eda *eda, - const unsigned char eth_addr[ETH_ALEN], - const struct uwb_dev_addr *dev_addr) -{ - int result = 0; - struct wlp_eda_node *itr; - unsigned long flags; - - BUG_ON(dev_addr == NULL || eth_addr == NULL); - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(itr, &eda->cache, list_node) { - if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) { - printk(KERN_ERR "EDA cache already contains entry " - "for neighbor %02x:%02x\n", - dev_addr->data[1], dev_addr->data[0]); - result = -EEXIST; - goto out_unlock; - } - } - itr = kzalloc(sizeof(*itr), GFP_ATOMIC); - if (itr != NULL) { - memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr)); - itr->dev_addr = *dev_addr; - list_add(&itr->list_node, &eda->cache); - } else - result = -ENOMEM; -out_unlock: - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -/* - * Remove entry from EDA cache - * - * This is done when the device goes off air. - */ -void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr) -{ - struct wlp_eda_node *itr, *next; - unsigned long flags; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry_safe(itr, next, &eda->cache, list_node) { - if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) { - list_del(&itr->list_node); - kfree(itr); - break; - } - } - spin_unlock_irqrestore(&eda->lock, flags); -} - -/* - * Update an address mapping - * - * @returns 0 if ok, < 0 errno code on error - */ -int wlp_eda_update_node(struct wlp_eda *eda, - const struct uwb_dev_addr *dev_addr, - struct wlp_wss *wss, - const unsigned char virt_addr[ETH_ALEN], - const u8 tag, const enum wlp_wss_connect state) -{ - int result = -ENOENT; - struct wlp_eda_node *itr; - unsigned long flags; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(itr, &eda->cache, list_node) { - if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) { - /* Found it, update it */ - itr->wss = wss; - memcpy(itr->virt_addr, virt_addr, - sizeof(itr->virt_addr)); - itr->tag = tag; - itr->state = state; - result = 0; - goto out_unlock; - } - } - /* Not found */ -out_unlock: - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -/* - * Update only state field of an address mapping - * - * @returns 0 if ok, < 0 errno code on error - */ -int wlp_eda_update_node_state(struct wlp_eda *eda, - const struct uwb_dev_addr *dev_addr, - const enum wlp_wss_connect state) -{ - int result = -ENOENT; - struct wlp_eda_node *itr; - unsigned long flags; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(itr, &eda->cache, list_node) { - if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) { - /* Found it, update it */ - itr->state = state; - result = 0; - goto out_unlock; - } - } - /* Not found */ -out_unlock: - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -/* - * Return contents of EDA cache entry - * - * @dev_addr: index to EDA cache - * @eda_entry: pointer to where contents of EDA cache will be copied - */ -int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr, - struct wlp_eda_node *eda_entry) -{ - int result = -ENOENT; - struct wlp_eda_node *itr; - unsigned long flags; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(itr, &eda->cache, list_node) { - if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) { - *eda_entry = *itr; - result = 0; - goto out_unlock; - } - } - /* Not found */ -out_unlock: - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -/* - * Execute function for every element in the cache - * - * @function: function to execute on element of cache (must be atomic) - * @priv: private data of function - * @returns: result of first function that failed, or last function - * executed if no function failed. - * - * Stop executing when function returns error for any element in cache. - * - * IMPORTANT: We are using a spinlock here: the function executed on each - * element has to be atomic. - */ -int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function, - void *priv) -{ - int result = 0; - struct wlp *wlp = container_of(eda, struct wlp, eda); - struct wlp_eda_node *entry; - unsigned long flags; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(entry, &eda->cache, list_node) { - result = (*function)(wlp, entry, priv); - if (result < 0) - break; - } - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -/* - * Execute function for single element in the cache (return dev addr) - * - * @virt_addr: index into EDA cache used to determine which element to - * execute the function on - * @dev_addr: device address of element in cache will be returned using - * @dev_addr - * @function: function to execute on element of cache (must be atomic) - * @priv: private data of function - * @returns: result of function - * - * IMPORTANT: We are using a spinlock here: the function executed on the - * element has to be atomic. - */ -int wlp_eda_for_virtual(struct wlp_eda *eda, - const unsigned char virt_addr[ETH_ALEN], - struct uwb_dev_addr *dev_addr, - wlp_eda_for_each_f function, - void *priv) -{ - int result = 0; - struct wlp *wlp = container_of(eda, struct wlp, eda); - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_eda_node *itr; - unsigned long flags; - int found = 0; - - spin_lock_irqsave(&eda->lock, flags); - list_for_each_entry(itr, &eda->cache, list_node) { - if (!memcmp(itr->virt_addr, virt_addr, - sizeof(itr->virt_addr))) { - d_printf(6, dev, "EDA: looking for " - "%02x:%02x:%02x:%02x:%02x:%02x hit %02x:%02x " - "wss %p tag 0x%02x state %u\n", - virt_addr[0], virt_addr[1], - virt_addr[2], virt_addr[3], - virt_addr[4], virt_addr[5], - itr->dev_addr.data[1], - itr->dev_addr.data[0], itr->wss, - itr->tag, itr->state); - result = (*function)(wlp, itr, priv); - *dev_addr = itr->dev_addr; - found = 1; - break; - } else - d_printf(6, dev, "EDA: looking for " - "%02x:%02x:%02x:%02x:%02x:%02x " - "against " - "%02x:%02x:%02x:%02x:%02x:%02x miss\n", - virt_addr[0], virt_addr[1], - virt_addr[2], virt_addr[3], - virt_addr[4], virt_addr[5], - itr->virt_addr[0], itr->virt_addr[1], - itr->virt_addr[2], itr->virt_addr[3], - itr->virt_addr[4], itr->virt_addr[5]); - } - if (!found) { - if (printk_ratelimit()) - dev_err(dev, "EDA: Eth addr %02x:%02x:%02x" - ":%02x:%02x:%02x not found.\n", - virt_addr[0], virt_addr[1], - virt_addr[2], virt_addr[3], - virt_addr[4], virt_addr[5]); - result = -ENODEV; - } - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} - -static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED", - "WLP_WSS_CONNECTED", - "WLP_WSS_CONNECT_FAILED", -}; - -static const char *wlp_wss_connect_state_str(unsigned id) -{ - if (id >= ARRAY_SIZE(__wlp_wss_connect_state)) - return "unknown WSS connection state"; - return __wlp_wss_connect_state[id]; -} - -/* - * View EDA cache from user space - * - * A debugging feature to give user visibility into the EDA cache. Also - * used to display members of WSS to user (called from wlp_wss_members_show()) - */ -ssize_t wlp_eda_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - struct wlp_eda_node *entry; - unsigned long flags; - struct wlp_eda *eda = &wlp->eda; - spin_lock_irqsave(&eda->lock, flags); - result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr " - "tag state virt_addr\n"); - list_for_each_entry(entry, &eda->cache, list_node) { - result += scnprintf(buf + result, PAGE_SIZE - result, - "%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x " - "%p 0x%02x %s " - "%02x:%02x:%02x:%02x:%02x:%02x\n", - entry->eth_addr[0], entry->eth_addr[1], - entry->eth_addr[2], entry->eth_addr[3], - entry->eth_addr[4], entry->eth_addr[5], - entry->dev_addr.data[1], - entry->dev_addr.data[0], entry->wss, - entry->tag, - wlp_wss_connect_state_str(entry->state), - entry->virt_addr[0], entry->virt_addr[1], - entry->virt_addr[2], entry->virt_addr[3], - entry->virt_addr[4], entry->virt_addr[5]); - if (result >= PAGE_SIZE) - break; - } - spin_unlock_irqrestore(&eda->lock, flags); - return result; -} -EXPORT_SYMBOL_GPL(wlp_eda_show); - -/* - * Add new EDA cache entry based on user input in sysfs - * - * Should only be used for debugging. - * - * The WSS is assumed to be the only WSS supported. This needs to be - * redesigned when we support more than one WSS. - */ -ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size) -{ - ssize_t result; - struct wlp_eda *eda = &wlp->eda; - u8 eth_addr[6]; - struct uwb_dev_addr dev_addr; - u8 tag; - unsigned state; - - result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx " - "%02hhx:%02hhx %02hhx %u\n", - ð_addr[0], ð_addr[1], - ð_addr[2], ð_addr[3], - ð_addr[4], ð_addr[5], - &dev_addr.data[1], &dev_addr.data[0], &tag, &state); - switch (result) { - case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */ - /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/ - result = -ENOSYS; - break; - case 10: - state = state >= 1 ? 1 : 0; - result = wlp_eda_create_node(eda, eth_addr, &dev_addr); - if (result < 0 && result != -EEXIST) - goto error; - /* Set virtual addr to be same as MAC */ - result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss, - eth_addr, tag, state); - if (result < 0) - goto error; - break; - default: /* bad format */ - result = -EINVAL; - } -error: - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_eda_store); diff --git a/trunk/drivers/uwb/wlp/messages.c b/trunk/drivers/uwb/wlp/messages.c deleted file mode 100644 index a64cb8241713..000000000000 --- a/trunk/drivers/uwb/wlp/messages.c +++ /dev/null @@ -1,1946 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * Message construction and parsing - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#define D_LOCAL 6 -#include -#include "wlp-internal.h" - -static -const char *__wlp_assoc_frame[] = { - [WLP_ASSOC_D1] = "WLP_ASSOC_D1", - [WLP_ASSOC_D2] = "WLP_ASSOC_D2", - [WLP_ASSOC_M1] = "WLP_ASSOC_M1", - [WLP_ASSOC_M2] = "WLP_ASSOC_M2", - [WLP_ASSOC_M3] = "WLP_ASSOC_M3", - [WLP_ASSOC_M4] = "WLP_ASSOC_M4", - [WLP_ASSOC_M5] = "WLP_ASSOC_M5", - [WLP_ASSOC_M6] = "WLP_ASSOC_M6", - [WLP_ASSOC_M7] = "WLP_ASSOC_M7", - [WLP_ASSOC_M8] = "WLP_ASSOC_M8", - [WLP_ASSOC_F0] = "WLP_ASSOC_F0", - [WLP_ASSOC_E1] = "WLP_ASSOC_E1", - [WLP_ASSOC_E2] = "WLP_ASSOC_E2", - [WLP_ASSOC_C1] = "WLP_ASSOC_C1", - [WLP_ASSOC_C2] = "WLP_ASSOC_C2", - [WLP_ASSOC_C3] = "WLP_ASSOC_C3", - [WLP_ASSOC_C4] = "WLP_ASSOC_C4", -}; - -static const char *wlp_assoc_frame_str(unsigned id) -{ - if (id >= ARRAY_SIZE(__wlp_assoc_frame)) - return "unknown association frame"; - return __wlp_assoc_frame[id]; -} - -static const char *__wlp_assc_error[] = { - "none", - "Authenticator Failure", - "Rogue activity suspected", - "Device busy", - "Setup Locked", - "Registrar not ready", - "Invalid WSS selection", - "Message timeout", - "Enrollment session timeout", - "Device password invalid", - "Unsupported version", - "Internal error", - "Undefined error", - "Numeric comparison failure", - "Waiting for user input", -}; - -static const char *wlp_assc_error_str(unsigned id) -{ - if (id >= ARRAY_SIZE(__wlp_assc_error)) - return "unknown WLP association error"; - return __wlp_assc_error[id]; -} - -static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type, - size_t len) -{ - hdr->type = cpu_to_le16(type); - hdr->length = cpu_to_le16(len); -} - -/* - * Populate fields of a constant sized attribute - * - * @returns: total size of attribute including size of new value - * - * We have two instances of this function (wlp_pset and wlp_set): one takes - * the value as a parameter, the other takes a pointer to the value as - * parameter. They thus only differ in how the value is assigned to the - * attribute. - * - * We use sizeof(*attr) - sizeof(struct wlp_attr_hdr) instead of - * sizeof(type) to be able to use this same code for the structures that - * contain 8bit enum values and be able to deal with pointer types. - */ -#define wlp_set(type, type_code, name) \ -static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ -{ \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ - wlp_set_attr_hdr(&attr->hdr, type_code, \ - sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ - attr->name = value; \ - d_dump(6, NULL, attr, sizeof(*attr)); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ - return sizeof(*attr); \ -} - -#define wlp_pset(type, type_code, name) \ -static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ -{ \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ - wlp_set_attr_hdr(&attr->hdr, type_code, \ - sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ - attr->name = *value; \ - d_dump(6, NULL, attr, sizeof(*attr)); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ - return sizeof(*attr); \ -} - -/** - * Populate fields of a variable attribute - * - * @returns: total size of attribute including size of new value - * - * Provided with a pointer to the memory area reserved for the - * attribute structure, the field is populated with the value. The - * reserved memory has to contain enough space for the value. - */ -#define wlp_vset(type, type_code, name) \ -static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \ - size_t len) \ -{ \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ - wlp_set_attr_hdr(&attr->hdr, type_code, len); \ - memcpy(attr->name, value, len); \ - d_dump(6, NULL, attr, sizeof(*attr) + len); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ - return sizeof(*attr) + len; \ -} - -wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name) -wlp_vset(char *, WLP_ATTR_MANUF, manufacturer) -wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type) -wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name) -wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr) -wlp_vset(char *, WLP_ATTR_SERIAL, serial) -wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name) -wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e) -wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r) -wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid) -wlp_pset(struct wlp_dev_type *, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type) -/*wlp_pset(struct wlp_dev_type *, WLP_ATTR_SEC_DEV_TYPE, sec_dev_type)*/ -wlp_set(u8, WLP_ATTR_WLP_VER, version) -wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err) -wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd) -wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl) -wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status) -wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast) -wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce) -wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce) -wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag) -wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt) - -/** - * Fill in the WSS information attributes - * - * We currently only support one WSS, and this is assumed in this function - * that can populate only one WSS information attribute. - */ -static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr, - struct wlp_wss *wss) -{ - size_t datalen; - void *ptr = attr->wss_info; - size_t used = sizeof(*attr); - d_fnstart(6, NULL, "(attribute %p)\n", attr); - datalen = sizeof(struct wlp_wss_info) + strlen(wss->name); - wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen); - used = wlp_set_wssid(ptr, &wss->wssid); - used += wlp_set_wss_name(ptr + used, wss->name, strlen(wss->name)); - used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll); - used += wlp_set_wss_sec_status(ptr + used, wss->secure_status); - used += wlp_set_wss_bcast(ptr + used, &wss->bcast); - d_dump(6, NULL, attr, sizeof(*attr) + datalen); - d_fnend(6, NULL, "(attribute %p, used %d)\n", - attr, (int)(sizeof(*attr) + used)); - return sizeof(*attr) + used; -} - -/** - * Verify attribute header - * - * @hdr: Pointer to attribute header that will be verified. - * @type: Expected attribute type. - * @len: Expected length of attribute value (excluding header). - * - * Most attribute values have a known length even when they do have a - * length field. This knowledge can be used via this function to verify - * that the length field matches the expected value. - */ -static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr, - enum wlp_attr_type type, unsigned len) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - - if (le16_to_cpu(hdr->type) != type) { - dev_err(dev, "WLP: unexpected header type. Expected " - "%u, got %u.\n", type, le16_to_cpu(hdr->type)); - return -EINVAL; - } - if (le16_to_cpu(hdr->length) != len) { - dev_err(dev, "WLP: unexpected length in header. Expected " - "%u, got %u.\n", len, le16_to_cpu(hdr->length)); - return -EINVAL; - } - return 0; -} - -/** - * Check if header of WSS information attribute valid - * - * @returns: length of WSS attributes (value of length attribute field) if - * valid WSS information attribute found - * -ENODATA if no WSS information attribute found - * -EIO other error occured - * - * The WSS information attribute is optional. The function will be provided - * with a pointer to data that could _potentially_ be a WSS information - * attribute. If a valid WSS information attribute is found it will return - * 0, if no WSS information attribute is found it will return -ENODATA, and - * another error will be returned if it is a WSS information attribute, but - * some parsing failure occured. - */ -static int wlp_check_wss_info_attr_hdr(struct wlp *wlp, - struct wlp_attr_hdr *hdr, size_t buflen) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - size_t len; - int result = 0; - - if (buflen < sizeof(*hdr)) { - dev_err(dev, "WLP: Not enough space in buffer to parse" - " WSS information attribute header.\n"); - result = -EIO; - goto out; - } - if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) { - /* WSS information is optional */ - result = -ENODATA; - goto out; - } - len = le16_to_cpu(hdr->length); - if (buflen < sizeof(*hdr) + len) { - dev_err(dev, "WLP: Not enough space in buffer to parse " - "variable data. Got %d, expected %d.\n", - (int)buflen, (int)(sizeof(*hdr) + len)); - result = -EIO; - goto out; - } - result = len; -out: - return result; -} - - -/** - * Get value of attribute from fixed size attribute field. - * - * @attr: Pointer to attribute field. - * @value: Pointer to variable in which attribute value will be placed. - * @buflen: Size of buffer in which attribute field (including header) - * can be found. - * @returns: Amount of given buffer consumed by parsing for this attribute. - * - * The size and type of the value is known by the type of the attribute. - */ -#define wlp_get(type, type_code, name) \ -ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \ - type *value, ssize_t buflen) \ -{ \ - struct device *dev = &wlp->rc->uwb_dev.dev; \ - if (buflen < 0) \ - return -EINVAL; \ - if (buflen < sizeof(*attr)) { \ - dev_err(dev, "WLP: Not enough space in buffer to parse" \ - " attribute field. Need %d, received %zu\n", \ - (int)sizeof(*attr), buflen); \ - return -EIO; \ - } \ - if (wlp_check_attr_hdr(wlp, &attr->hdr, type_code, \ - sizeof(attr->name)) < 0) { \ - dev_err(dev, "WLP: Header verification failed. \n"); \ - return -EINVAL; \ - } \ - *value = attr->name; \ - return sizeof(*attr); \ -} - -#define wlp_get_sparse(type, type_code, name) \ - static wlp_get(type, type_code, name) - -/** - * Get value of attribute from variable sized attribute field. - * - * @max: The maximum size of this attribute. This value is dictated by - * the maximum value from the WLP specification. - * - * @attr: Pointer to attribute field. - * @value: Pointer to variable that will contain the value. The memory - * must already have been allocated for this value. - * @buflen: Size of buffer in which attribute field (including header) - * can be found. - * @returns: Amount of given bufferconsumed by parsing for this attribute. - */ -#define wlp_vget(type_val, type_code, name, max) \ -static ssize_t wlp_get_##name(struct wlp *wlp, \ - struct wlp_attr_##name *attr, \ - type_val *value, ssize_t buflen) \ -{ \ - struct device *dev = &wlp->rc->uwb_dev.dev; \ - size_t len; \ - if (buflen < 0) \ - return -EINVAL; \ - if (buflen < sizeof(*attr)) { \ - dev_err(dev, "WLP: Not enough space in buffer to parse" \ - " header.\n"); \ - return -EIO; \ - } \ - if (le16_to_cpu(attr->hdr.type) != type_code) { \ - dev_err(dev, "WLP: Unexpected attribute type. Got %u, " \ - "expected %u.\n", le16_to_cpu(attr->hdr.type), \ - type_code); \ - return -EINVAL; \ - } \ - len = le16_to_cpu(attr->hdr.length); \ - if (len > max) { \ - dev_err(dev, "WLP: Attribute larger than maximum " \ - "allowed. Received %zu, max is %d.\n", len, \ - (int)max); \ - return -EFBIG; \ - } \ - if (buflen < sizeof(*attr) + len) { \ - dev_err(dev, "WLP: Not enough space in buffer to parse "\ - "variable data.\n"); \ - return -EIO; \ - } \ - memcpy(value, (void *) attr + sizeof(*attr), len); \ - return sizeof(*attr) + len; \ -} - -wlp_get(u8, WLP_ATTR_WLP_VER, version) -wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd) -wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type) -wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err) -wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e) -wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r) -wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid) -wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl) -wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status) -wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast) -wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag) -wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt) -wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce) -wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce) - -/* The buffers for the device info attributes can be found in the - * wlp_device_info struct. These buffers contain one byte more than the - * max allowed by the spec - this is done to be able to add the - * terminating \0 for user display. This terminating byte is not required - * in the actual attribute field (because it has a length field) so the - * maximum allowed for this value is one less than its size in the - * structure. - */ -wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name, - FIELD_SIZEOF(struct wlp_wss, name) - 1) -wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name, - FIELD_SIZEOF(struct wlp_device_info, name) - 1) -wlp_vget(char, WLP_ATTR_MANUF, manufacturer, - FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1) -wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name, - FIELD_SIZEOF(struct wlp_device_info, model_name) - 1) -wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr, - FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1) -wlp_vget(char, WLP_ATTR_SERIAL, serial, - FIELD_SIZEOF(struct wlp_device_info, serial) - 1) - -/** - * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info - * - * @attr: pointer to WSS name attribute in WSS information attribute field - * @info: structure that will be populated with data from WSS information - * field (WSS name, Accept enroll, secure status, broadcast address) - * @buflen: size of buffer - * - * Although the WSSID attribute forms part of the WSS info attribute it is - * retrieved separately and stored in a different location. - */ -static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, - struct wlp_attr_hdr *attr, - struct wlp_wss_tmp_info *info, - ssize_t buflen) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - void *ptr = attr; - size_t used = 0; - ssize_t result = -EINVAL; - - d_printf(6, dev, "WLP: WSS info: Retrieving WSS name\n"); - result = wlp_get_wss_name(wlp, ptr, info->name, buflen); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS name from " - "WSS info in D2 message.\n"); - goto error_parse; - } - used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving accept enroll\n"); - result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll, - buflen - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain accepting " - "enrollment from WSS info in D2 message.\n"); - goto error_parse; - } - if (info->accept_enroll != 0 && info->accept_enroll != 1) { - dev_err(dev, "WLP: invalid value for accepting " - "enrollment in D2 message.\n"); - result = -EINVAL; - goto error_parse; - } - used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving secure status\n"); - result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status, - buflen - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain secure " - "status from WSS info in D2 message.\n"); - goto error_parse; - } - if (info->sec_status != 0 && info->sec_status != 1) { - dev_err(dev, "WLP: invalid value for secure " - "status in D2 message.\n"); - result = -EINVAL; - goto error_parse; - } - used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving broadcast\n"); - result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast, - buflen - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain broadcast " - "address from WSS info in D2 message.\n"); - goto error_parse; - } - used += result; - result = used; -error_parse: - return result; -} - -/** - * Create a new WSSID entry for the neighbor, allocate temporary storage - * - * Each neighbor can have many WSS active. We maintain a list of WSSIDs - * advertised by neighbor. During discovery we also cache information about - * these WSS in temporary storage. - * - * The temporary storage will be removed after it has been used (eg. - * displayed to user), the wssid element will be removed from the list when - * the neighbor is rediscovered or when it disappears. - */ -static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp, - struct wlp_neighbor_e *neighbor) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_wssid_e *wssid_e; - - wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL); - if (wssid_e == NULL) { - dev_err(dev, "WLP: unable to allocate memory " - "for WSS information.\n"); - goto error_alloc; - } - wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL); - if (wssid_e->info == NULL) { - dev_err(dev, "WLP: unable to allocate memory " - "for temporary WSS information.\n"); - kfree(wssid_e); - wssid_e = NULL; - goto error_alloc; - } - list_add(&wssid_e->node, &neighbor->wssid); -error_alloc: - return wssid_e; -} - -/** - * Parse WSS information attribute - * - * @attr: pointer to WSS information attribute header - * @buflen: size of buffer in which WSS information attribute appears - * @wssid: will place wssid from WSS info attribute in this location - * @wss_info: will place other information from WSS information attribute - * in this location - * - * memory for @wssid and @wss_info must be allocated when calling this - */ -static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr, - size_t buflen, struct wlp_uuid *wssid, - struct wlp_wss_tmp_info *wss_info) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - ssize_t result; - size_t len; - size_t used = 0; - void *ptr; - - result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr, - buflen); - if (result < 0) - goto out; - len = result; - used = sizeof(*attr); - ptr = attr; - d_printf(6, dev, "WLP: WSS info: Retrieving WSSID\n"); - result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n"); - goto out; - } - used += result; - result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info, - buflen - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS information " - "from WSS information attributes. \n"); - goto out; - } - used += result; - if (len + sizeof(*attr) != used) { - dev_err(dev, "WLP: Amount of data parsed does not " - "match length field. Parsed %zu, length " - "field %zu. \n", used, len); - result = -EINVAL; - goto out; - } - result = used; - d_printf(6, dev, "WLP: Successfully parsed WLP information " - "attribute. used %zu bytes\n", used); -out: - return result; -} - -/** - * Retrieve WSS info from association frame - * - * @attr: pointer to WSS information attribute - * @neighbor: ptr to neighbor being discovered, NULL if enrollment in - * progress - * @wss: ptr to WSS being enrolled in, NULL if discovery in progress - * @buflen: size of buffer in which WSS information appears - * - * The WSS information attribute appears in the D2 association message. - * This message is used in two ways: to discover all neighbors or to enroll - * into a WSS activated by a neighbor. During discovery we only want to - * store the WSS info in a cache, to be deleted right after it has been - * used (eg. displayed to the user). During enrollment we store the WSS - * information for the lifetime of enrollment. - * - * During discovery we are interested in all WSS information, during - * enrollment we are only interested in the WSS being enrolled in. Even so, - * when in enrollment we keep parsing the message after finding the WSS of - * interest, this simplifies the calling routine in that it can be sure - * that all WSS information attributes have been parsed out of the message. - * - * Association frame is process with nbmutex held. The list access is safe. - */ -static ssize_t wlp_get_all_wss_info(struct wlp *wlp, - struct wlp_attr_wss_info *attr, - struct wlp_neighbor_e *neighbor, - struct wlp_wss *wss, ssize_t buflen) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - size_t used = 0; - ssize_t result = -EINVAL; - struct wlp_attr_wss_info *cur; - struct wlp_uuid wssid; - struct wlp_wss_tmp_info wss_info; - unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */ - struct wlp_wssid_e *wssid_e; - char buf[WLP_WSS_UUID_STRSIZE]; - - d_fnstart(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d \n", - wlp, attr, neighbor, wss, (int)buflen); - if (buflen < 0) - goto out; - - if (neighbor != NULL && wss == NULL) - enroll = 0; /* discovery */ - else if (wss != NULL && neighbor == NULL) - enroll = 1; /* enrollment */ - else - goto out; - - cur = attr; - while (buflen - used > 0) { - memset(&wss_info, 0, sizeof(wss_info)); - cur = (void *)cur + used; - result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid, - &wss_info); - if (result == -ENODATA) { - result = used; - goto out; - } else if (result < 0) { - dev_err(dev, "WLP: Unable to parse WSS information " - "from WSS information attribute. \n"); - result = -EINVAL; - goto error_parse; - } - if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) { - if (wss_info.accept_enroll != 1) { - dev_err(dev, "WLP: Requested WSS does " - "not accept enrollment.\n"); - result = -EINVAL; - goto out; - } - memcpy(wss->name, wss_info.name, sizeof(wss->name)); - wss->bcast = wss_info.bcast; - wss->secure_status = wss_info.sec_status; - wss->accept_enroll = wss_info.accept_enroll; - wss->state = WLP_WSS_STATE_PART_ENROLLED; - wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(2, dev, "WLP: Found WSS %s. Enrolling.\n", - buf); - } else { - wssid_e = wlp_create_wssid_e(wlp, neighbor); - if (wssid_e == NULL) { - dev_err(dev, "WLP: Cannot create new WSSID " - "entry for neighbor %02x:%02x.\n", - neighbor->uwb_dev->dev_addr.data[1], - neighbor->uwb_dev->dev_addr.data[0]); - result = -ENOMEM; - goto out; - } - wssid_e->wssid = wssid; - *wssid_e->info = wss_info; - } - used += result; - } - result = used; -error_parse: - if (result < 0 && !enroll) /* this was a discovery */ - wlp_remove_neighbor_tmp_info(neighbor); -out: - d_fnend(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d, " - "result %d \n", wlp, attr, neighbor, wss, (int)buflen, - (int)result); - return result; - -} - -/** - * Parse WSS information attributes into cache for discovery - * - * @attr: the first WSS information attribute in message - * @neighbor: the neighbor whose cache will be populated - * @buflen: size of the input buffer - */ -static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp, - struct wlp_attr_wss_info *attr, - struct wlp_neighbor_e *neighbor, - ssize_t buflen) -{ - return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen); -} - -/** - * Parse WSS information attributes into WSS struct for enrollment - * - * @attr: the first WSS information attribute in message - * @wss: the WSS that will be enrolled - * @buflen: size of the input buffer - */ -static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp, - struct wlp_attr_wss_info *attr, - struct wlp_wss *wss, ssize_t buflen) -{ - return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen); -} - -/** - * Construct a D1 association frame - * - * We use the radio control functions to determine the values of the device - * properties. These are of variable length and the total space needed is - * tallied first before we start constructing the message. The radio - * control functions return strings that are terminated with \0. This - * character should not be included in the message (there is a length field - * accompanying it in the attribute). - */ -static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb) -{ - - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - struct wlp_device_info *info; - size_t used = 0; - struct wlp_frame_assoc *_d1; - struct sk_buff *_skb; - void *d1_itr; - - d_fnstart(6, dev, "wlp %p\n", wlp); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) { - dev_err(dev, "WLP: Unable to setup device " - "information for D1 message.\n"); - goto error; - } - } - info = wlp->dev_info; - d_printf(6, dev, "Local properties:\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - (int)strlen(info->name), info->name, - (int)strlen(info->model_name), info->model_name, - (int)strlen(info->manufacturer), info->manufacturer, - (int)strlen(info->model_nr), info->model_nr, - (int)strlen(info->serial), info->serial, - info->prim_dev_type.category, - info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], - info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); - _skb = dev_alloc_skb(sizeof(*_d1) - + sizeof(struct wlp_attr_uuid_e) - + sizeof(struct wlp_attr_wss_sel_mthd) - + sizeof(struct wlp_attr_dev_name) - + strlen(info->name) - + sizeof(struct wlp_attr_manufacturer) - + strlen(info->manufacturer) - + sizeof(struct wlp_attr_model_name) - + strlen(info->model_name) - + sizeof(struct wlp_attr_model_nr) - + strlen(info->model_nr) - + sizeof(struct wlp_attr_serial) - + strlen(info->serial) - + sizeof(struct wlp_attr_prim_dev_type) - + sizeof(struct wlp_attr_wlp_assc_err)); - if (_skb == NULL) { - dev_err(dev, "WLP: Cannot allocate memory for association " - "message.\n"); - result = -ENOMEM; - goto error; - } - _d1 = (void *) _skb->data; - d_printf(6, dev, "D1 starts at %p \n", _d1); - _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - _d1->hdr.type = WLP_FRAME_ASSOCIATION; - _d1->type = WLP_ASSOC_D1; - - wlp_set_version(&_d1->version, WLP_VERSION); - wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1); - d1_itr = _d1->attr; - used = wlp_set_uuid_e(d1_itr, &wlp->uuid); - used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT); - used += wlp_set_dev_name(d1_itr + used, info->name, - strlen(info->name)); - used += wlp_set_manufacturer(d1_itr + used, info->manufacturer, - strlen(info->manufacturer)); - used += wlp_set_model_name(d1_itr + used, info->model_name, - strlen(info->model_name)); - used += wlp_set_model_nr(d1_itr + used, info->model_nr, - strlen(info->model_nr)); - used += wlp_set_serial(d1_itr + used, info->serial, - strlen(info->serial)); - used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type); - used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE); - skb_put(_skb, sizeof(*_d1) + used); - d_printf(6, dev, "D1 message:\n"); - d_dump(6, dev, _d1, sizeof(*_d1) - + sizeof(struct wlp_attr_uuid_e) - + sizeof(struct wlp_attr_wss_sel_mthd) - + sizeof(struct wlp_attr_dev_name) - + strlen(info->name) - + sizeof(struct wlp_attr_manufacturer) - + strlen(info->manufacturer) - + sizeof(struct wlp_attr_model_name) - + strlen(info->model_name) - + sizeof(struct wlp_attr_model_nr) - + strlen(info->model_nr) - + sizeof(struct wlp_attr_serial) - + strlen(info->serial) - + sizeof(struct wlp_attr_prim_dev_type) - + sizeof(struct wlp_attr_wlp_assc_err)); - *skb = _skb; -error: - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); - return result; -} - -/** - * Construct a D2 association frame - * - * We use the radio control functions to determine the values of the device - * properties. These are of variable length and the total space needed is - * tallied first before we start constructing the message. The radio - * control functions return strings that are terminated with \0. This - * character should not be included in the message (there is a length field - * accompanying it in the attribute). - */ -static -int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb, struct wlp_uuid *uuid_e) -{ - - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - struct wlp_device_info *info; - size_t used = 0; - struct wlp_frame_assoc *_d2; - struct sk_buff *_skb; - void *d2_itr; - size_t mem_needed; - - d_fnstart(6, dev, "wlp %p\n", wlp); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) { - dev_err(dev, "WLP: Unable to setup device " - "information for D2 message.\n"); - goto error; - } - } - info = wlp->dev_info; - d_printf(6, dev, "Local properties:\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - (int)strlen(info->name), info->name, - (int)strlen(info->model_name), info->model_name, - (int)strlen(info->manufacturer), info->manufacturer, - (int)strlen(info->model_nr), info->model_nr, - (int)strlen(info->serial), info->serial, - info->prim_dev_type.category, - info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], - info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); - mem_needed = sizeof(*_d2) - + sizeof(struct wlp_attr_uuid_e) - + sizeof(struct wlp_attr_uuid_r) - + sizeof(struct wlp_attr_dev_name) - + strlen(info->name) - + sizeof(struct wlp_attr_manufacturer) - + strlen(info->manufacturer) - + sizeof(struct wlp_attr_model_name) - + strlen(info->model_name) - + sizeof(struct wlp_attr_model_nr) - + strlen(info->model_nr) - + sizeof(struct wlp_attr_serial) - + strlen(info->serial) - + sizeof(struct wlp_attr_prim_dev_type) - + sizeof(struct wlp_attr_wlp_assc_err); - if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE) - mem_needed += sizeof(struct wlp_attr_wss_info) - + sizeof(struct wlp_wss_info) - + strlen(wlp->wss.name); - _skb = dev_alloc_skb(mem_needed); - if (_skb == NULL) { - dev_err(dev, "WLP: Cannot allocate memory for association " - "message.\n"); - result = -ENOMEM; - goto error; - } - _d2 = (void *) _skb->data; - d_printf(6, dev, "D2 starts at %p \n", _d2); - _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - _d2->hdr.type = WLP_FRAME_ASSOCIATION; - _d2->type = WLP_ASSOC_D2; - - wlp_set_version(&_d2->version, WLP_VERSION); - wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2); - d2_itr = _d2->attr; - used = wlp_set_uuid_e(d2_itr, uuid_e); - used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid); - if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE) - used += wlp_set_wss_info(d2_itr + used, &wlp->wss); - used += wlp_set_dev_name(d2_itr + used, info->name, - strlen(info->name)); - used += wlp_set_manufacturer(d2_itr + used, info->manufacturer, - strlen(info->manufacturer)); - used += wlp_set_model_name(d2_itr + used, info->model_name, - strlen(info->model_name)); - used += wlp_set_model_nr(d2_itr + used, info->model_nr, - strlen(info->model_nr)); - used += wlp_set_serial(d2_itr + used, info->serial, - strlen(info->serial)); - used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type); - used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE); - skb_put(_skb, sizeof(*_d2) + used); - d_printf(6, dev, "D2 message:\n"); - d_dump(6, dev, _d2, mem_needed); - *skb = _skb; -error: - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); - return result; -} - -/** - * Allocate memory for and populate fields of F0 association frame - * - * Currently (while focusing on unsecure enrollment) we ignore the - * nonce's that could be placed in the message. Only the error field is - * populated by the value provided by the caller. - */ -static -int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, - enum wlp_assc_error error) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = -ENOMEM; - struct { - struct wlp_frame_assoc f0_hdr; - struct wlp_attr_enonce enonce; - struct wlp_attr_rnonce rnonce; - struct wlp_attr_wlp_assc_err assc_err; - } *f0; - struct sk_buff *_skb; - struct wlp_nonce tmp; - - d_fnstart(6, dev, "wlp %p\n", wlp); - _skb = dev_alloc_skb(sizeof(*f0)); - if (_skb == NULL) { - dev_err(dev, "WLP: Unable to allocate memory for F0 " - "association frame. \n"); - goto error_alloc; - } - f0 = (void *) _skb->data; - d_printf(6, dev, "F0 starts at %p \n", f0); - f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION; - f0->f0_hdr.type = WLP_ASSOC_F0; - wlp_set_version(&f0->f0_hdr.version, WLP_VERSION); - wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0); - memset(&tmp, 0, sizeof(tmp)); - wlp_set_enonce(&f0->enonce, &tmp); - wlp_set_rnonce(&f0->rnonce, &tmp); - wlp_set_wlp_assc_err(&f0->assc_err, error); - skb_put(_skb, sizeof(*f0)); - *skb = _skb; - result = 0; -error_alloc: - d_fnend(6, dev, "wlp %p, result %d \n", wlp, result); - return result; -} - -/** - * Parse F0 frame - * - * We just retrieve the values and print it as an error to the user. - * Calling function already knows an error occured (F0 indicates error), so - * we just parse the content as debug for higher layers. - */ -int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *f0 = (void *) skb->data; - void *ptr = skb->data; - size_t len = skb->len; - size_t used; - ssize_t result; - struct wlp_nonce enonce, rnonce; - enum wlp_assc_error assc_err; - char enonce_buf[WLP_WSS_NONCE_STRSIZE]; - char rnonce_buf[WLP_WSS_NONCE_STRSIZE]; - - used = sizeof(*f0); - result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Enrollee nonce " - "attribute from F0 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Registrar nonce " - "attribute from F0 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WLP Association error " - "attribute from F0 message.\n"); - goto error_parse; - } - wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce); - wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce); - dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee " - "nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n", - enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err)); - result = 0; -error_parse: - return result; -} - -/** - * Retrieve variable device information from association message - * - * The device information parsed is not required in any message. This - * routine will thus not fail if an attribute is not present. - * The attributes are expected in a certain order, even if all are not - * present. The "attribute type" value is used to ensure the attributes - * are parsed in the correct order. - * - * If an error is encountered during parsing the function will return an - * error code, when this happens the given device_info structure may be - * partially filled. - */ -static -int wlp_get_variable_info(struct wlp *wlp, void *data, - struct wlp_device_info *dev_info, ssize_t len) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - size_t used = 0; - struct wlp_attr_hdr *hdr; - ssize_t result = 0; - unsigned last = 0; - - while (len - used > 0) { - if (len - used < sizeof(*hdr)) { - dev_err(dev, "WLP: Partial data in frame, cannot " - "parse. \n"); - goto error_parse; - } - hdr = data + used; - switch (le16_to_cpu(hdr->type)) { - case WLP_ATTR_MANUF: - if (last >= WLP_ATTR_MANUF) { - dev_err(dev, "WLP: Incorrect order of " - "attribute values in D1 msg.\n"); - goto error_parse; - } - result = wlp_get_manufacturer(wlp, data + used, - dev_info->manufacturer, - len - used); - if (result < 0) { - dev_err(dev, "WLP: Unable to obtain " - "Manufacturer attribute from D1 " - "message.\n"); - goto error_parse; - } - last = WLP_ATTR_MANUF; - used += result; - break; - case WLP_ATTR_MODEL_NAME: - if (last >= WLP_ATTR_MODEL_NAME) { - dev_err(dev, "WLP: Incorrect order of " - "attribute values in D1 msg.\n"); - goto error_parse; - } - result = wlp_get_model_name(wlp, data + used, - dev_info->model_name, - len - used); - if (result < 0) { - dev_err(dev, "WLP: Unable to obtain Model " - "name attribute from D1 message.\n"); - goto error_parse; - } - last = WLP_ATTR_MODEL_NAME; - used += result; - break; - case WLP_ATTR_MODEL_NR: - if (last >= WLP_ATTR_MODEL_NR) { - dev_err(dev, "WLP: Incorrect order of " - "attribute values in D1 msg.\n"); - goto error_parse; - } - result = wlp_get_model_nr(wlp, data + used, - dev_info->model_nr, - len - used); - if (result < 0) { - dev_err(dev, "WLP: Unable to obtain Model " - "number attribute from D1 message.\n"); - goto error_parse; - } - last = WLP_ATTR_MODEL_NR; - used += result; - break; - case WLP_ATTR_SERIAL: - if (last >= WLP_ATTR_SERIAL) { - dev_err(dev, "WLP: Incorrect order of " - "attribute values in D1 msg.\n"); - goto error_parse; - } - result = wlp_get_serial(wlp, data + used, - dev_info->serial, len - used); - if (result < 0) { - dev_err(dev, "WLP: Unable to obtain Serial " - "number attribute from D1 message.\n"); - goto error_parse; - } - last = WLP_ATTR_SERIAL; - used += result; - break; - case WLP_ATTR_PRI_DEV_TYPE: - if (last >= WLP_ATTR_PRI_DEV_TYPE) { - dev_err(dev, "WLP: Incorrect order of " - "attribute values in D1 msg.\n"); - goto error_parse; - } - result = wlp_get_prim_dev_type(wlp, data + used, - &dev_info->prim_dev_type, - len - used); - if (result < 0) { - dev_err(dev, "WLP: Unable to obtain Primary " - "device type attribute from D1 " - "message.\n"); - goto error_parse; - } - dev_info->prim_dev_type.category = - le16_to_cpu(dev_info->prim_dev_type.category); - dev_info->prim_dev_type.subID = - le16_to_cpu(dev_info->prim_dev_type.subID); - last = WLP_ATTR_PRI_DEV_TYPE; - used += result; - break; - default: - /* This is not variable device information. */ - goto out; - break; - } - } -out: - return used; -error_parse: - return -EINVAL; -} - -/** - * Parse incoming D1 frame, populate attribute values - * - * Caller provides pointers to memory already allocated for attributes - * expected in the D1 frame. These variables will be populated. - */ -static -int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb, - struct wlp_uuid *uuid_e, - enum wlp_wss_sel_mthd *sel_mthd, - struct wlp_device_info *dev_info, - enum wlp_assc_error *assc_err) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *d1 = (void *) skb->data; - void *ptr = skb->data; - size_t len = skb->len; - size_t used; - ssize_t result; - - used = sizeof(*d1); - result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 " - "message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS selection method " - "from D1 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_dev_name(wlp, ptr + used, dev_info->name, - len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Name from D1 " - "message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Information from " - "D1 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WLP Association Error " - "Information from D1 message.\n"); - goto error_parse; - } - result = 0; -error_parse: - return result; -} -/** - * Handle incoming D1 frame - * - * The frame has already been verified to contain an Association header with - * the correct version number. Parse the incoming frame, construct and send - * a D2 frame in response. - * - * It is not clear what to do with most fields in the incoming D1 frame. We - * retrieve and discard the information here for now. - */ -void wlp_handle_d1_frame(struct work_struct *ws) -{ - struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws, - struct wlp_assoc_frame_ctx, - ws); - struct wlp *wlp = frame_ctx->wlp; - struct wlp_wss *wss = &wlp->wss; - struct sk_buff *skb = frame_ctx->skb; - struct uwb_dev_addr *src = &frame_ctx->src; - int result; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_uuid uuid_e; - enum wlp_wss_sel_mthd sel_mthd = 0; - struct wlp_device_info dev_info; - enum wlp_assc_error assc_err; - char uuid[WLP_WSS_UUID_STRSIZE]; - struct sk_buff *resp = NULL; - - /* Parse D1 frame */ - d_fnstart(6, dev, "WLP: handle D1 frame. wlp = %p, skb = %p\n", - wlp, skb); - mutex_lock(&wss->mutex); - mutex_lock(&wlp->mutex); /* to access wlp->uuid */ - memset(&dev_info, 0, sizeof(dev_info)); - result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info, - &assc_err); - if (result < 0) { - dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n"); - kfree_skb(skb); - goto out; - } - wlp_wss_uuid_print(uuid, sizeof(uuid), &uuid_e); - d_printf(6, dev, "From D1 frame:\n" - "UUID-E: %s\n" - "Selection method: %d\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - uuid, sel_mthd, - (int)strlen(dev_info.name), dev_info.name, - (int)strlen(dev_info.model_name), dev_info.model_name, - (int)strlen(dev_info.manufacturer), dev_info.manufacturer, - (int)strlen(dev_info.model_nr), dev_info.model_nr, - (int)strlen(dev_info.serial), dev_info.serial, - dev_info.prim_dev_type.category, - dev_info.prim_dev_type.OUI[0], - dev_info.prim_dev_type.OUI[1], - dev_info.prim_dev_type.OUI[2], - dev_info.prim_dev_type.OUIsubdiv); - - kfree_skb(skb); - if (!wlp_uuid_is_set(&wlp->uuid)) { - dev_err(dev, "WLP: UUID is not set. Set via sysfs to " - "proceed. Respong to D1 message with error F0.\n"); - result = wlp_build_assoc_f0(wlp, &resp, - WLP_ASSOC_ERROR_NOT_READY); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct F0 message.\n"); - goto out; - } - } else { - /* Construct D2 frame */ - result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct D2 message.\n"); - goto out; - } - } - /* Send D2 frame */ - BUG_ON(wlp->xmit_frame == NULL); - result = wlp->xmit_frame(wlp, resp, src); - if (result < 0) { - dev_err(dev, "WLP: Unable to transmit D2 association " - "message: %d\n", result); - if (result == -ENXIO) - dev_err(dev, "WLP: Is network interface up? \n"); - /* We could try again ... */ - dev_kfree_skb_any(resp); /* we need to free if tx fails */ - } -out: - kfree(frame_ctx); - mutex_unlock(&wlp->mutex); - mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle D1 frame. wlp = %p\n", wlp); -} - -/** - * Parse incoming D2 frame, create and populate temporary cache - * - * @skb: socket buffer in which D2 frame can be found - * @neighbor: the neighbor that sent the D2 frame - * - * Will allocate memory for temporary storage of information learned during - * discovery. - */ -int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb, - struct wlp_neighbor_e *neighbor) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *d2 = (void *) skb->data; - void *ptr = skb->data; - size_t len = skb->len; - size_t used; - ssize_t result; - struct wlp_uuid uuid_e; - struct wlp_device_info *nb_info; - enum wlp_assc_error assc_err; - - used = sizeof(*d2); - result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 " - "message.\n"); - goto error_parse; - } - if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) { - dev_err(dev, "WLP: UUID-E in incoming D2 does not match " - "local UUID sent in D1. \n"); - goto error_parse; - } - used += result; - result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 " - "message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor, - len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS information " - "from D2 message.\n"); - goto error_parse; - } - used += result; - neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL); - if (neighbor->info == NULL) { - dev_err(dev, "WLP: cannot allocate memory to store device " - "info.\n"); - result = -ENOMEM; - goto error_parse; - } - nb_info = neighbor->info; - result = wlp_get_dev_name(wlp, ptr + used, nb_info->name, - len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Name from D2 " - "message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Information from " - "D2 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WLP Association Error " - "Information from D2 message.\n"); - goto error_parse; - } - if (assc_err != WLP_ASSOC_ERROR_NONE) { - dev_err(dev, "WLP: neighbor device returned association " - "error %d\n", assc_err); - result = -EINVAL; - goto error_parse; - } - result = 0; -error_parse: - if (result < 0) - wlp_remove_neighbor_tmp_info(neighbor); - return result; -} - -/** - * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in - * - * @wss: our WSS that will be enrolled - * @skb: socket buffer in which D2 frame can be found - * @neighbor: the neighbor that sent the D2 frame - * @wssid: the wssid of the WSS in which we want to enroll - * - * Forms part of enrollment sequence. We are trying to enroll in WSS with - * @wssid by using @neighbor as registrar. A D1 message was sent to - * @neighbor and now we need to parse the D2 response. The neighbor's - * response is searched for the requested WSS and if found (and it accepts - * enrollment), we store the information. - */ -int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb, - struct wlp_neighbor_e *neighbor, - struct wlp_uuid *wssid) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - void *ptr = skb->data; - size_t len = skb->len; - size_t used; - ssize_t result; - struct wlp_uuid uuid_e; - struct wlp_uuid uuid_r; - struct wlp_device_info nb_info; - enum wlp_assc_error assc_err; - char uuid_bufA[WLP_WSS_UUID_STRSIZE]; - char uuid_bufB[WLP_WSS_UUID_STRSIZE]; - - used = sizeof(struct wlp_frame_assoc); - result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 " - "message.\n"); - goto error_parse; - } - if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) { - dev_err(dev, "WLP: UUID-E in incoming D2 does not match " - "local UUID sent in D1. \n"); - goto error_parse; - } - used += result; - result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 " - "message.\n"); - goto error_parse; - } - if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) { - wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA), - &neighbor->uuid); - wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r); - dev_err(dev, "WLP: UUID of neighbor does not match UUID " - "learned during discovery. Originally discovered: %s, " - "now from D2 message: %s\n", uuid_bufA, uuid_bufB); - result = -EINVAL; - goto error_parse; - } - used += result; - wss->wssid = *wssid; - result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS information " - "from D2 message.\n"); - goto error_parse; - } - if (wss->state != WLP_WSS_STATE_PART_ENROLLED) { - dev_err(dev, "WLP: D2 message did not contain information " - "for successful enrollment. \n"); - result = -EINVAL; - goto error_parse; - } - used += result; - /* Place device information on stack to continue parsing of message */ - result = wlp_get_dev_name(wlp, ptr + used, nb_info.name, - len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Name from D2 " - "message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain Device Information from " - "D2 message.\n"); - goto error_parse; - } - used += result; - result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WLP Association Error " - "Information from D2 message.\n"); - goto error_parse; - } - if (assc_err != WLP_ASSOC_ERROR_NONE) { - dev_err(dev, "WLP: neighbor device returned association " - "error %d\n", assc_err); - if (wss->state == WLP_WSS_STATE_PART_ENROLLED) { - dev_err(dev, "WLP: Enrolled in WSS (should not " - "happen according to spec). Undoing. \n"); - wlp_wss_reset(wss); - } - result = -EINVAL; - goto error_parse; - } - result = 0; -error_parse: - return result; -} - -/** - * Parse C3/C4 frame into provided variables - * - * @wssid: will point to copy of wssid retrieved from C3/C4 frame - * @tag: will point to copy of tag retrieved from C3/C4 frame - * @virt_addr: will point to copy of virtual address retrieved from C3/C4 - * frame. - * - * Calling function has to allocate memory for these values. - * - * skb contains a valid C3/C4 frame, return the individual fields of this - * frame in the provided variables. - */ -int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb, - struct wlp_uuid *wssid, u8 *tag, - struct uwb_mac_addr *virt_addr) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result; - void *ptr = skb->data; - size_t len = skb->len; - size_t used; - char buf[WLP_WSS_UUID_STRSIZE]; - struct wlp_frame_assoc *assoc = ptr; - - d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); - used = sizeof(*assoc); - result = wlp_get_wssid(wlp, ptr + used, wssid, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSSID attribute from " - "%s message.\n", wlp_assoc_frame_str(assoc->type)); - goto error_parse; - } - used += result; - result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS tag attribute from " - "%s message.\n", wlp_assoc_frame_str(assoc->type)); - goto error_parse; - } - used += result; - result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSS virtual address " - "attribute from %s message.\n", - wlp_assoc_frame_str(assoc->type)); - goto error_parse; - } - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_printf(6, dev, "WLP: parsed: WSSID %s, tag 0x%02x, virt " - "%02x:%02x:%02x:%02x:%02x:%02x \n", buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); - -error_parse: - d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); - return result; -} - -/** - * Allocate memory for and populate fields of C1 or C2 association frame - * - * The C1 and C2 association frames appear identical - except for the type. - */ -static -int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb, enum wlp_assoc_type type) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = -ENOMEM; - struct { - struct wlp_frame_assoc c_hdr; - struct wlp_attr_wssid wssid; - } *c; - struct sk_buff *_skb; - - d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); - _skb = dev_alloc_skb(sizeof(*c)); - if (_skb == NULL) { - dev_err(dev, "WLP: Unable to allocate memory for C1/C2 " - "association frame. \n"); - goto error_alloc; - } - c = (void *) _skb->data; - d_printf(6, dev, "C1/C2 starts at %p \n", c); - c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; - c->c_hdr.type = type; - wlp_set_version(&c->c_hdr.version, WLP_VERSION); - wlp_set_msg_type(&c->c_hdr.msg_type, type); - wlp_set_wssid(&c->wssid, &wss->wssid); - skb_put(_skb, sizeof(*c)); - d_printf(6, dev, "C1/C2 message:\n"); - d_dump(6, dev, c, sizeof(*c)); - *skb = _skb; - result = 0; -error_alloc: - d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); - return result; -} - - -static -int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb) -{ - return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1); -} - -static -int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb) -{ - return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2); -} - - -/** - * Allocate memory for and populate fields of C3 or C4 association frame - * - * The C3 and C4 association frames appear identical - except for the type. - */ -static -int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb, enum wlp_assoc_type type) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = -ENOMEM; - struct { - struct wlp_frame_assoc c_hdr; - struct wlp_attr_wssid wssid; - struct wlp_attr_wss_tag wss_tag; - struct wlp_attr_wss_virt wss_virt; - } *c; - struct sk_buff *_skb; - - d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); - _skb = dev_alloc_skb(sizeof(*c)); - if (_skb == NULL) { - dev_err(dev, "WLP: Unable to allocate memory for C3/C4 " - "association frame. \n"); - goto error_alloc; - } - c = (void *) _skb->data; - d_printf(6, dev, "C3/C4 starts at %p \n", c); - c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; - c->c_hdr.type = type; - wlp_set_version(&c->c_hdr.version, WLP_VERSION); - wlp_set_msg_type(&c->c_hdr.msg_type, type); - wlp_set_wssid(&c->wssid, &wss->wssid); - wlp_set_wss_tag(&c->wss_tag, wss->tag); - wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr); - skb_put(_skb, sizeof(*c)); - d_printf(6, dev, "C3/C4 message:\n"); - d_dump(6, dev, c, sizeof(*c)); - *skb = _skb; - result = 0; -error_alloc: - d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); - return result; -} - -static -int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb) -{ - return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3); -} - -static -int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss, - struct sk_buff **skb) -{ - return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4); -} - - -#define wlp_send_assoc(type, id) \ -static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \ - struct uwb_dev_addr *dev_addr) \ -{ \ - struct device *dev = &wlp->rc->uwb_dev.dev; \ - int result; \ - struct sk_buff *skb = NULL; \ - d_fnstart(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ - wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ - d_printf(6, dev, "WLP: Constructing %s frame. \n", \ - wlp_assoc_frame_str(id)); \ - /* Build the frame */ \ - result = wlp_build_assoc_##type(wlp, wss, &skb); \ - if (result < 0) { \ - dev_err(dev, "WLP: Unable to construct %s association " \ - "frame: %d\n", wlp_assoc_frame_str(id), result);\ - goto error_build_assoc; \ - } \ - /* Send the frame */ \ - d_printf(6, dev, "Transmitting %s frame to %02x:%02x \n", \ - wlp_assoc_frame_str(id), \ - dev_addr->data[1], dev_addr->data[0]); \ - BUG_ON(wlp->xmit_frame == NULL); \ - result = wlp->xmit_frame(wlp, skb, dev_addr); \ - if (result < 0) { \ - dev_err(dev, "WLP: Unable to transmit %s association " \ - "message: %d\n", wlp_assoc_frame_str(id), \ - result); \ - if (result == -ENXIO) \ - dev_err(dev, "WLP: Is network interface " \ - "up? \n"); \ - goto error_xmit; \ - } \ - return 0; \ -error_xmit: \ - /* We could try again ... */ \ - dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \ -error_build_assoc: \ - d_fnend(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ - wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ - return result; \ -} - -wlp_send_assoc(d1, WLP_ASSOC_D1) -wlp_send_assoc(c1, WLP_ASSOC_C1) -wlp_send_assoc(c3, WLP_ASSOC_C3) - -int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss, - struct uwb_dev_addr *dev_addr, - enum wlp_assoc_type type) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - switch (type) { - case WLP_ASSOC_D1: - result = wlp_send_assoc_d1(wlp, wss, dev_addr); - break; - case WLP_ASSOC_C1: - result = wlp_send_assoc_c1(wlp, wss, dev_addr); - break; - case WLP_ASSOC_C3: - result = wlp_send_assoc_c3(wlp, wss, dev_addr); - break; - default: - dev_err(dev, "WLP: Received request to send unknown " - "association message.\n"); - result = -EINVAL; - break; - } - return result; -} - -/** - * Handle incoming C1 frame - * - * The frame has already been verified to contain an Association header with - * the correct version number. Parse the incoming frame, construct and send - * a C2 frame in response. - */ -void wlp_handle_c1_frame(struct work_struct *ws) -{ - struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws, - struct wlp_assoc_frame_ctx, - ws); - struct wlp *wlp = frame_ctx->wlp; - struct wlp_wss *wss = &wlp->wss; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data; - unsigned int len = frame_ctx->skb->len; - struct uwb_dev_addr *src = &frame_ctx->src; - int result; - struct wlp_uuid wssid; - char buf[WLP_WSS_UUID_STRSIZE]; - struct sk_buff *resp = NULL; - - /* Parse C1 frame */ - d_fnstart(6, dev, "WLP: handle C1 frame. wlp = %p, c1 = %p\n", - wlp, c1); - mutex_lock(&wss->mutex); - result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid, - len - sizeof(*c1)); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n"); - goto out; - } - wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(6, dev, "Received C1 frame with WSSID %s \n", buf); - if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) - && wss->state == WLP_WSS_STATE_ACTIVE) { - d_printf(6, dev, "WSSID from C1 frame is known locally " - "and is active\n"); - /* Construct C2 frame */ - result = wlp_build_assoc_c2(wlp, wss, &resp); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct C2 message.\n"); - goto out; - } - } else { - d_printf(6, dev, "WSSID from C1 frame is not known locally " - "or is not active\n"); - /* Construct F0 frame */ - result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct F0 message.\n"); - goto out; - } - } - /* Send C2 frame */ - d_printf(6, dev, "Transmitting response (C2/F0) frame to %02x:%02x \n", - src->data[1], src->data[0]); - BUG_ON(wlp->xmit_frame == NULL); - result = wlp->xmit_frame(wlp, resp, src); - if (result < 0) { - dev_err(dev, "WLP: Unable to transmit response association " - "message: %d\n", result); - if (result == -ENXIO) - dev_err(dev, "WLP: Is network interface up? \n"); - /* We could try again ... */ - dev_kfree_skb_any(resp); /* we need to free if tx fails */ - } -out: - kfree_skb(frame_ctx->skb); - kfree(frame_ctx); - mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle C1 frame. wlp = %p\n", wlp); -} - -/** - * Handle incoming C3 frame - * - * The frame has already been verified to contain an Association header with - * the correct version number. Parse the incoming frame, construct and send - * a C4 frame in response. If the C3 frame identifies a WSS that is locally - * active then we connect to this neighbor (add it to our EDA cache). - */ -void wlp_handle_c3_frame(struct work_struct *ws) -{ - struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws, - struct wlp_assoc_frame_ctx, - ws); - struct wlp *wlp = frame_ctx->wlp; - struct wlp_wss *wss = &wlp->wss; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct sk_buff *skb = frame_ctx->skb; - struct uwb_dev_addr *src = &frame_ctx->src; - int result; - char buf[WLP_WSS_UUID_STRSIZE]; - struct sk_buff *resp = NULL; - struct wlp_uuid wssid; - u8 tag; - struct uwb_mac_addr virt_addr; - - /* Parse C3 frame */ - d_fnstart(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", - wlp, skb); - mutex_lock(&wss->mutex); - result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain values from C3 frame.\n"); - goto out; - } - wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(6, dev, "Received C3 frame with WSSID %s \n", buf); - if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) - && wss->state >= WLP_WSS_STATE_ACTIVE) { - d_printf(6, dev, "WSSID from C3 frame is known locally " - "and is active\n"); - result = wlp_eda_update_node(&wlp->eda, src, wss, - (void *) virt_addr.data, tag, - WLP_WSS_CONNECTED); - if (result < 0) { - dev_err(dev, "WLP: Unable to update EDA cache " - "with new connected neighbor information.\n"); - result = wlp_build_assoc_f0(wlp, &resp, - WLP_ASSOC_ERROR_INT); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct F0 " - "message.\n"); - goto out; - } - } else { - wss->state = WLP_WSS_STATE_CONNECTED; - /* Construct C4 frame */ - result = wlp_build_assoc_c4(wlp, wss, &resp); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct C4 " - "message.\n"); - goto out; - } - } - } else { - d_printf(6, dev, "WSSID from C3 frame is not known locally " - "or is not active\n"); - /* Construct F0 frame */ - result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); - if (result < 0) { - dev_err(dev, "WLP: Unable to construct F0 message.\n"); - goto out; - } - } - /* Send C4 frame */ - d_printf(6, dev, "Transmitting response (C4/F0) frame to %02x:%02x \n", - src->data[1], src->data[0]); - BUG_ON(wlp->xmit_frame == NULL); - result = wlp->xmit_frame(wlp, resp, src); - if (result < 0) { - dev_err(dev, "WLP: Unable to transmit response association " - "message: %d\n", result); - if (result == -ENXIO) - dev_err(dev, "WLP: Is network interface up? \n"); - /* We could try again ... */ - dev_kfree_skb_any(resp); /* we need to free if tx fails */ - } -out: - kfree_skb(frame_ctx->skb); - kfree(frame_ctx); - mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", - wlp, skb); -} - - diff --git a/trunk/drivers/uwb/wlp/sysfs.c b/trunk/drivers/uwb/wlp/sysfs.c deleted file mode 100644 index 1bb9b1f97d47..000000000000 --- a/trunk/drivers/uwb/wlp/sysfs.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * sysfs functions - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: Docs - * - */ - -#include -#include "wlp-internal.h" - -static -size_t wlp_wss_wssid_e_print(char *buf, size_t bufsize, - struct wlp_wssid_e *wssid_e) -{ - size_t used = 0; - used += scnprintf(buf, bufsize, " WSS: "); - used += wlp_wss_uuid_print(buf + used, bufsize - used, - &wssid_e->wssid); - - if (wssid_e->info != NULL) { - used += scnprintf(buf + used, bufsize - used, " "); - used += uwb_mac_addr_print(buf + used, bufsize - used, - &wssid_e->info->bcast); - used += scnprintf(buf + used, bufsize - used, " %u %u %s\n", - wssid_e->info->accept_enroll, - wssid_e->info->sec_status, - wssid_e->info->name); - } - return used; -} - -/** - * Print out information learned from neighbor discovery - * - * Some fields being printed may not be included in the device discovery - * information (it is not mandatory). We are thus careful how the - * information is printed to ensure it is clear to the user what field is - * being referenced. - * The information being printed is for one time use - temporary storage is - * cleaned after it is printed. - * - * Ideally sysfs output should be on one line. The information printed here - * contain a few strings so it will be hard to parse if they are all - * printed on the same line - without agreeing on a standard field - * separator. - */ -static -ssize_t wlp_wss_neighborhood_print_remove(struct wlp *wlp, char *buf, - size_t bufsize) -{ - size_t used = 0; - struct wlp_neighbor_e *neighb; - struct wlp_wssid_e *wssid_e; - - mutex_lock(&wlp->nbmutex); - used = scnprintf(buf, bufsize, "#Neighbor information\n" - "#uuid dev_addr\n" - "# Device Name:\n# Model Name:\n# Manufacturer:\n" - "# Model Nr:\n# Serial:\n" - "# Pri Dev type: CategoryID OUI OUISubdiv " - "SubcategoryID\n" - "# WSS: WSSID WSS_name accept_enroll sec_status " - "bcast\n" - "# WSS: WSSID WSS_name accept_enroll sec_status " - "bcast\n\n"); - list_for_each_entry(neighb, &wlp->neighbors, node) { - if (bufsize - used <= 0) - goto out; - used += wlp_wss_uuid_print(buf + used, bufsize - used, - &neighb->uuid); - buf[used++] = ' '; - used += uwb_dev_addr_print(buf + used, bufsize - used, - &neighb->uwb_dev->dev_addr); - if (neighb->info != NULL) - used += scnprintf(buf + used, bufsize - used, - "\n Device Name: %s\n" - " Model Name: %s\n" - " Manufacturer:%s \n" - " Model Nr: %s\n" - " Serial: %s\n" - " Pri Dev type: " - "%u %02x:%02x:%02x %u %u\n", - neighb->info->name, - neighb->info->model_name, - neighb->info->manufacturer, - neighb->info->model_nr, - neighb->info->serial, - neighb->info->prim_dev_type.category, - neighb->info->prim_dev_type.OUI[0], - neighb->info->prim_dev_type.OUI[1], - neighb->info->prim_dev_type.OUI[2], - neighb->info->prim_dev_type.OUIsubdiv, - neighb->info->prim_dev_type.subID); - list_for_each_entry(wssid_e, &neighb->wssid, node) { - used += wlp_wss_wssid_e_print(buf + used, - bufsize - used, - wssid_e); - } - buf[used++] = '\n'; - wlp_remove_neighbor_tmp_info(neighb); - } - - -out: - mutex_unlock(&wlp->nbmutex); - return used; -} - - -/** - * Show properties of all WSS in neighborhood. - * - * Will trigger a complete discovery of WSS activated by this device and - * its neighbors. - */ -ssize_t wlp_neighborhood_show(struct wlp *wlp, char *buf) -{ - wlp_discover(wlp); - return wlp_wss_neighborhood_print_remove(wlp, buf, PAGE_SIZE); -} -EXPORT_SYMBOL_GPL(wlp_neighborhood_show); - -static -ssize_t __wlp_wss_properties_show(struct wlp_wss *wss, char *buf, - size_t bufsize) -{ - ssize_t result; - - result = wlp_wss_uuid_print(buf, bufsize, &wss->wssid); - result += scnprintf(buf + result, bufsize - result, " "); - result += uwb_mac_addr_print(buf + result, bufsize - result, - &wss->bcast); - result += scnprintf(buf + result, bufsize - result, - " 0x%02x %u ", wss->hash, wss->secure_status); - result += wlp_wss_key_print(buf + result, bufsize - result, - wss->master_key); - result += scnprintf(buf + result, bufsize - result, " 0x%02x ", - wss->tag); - result += uwb_mac_addr_print(buf + result, bufsize - result, - &wss->virtual_addr); - result += scnprintf(buf + result, bufsize - result, " %s", wss->name); - result += scnprintf(buf + result, bufsize - result, - "\n\n#WSSID\n#WSS broadcast address\n" - "#WSS hash\n#WSS secure status\n" - "#WSS master key\n#WSS local tag\n" - "#WSS local virtual EUI-48\n#WSS name\n"); - return result; -} - -/** - * Show which WSS is activated. - */ -ssize_t wlp_wss_activate_show(struct wlp_wss *wss, char *buf) -{ - int result = 0; - - if (mutex_lock_interruptible(&wss->mutex)) - goto out; - if (wss->state >= WLP_WSS_STATE_ACTIVE) - result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE); - else - result = scnprintf(buf, PAGE_SIZE, "No local WSS active.\n"); - result += scnprintf(buf + result, PAGE_SIZE - result, - "\n\n" - "# echo WSSID SECURE_STATUS ACCEPT_ENROLLMENT " - "NAME #create new WSS\n" - "# echo WSSID [DEV ADDR] #enroll in and activate " - "existing WSS, can request registrar\n" - "#\n" - "# WSSID is a 16 byte hex array. Eg. 12 A3 3B ... \n" - "# SECURE_STATUS 0 - unsecure, 1 - secure (default)\n" - "# ACCEPT_ENROLLMENT 0 - no, 1 - yes (default)\n" - "# NAME is the text string identifying the WSS\n" - "# DEV ADDR is the device address of neighbor " - "that should be registrar. Eg. 32:AB\n"); - - mutex_unlock(&wss->mutex); -out: - return result; - -} -EXPORT_SYMBOL_GPL(wlp_wss_activate_show); - -/** - * Create/activate a new WSS or enroll/activate in neighboring WSS - * - * The user can provide the WSSID of a WSS in which it wants to enroll. - * Only the WSSID is necessary if the WSS have been discovered before. If - * the WSS has not been discovered before, or the user wants to use a - * particular neighbor as its registrar, then the user can also provide a - * device address or the neighbor that will be used as registrar. - * - * A new WSS is created when the user provides a WSSID, secure status, and - * WSS name. - */ -ssize_t wlp_wss_activate_store(struct wlp_wss *wss, - const char *buf, size_t size) -{ - ssize_t result = -EINVAL; - struct wlp_uuid wssid; - struct uwb_dev_addr dev; - struct uwb_dev_addr bcast = {.data = {0xff, 0xff} }; - char name[65]; - unsigned sec_status, accept; - memset(name, 0, sizeof(name)); - result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx:%02hhx", - &wssid.data[0] , &wssid.data[1], - &wssid.data[2] , &wssid.data[3], - &wssid.data[4] , &wssid.data[5], - &wssid.data[6] , &wssid.data[7], - &wssid.data[8] , &wssid.data[9], - &wssid.data[10], &wssid.data[11], - &wssid.data[12], &wssid.data[13], - &wssid.data[14], &wssid.data[15], - &dev.data[1], &dev.data[0]); - if (result == 16 || result == 17) { - result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%u %u %64c", - &wssid.data[0] , &wssid.data[1], - &wssid.data[2] , &wssid.data[3], - &wssid.data[4] , &wssid.data[5], - &wssid.data[6] , &wssid.data[7], - &wssid.data[8] , &wssid.data[9], - &wssid.data[10], &wssid.data[11], - &wssid.data[12], &wssid.data[13], - &wssid.data[14], &wssid.data[15], - &sec_status, &accept, name); - if (result == 16) - result = wlp_wss_enroll_activate(wss, &wssid, &bcast); - else if (result == 19) { - sec_status = sec_status == 0 ? 0 : 1; - accept = accept == 0 ? 0 : 1; - /* We read name using %c, so the newline needs to be - * removed */ - if (strlen(name) != sizeof(name) - 1) - name[strlen(name) - 1] = '\0'; - result = wlp_wss_create_activate(wss, &wssid, name, - sec_status, accept); - } else - result = -EINVAL; - } else if (result == 18) - result = wlp_wss_enroll_activate(wss, &wssid, &dev); - else - result = -EINVAL; - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_wss_activate_store); - -/** - * Show the UUID of this host - */ -ssize_t wlp_uuid_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - - mutex_lock(&wlp->mutex); - result = wlp_wss_uuid_print(buf, PAGE_SIZE, &wlp->uuid); - buf[result++] = '\n'; - mutex_unlock(&wlp->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wlp_uuid_show); - -/** - * Store a new UUID for this host - * - * According to the spec this should be encoded as an octet string in the - * order the octets are shown in string representation in RFC 4122 (WLP - * 0.99 [Table 6]) - * - * We do not check value provided by user. - */ -ssize_t wlp_uuid_store(struct wlp *wlp, const char *buf, size_t size) -{ - ssize_t result; - struct wlp_uuid uuid; - - mutex_lock(&wlp->mutex); - result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx " - "%02hhx %02hhx %02hhx %02hhx ", - &uuid.data[0] , &uuid.data[1], - &uuid.data[2] , &uuid.data[3], - &uuid.data[4] , &uuid.data[5], - &uuid.data[6] , &uuid.data[7], - &uuid.data[8] , &uuid.data[9], - &uuid.data[10], &uuid.data[11], - &uuid.data[12], &uuid.data[13], - &uuid.data[14], &uuid.data[15]); - if (result != 16) { - result = -EINVAL; - goto error; - } - wlp->uuid = uuid; -error: - mutex_unlock(&wlp->mutex); - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_uuid_store); - -/** - * Show contents of members of device information structure - */ -#define wlp_dev_info_show(type) \ -ssize_t wlp_dev_##type##_show(struct wlp *wlp, char *buf) \ -{ \ - ssize_t result = 0; \ - mutex_lock(&wlp->mutex); \ - if (wlp->dev_info == NULL) { \ - result = __wlp_setup_device_info(wlp); \ - if (result < 0) \ - goto out; \ - } \ - result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->dev_info->type);\ -out: \ - mutex_unlock(&wlp->mutex); \ - return result; \ -} \ -EXPORT_SYMBOL_GPL(wlp_dev_##type##_show); - -wlp_dev_info_show(name) -wlp_dev_info_show(model_name) -wlp_dev_info_show(model_nr) -wlp_dev_info_show(manufacturer) -wlp_dev_info_show(serial) - -/** - * Store contents of members of device information structure - */ -#define wlp_dev_info_store(type, len) \ -ssize_t wlp_dev_##type##_store(struct wlp *wlp, const char *buf, size_t size)\ -{ \ - ssize_t result; \ - char format[10]; \ - mutex_lock(&wlp->mutex); \ - if (wlp->dev_info == NULL) { \ - result = __wlp_alloc_device_info(wlp); \ - if (result < 0) \ - goto out; \ - } \ - memset(wlp->dev_info->type, 0, sizeof(wlp->dev_info->type)); \ - sprintf(format, "%%%uc", len); \ - result = sscanf(buf, format, wlp->dev_info->type); \ -out: \ - mutex_unlock(&wlp->mutex); \ - return result < 0 ? result : size; \ -} \ -EXPORT_SYMBOL_GPL(wlp_dev_##type##_store); - -wlp_dev_info_store(name, 32) -wlp_dev_info_store(manufacturer, 64) -wlp_dev_info_store(model_name, 32) -wlp_dev_info_store(model_nr, 32) -wlp_dev_info_store(serial, 32) - -static -const char *__wlp_dev_category[] = { - [WLP_DEV_CAT_COMPUTER] = "Computer", - [WLP_DEV_CAT_INPUT] = "Input device", - [WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER] = "Printer, scanner, FAX, or " - "Copier", - [WLP_DEV_CAT_CAMERA] = "Camera", - [WLP_DEV_CAT_STORAGE] = "Storage Network", - [WLP_DEV_CAT_INFRASTRUCTURE] = "Infrastructure", - [WLP_DEV_CAT_DISPLAY] = "Display", - [WLP_DEV_CAT_MULTIM] = "Multimedia device", - [WLP_DEV_CAT_GAMING] = "Gaming device", - [WLP_DEV_CAT_TELEPHONE] = "Telephone", - [WLP_DEV_CAT_OTHER] = "Other", -}; - -static -const char *wlp_dev_category_str(unsigned cat) -{ - if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE) - || cat == WLP_DEV_CAT_OTHER) - return __wlp_dev_category[cat]; - return "unknown category"; -} - -ssize_t wlp_dev_prim_category_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) - goto out; - } - result = scnprintf(buf, PAGE_SIZE, "%s\n", - wlp_dev_category_str(wlp->dev_info->prim_dev_type.category)); -out: - mutex_unlock(&wlp->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_category_show); - -ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf, - size_t size) -{ - ssize_t result; - u16 cat; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_alloc_device_info(wlp); - if (result < 0) - goto out; - } - result = sscanf(buf, "%hu", &cat); - if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE) - || cat == WLP_DEV_CAT_OTHER) - wlp->dev_info->prim_dev_type.category = cat; - else - result = -EINVAL; -out: - mutex_unlock(&wlp->mutex); - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_category_store); - -ssize_t wlp_dev_prim_OUI_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) - goto out; - } - result = scnprintf(buf, PAGE_SIZE, "%02x:%02x:%02x\n", - wlp->dev_info->prim_dev_type.OUI[0], - wlp->dev_info->prim_dev_type.OUI[1], - wlp->dev_info->prim_dev_type.OUI[2]); -out: - mutex_unlock(&wlp->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_show); - -ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size) -{ - ssize_t result; - u8 OUI[3]; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_alloc_device_info(wlp); - if (result < 0) - goto out; - } - result = sscanf(buf, "%hhx:%hhx:%hhx", - &OUI[0], &OUI[1], &OUI[2]); - if (result != 3) { - result = -EINVAL; - goto out; - } else - memcpy(wlp->dev_info->prim_dev_type.OUI, OUI, sizeof(OUI)); -out: - mutex_unlock(&wlp->mutex); - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_store); - - -ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) - goto out; - } - result = scnprintf(buf, PAGE_SIZE, "%u\n", - wlp->dev_info->prim_dev_type.OUIsubdiv); -out: - mutex_unlock(&wlp->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_show); - -ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *wlp, const char *buf, - size_t size) -{ - ssize_t result; - unsigned sub; - u8 max_sub = ~0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_alloc_device_info(wlp); - if (result < 0) - goto out; - } - result = sscanf(buf, "%u", &sub); - if (sub <= max_sub) - wlp->dev_info->prim_dev_type.OUIsubdiv = sub; - else - result = -EINVAL; -out: - mutex_unlock(&wlp->mutex); - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_store); - -ssize_t wlp_dev_prim_subcat_show(struct wlp *wlp, char *buf) -{ - ssize_t result = 0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_setup_device_info(wlp); - if (result < 0) - goto out; - } - result = scnprintf(buf, PAGE_SIZE, "%u\n", - wlp->dev_info->prim_dev_type.subID); -out: - mutex_unlock(&wlp->mutex); - return result; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_show); - -ssize_t wlp_dev_prim_subcat_store(struct wlp *wlp, const char *buf, - size_t size) -{ - ssize_t result; - unsigned sub; - __le16 max_sub = ~0; - mutex_lock(&wlp->mutex); - if (wlp->dev_info == NULL) { - result = __wlp_alloc_device_info(wlp); - if (result < 0) - goto out; - } - result = sscanf(buf, "%u", &sub); - if (sub <= max_sub) - wlp->dev_info->prim_dev_type.subID = sub; - else - result = -EINVAL; -out: - mutex_unlock(&wlp->mutex); - return result < 0 ? result : size; -} -EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_store); - -/** - * Subsystem implementation for interaction with individual WSS via sysfs - * - * Followed instructions for subsystem in Documentation/filesystems/sysfs.txt - */ - -#define kobj_to_wlp_wss(obj) container_of(obj, struct wlp_wss, kobj) -#define attr_to_wlp_wss_attr(_attr) \ - container_of(_attr, struct wlp_wss_attribute, attr) - -/** - * Sysfs subsystem: forward read calls - * - * Sysfs operation for forwarding read call to the show method of the - * attribute owner - */ -static -ssize_t wlp_wss_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr); - struct wlp_wss *wss = kobj_to_wlp_wss(kobj); - ssize_t ret = -EIO; - - if (wss_attr->show) - ret = wss_attr->show(wss, buf); - return ret; -} -/** - * Sysfs subsystem: forward write calls - * - * Sysfs operation for forwarding write call to the store method of the - * attribute owner - */ -static -ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr); - struct wlp_wss *wss = kobj_to_wlp_wss(kobj); - ssize_t ret = -EIO; - - if (wss_attr->store) - ret = wss_attr->store(wss, buf, count); - return ret; -} - -static -struct sysfs_ops wss_sysfs_ops = { - .show = wlp_wss_attr_show, - .store = wlp_wss_attr_store, -}; - -struct kobj_type wss_ktype = { - .release = wlp_wss_release, - .sysfs_ops = &wss_sysfs_ops, -}; - - -/** - * Sysfs files for individual WSS - */ - -/** - * Print static properties of this WSS - * - * The name of a WSS may not be null teminated. It's max size is 64 bytes - * so we copy it to a larger array just to make sure we print sane data. - */ -static ssize_t wlp_wss_properties_show(struct wlp_wss *wss, char *buf) -{ - int result = 0; - - if (mutex_lock_interruptible(&wss->mutex)) - goto out; - result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE); - mutex_unlock(&wss->mutex); -out: - return result; -} -WSS_ATTR(properties, S_IRUGO, wlp_wss_properties_show, NULL); - -/** - * Print all connected members of this WSS - * The EDA cache contains all members of WSS neighborhood. - */ -static ssize_t wlp_wss_members_show(struct wlp_wss *wss, char *buf) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - return wlp_eda_show(wlp, buf); -} -WSS_ATTR(members, S_IRUGO, wlp_wss_members_show, NULL); - -static -const char *__wlp_strstate[] = { - "none", - "partially enrolled", - "enrolled", - "active", - "connected", -}; - -static const char *wlp_wss_strstate(unsigned state) -{ - if (state >= ARRAY_SIZE(__wlp_strstate)) - return "unknown state"; - return __wlp_strstate[state]; -} - -/* - * Print current state of this WSS - */ -static ssize_t wlp_wss_state_show(struct wlp_wss *wss, char *buf) -{ - int result = 0; - - if (mutex_lock_interruptible(&wss->mutex)) - goto out; - result = scnprintf(buf, PAGE_SIZE, "%s\n", - wlp_wss_strstate(wss->state)); - mutex_unlock(&wss->mutex); -out: - return result; -} -WSS_ATTR(state, S_IRUGO, wlp_wss_state_show, NULL); - - -static -struct attribute *wss_attrs[] = { - &wss_attr_properties.attr, - &wss_attr_members.attr, - &wss_attr_state.attr, - NULL, -}; - -struct attribute_group wss_attr_group = { - .name = NULL, /* we want them in the same directory */ - .attrs = wss_attrs, -}; diff --git a/trunk/drivers/uwb/wlp/txrx.c b/trunk/drivers/uwb/wlp/txrx.c deleted file mode 100644 index c701bd1a2887..000000000000 --- a/trunk/drivers/uwb/wlp/txrx.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * Message exchange infrastructure - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: Docs - * - */ - -#include -#include -#define D_LOCAL 5 -#include -#include "wlp-internal.h" - - -/** - * Direct incoming association msg to correct parsing routine - * - * We only expect D1, E1, C1, C3 messages as new. All other incoming - * association messages should form part of an established session that is - * handled elsewhere. - * The handling of these messages often require calling sleeping functions - * - this cannot be done in interrupt context. We use the kernel's - * workqueue to handle these messages. - */ -static -void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, - struct uwb_dev_addr *src) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *assoc = (void *) skb->data; - struct wlp_assoc_frame_ctx *frame_ctx; - d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); - frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC); - if (frame_ctx == NULL) { - dev_err(dev, "WLP: Unable to allocate memory for association " - "frame handling.\n"); - kfree_skb(skb); - goto out; - } - frame_ctx->wlp = wlp; - frame_ctx->skb = skb; - frame_ctx->src = *src; - switch (assoc->type) { - case WLP_ASSOC_D1: - d_printf(5, dev, "Received a D1 frame.\n"); - INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame); - schedule_work(&frame_ctx->ws); - break; - case WLP_ASSOC_E1: - d_printf(5, dev, "Received a E1 frame. FIXME?\n"); - kfree_skb(skb); /* Temporary until we handle it */ - kfree(frame_ctx); /* Temporary until we handle it */ - break; - case WLP_ASSOC_C1: - d_printf(5, dev, "Received a C1 frame.\n"); - INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame); - schedule_work(&frame_ctx->ws); - break; - case WLP_ASSOC_C3: - d_printf(5, dev, "Received a C3 frame.\n"); - INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame); - schedule_work(&frame_ctx->ws); - break; - default: - dev_err(dev, "Received unexpected association frame. " - "Type = %d \n", assoc->type); - kfree_skb(skb); - kfree(frame_ctx); - break; - } -out: - d_fnend(5, dev, "wlp %p\n", wlp); -} - -/** - * Process incoming association frame - * - * Although it could be possible to deal with some incoming association - * messages without creating a new session we are keeping things simple. We - * do not accept new association messages if there is a session in progress - * and the messages do not belong to that session. - * - * If an association message arrives that causes the creation of a session - * (WLP_ASSOC_E1) while we are in the process of creating a session then we - * rely on the neighbor mutex to protect the data. That is, the new session - * will not be started until the previous is completed. - */ -static -void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, - struct uwb_dev_addr *src) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_frame_assoc *assoc = (void *) skb->data; - struct wlp_session *session = wlp->session; - u8 version; - d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); - - if (wlp_get_version(wlp, &assoc->version, &version, - sizeof(assoc->version)) < 0) - goto error; - if (version != WLP_VERSION) { - dev_err(dev, "Unsupported WLP version in association " - "message.\n"); - goto error; - } - if (session != NULL) { - /* Function that created this session is still holding the - * &wlp->mutex to protect this session. */ - if (assoc->type == session->exp_message || - assoc->type == WLP_ASSOC_F0) { - if (!memcmp(&session->neighbor_addr, src, - sizeof(*src))) { - session->data = skb; - (session->cb)(wlp); - } else { - dev_err(dev, "Received expected message from " - "unexpected source. Expected message " - "%d or F0 from %02x:%02x, but received " - "it from %02x:%02x. Dropping.\n", - session->exp_message, - session->neighbor_addr.data[1], - session->neighbor_addr.data[0], - src->data[1], src->data[0]); - goto error; - } - } else { - dev_err(dev, "Association already in progress. " - "Dropping.\n"); - goto error; - } - } else { - wlp_direct_assoc_frame(wlp, skb, src); - } - d_fnend(5, dev, "wlp %p\n", wlp); - return; -error: - kfree_skb(skb); - d_fnend(5, dev, "wlp %p\n", wlp); -} - -/** - * Verify incoming frame is from connected neighbor, prep to pass to WLP client - * - * Verification proceeds according to WLP 0.99 [7.3.1]. The source address - * is used to determine which neighbor is sending the frame and the WSS tag - * is used to know to which WSS the frame belongs (we only support one WSS - * so this test is straight forward). - * With the WSS found we need to ensure that we are connected before - * allowing the exchange of data frames. - */ -static -int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, - struct uwb_dev_addr *src) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = -EINVAL; - struct wlp_eda_node eda_entry; - struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data; - - d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); - /*verify*/ - result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Incoming frame is from unknown " - "neighbor %02x:%02x.\n", src->data[1], - src->data[0]); - goto out; - } - if (hdr->tag != eda_entry.tag) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Tag of incoming frame from " - "%02x:%02x does not match expected tag. " - "Received 0x%02x, expected 0x%02x. \n", - src->data[1], src->data[0], hdr->tag, - eda_entry.tag); - result = -EINVAL; - goto out; - } - if (eda_entry.state != WLP_WSS_CONNECTED) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Incoming frame from " - "%02x:%02x does is not from connected WSS.\n", - src->data[1], src->data[0]); - result = -EINVAL; - goto out; - } - /*prep*/ - skb_pull(skb, sizeof(*hdr)); -out: - d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); - return result; -} - -/** - * Receive a WLP frame from device - * - * @returns: 1 if calling function should free the skb - * 0 if it successfully handled skb and freed it - * 0 if error occured, will free skb in this case - */ -int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, - struct uwb_dev_addr *src) -{ - unsigned len = skb->len; - void *ptr = skb->data; - struct wlp_frame_hdr *hdr; - int result = 0; - - d_fnstart(6, dev, "skb (%p), len (%u)\n", skb, len); - if (len < sizeof(*hdr)) { - dev_err(dev, "Not enough data to parse WLP header.\n"); - result = -EINVAL; - goto out; - } - hdr = ptr; - d_dump(6, dev, hdr, sizeof(*hdr)); - if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) { - dev_err(dev, "Not a WLP frame type.\n"); - result = -EINVAL; - goto out; - } - switch (hdr->type) { - case WLP_FRAME_STANDARD: - if (len < sizeof(struct wlp_frame_std_abbrv_hdr)) { - dev_err(dev, "Not enough data to parse Standard " - "WLP header.\n"); - goto out; - } - result = wlp_verify_prep_rx_frame(wlp, skb, src); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Verification of frame " - "from neighbor %02x:%02x failed.\n", - src->data[1], src->data[0]); - goto out; - } - result = 1; - break; - case WLP_FRAME_ABBREVIATED: - dev_err(dev, "Abbreviated frame received. FIXME?\n"); - kfree_skb(skb); - break; - case WLP_FRAME_CONTROL: - dev_err(dev, "Control frame received. FIXME?\n"); - kfree_skb(skb); - break; - case WLP_FRAME_ASSOCIATION: - if (len < sizeof(struct wlp_frame_assoc)) { - dev_err(dev, "Not enough data to parse Association " - "WLP header.\n"); - goto out; - } - d_printf(5, dev, "Association frame received.\n"); - wlp_receive_assoc_frame(wlp, skb, src); - break; - default: - dev_err(dev, "Invalid frame received.\n"); - result = -EINVAL; - break; - } -out: - if (result < 0) { - kfree_skb(skb); - result = 0; - } - d_fnend(6, dev, "skb (%p)\n", skb); - return result; -} -EXPORT_SYMBOL_GPL(wlp_receive_frame); - - -/** - * Verify frame from network stack, prepare for further transmission - * - * @skb: the socket buffer that needs to be prepared for transmission (it - * is in need of a WLP header). If this is a broadcast frame we take - * over the entire transmission. - * If it is a unicast the WSS connection should already be established - * and transmission will be done by the calling function. - * @dst: On return this will contain the device address to which the - * frame is destined. - * @returns: 0 on success no tx : WLP header sucessfully applied to skb buffer, - * calling function can proceed with tx - * 1 on success with tx : WLP will take over transmission of this - * frame - * <0 on error - * - * The network stack (WLP client) is attempting to transmit a frame. We can - * only transmit data if a local WSS is at least active (connection will be - * done here if this is a broadcast frame and neighbor also has the WSS - * active). - * - * The frame can be either broadcast or unicast. Broadcast in a WSS is - * supported via multicast, but we don't support multicast yet (until - * devices start to support MAB IEs). If a broadcast frame needs to be - * transmitted it is treated as a unicast frame to each neighbor. In this - * case the WLP takes over transmission of the skb and returns 1 - * to the caller to indicate so. Also, in this case, if a neighbor has the - * same WSS activated but is not connected then the WSS connection will be - * done at this time. The neighbor's virtual address will be learned at - * this time. - * - * The destination address in a unicast frame is the virtual address of the - * neighbor. This address only becomes known when a WSS connection is - * established. We thus rely on a broadcast frame to trigger the setup of - * WSS connections to all neighbors before we are able to send unicast - * frames to them. This seems reasonable as IP would usually use ARP first - * before any unicast frames are sent. - * - * If we are already connected to the neighbor (neighbor's virtual address - * is known) we just prepare the WLP header and the caller will continue to - * send the frame. - * - * A failure in this function usually indicates something that cannot be - * fixed automatically. So, if this function fails (@return < 0) the calling - * function should not retry to send the frame as it will very likely keep - * failing. - * - */ -int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, - struct sk_buff *skb, struct uwb_dev_addr *dst) -{ - int result = -EINVAL; - struct ethhdr *eth_hdr = (void *) skb->data; - - d_fnstart(6, dev, "wlp (%p), skb (%p) \n", wlp, skb); - if (is_broadcast_ether_addr(eth_hdr->h_dest)) { - d_printf(6, dev, "WLP: handling broadcast frame. \n"); - result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "Unable to handle broadcast " - "frame from WLP client.\n"); - goto out; - } - dev_kfree_skb_irq(skb); - result = 1; - /* Frame will be transmitted by WLP. */ - } else { - d_printf(6, dev, "WLP: handling unicast frame. \n"); - result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst, - wlp_wss_prep_hdr, skb); - if (unlikely(result < 0)) { - if (printk_ratelimit()) - dev_err(dev, "Unable to prepare " - "skb for transmission. \n"); - goto out; - } - } -out: - d_fnend(6, dev, "wlp (%p), skb (%p). result = %d \n", wlp, skb, result); - return result; -} -EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame); diff --git a/trunk/drivers/uwb/wlp/wlp-internal.h b/trunk/drivers/uwb/wlp/wlp-internal.h deleted file mode 100644 index 1c94fabfb1a7..000000000000 --- a/trunk/drivers/uwb/wlp/wlp-internal.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * Internal API - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#ifndef __WLP_INTERNAL_H__ -#define __WLP_INTERNAL_H__ - -/** - * State of WSS connection - * - * A device needs to connect to a neighbor in an activated WSS before data - * can be transmitted. The spec also distinguishes between a new connection - * attempt and a connection attempt after previous connection attempts. The - * state WLP_WSS_CONNECT_FAILED is used for this scenario. See WLP 0.99 - * [7.2.6] - */ -enum wlp_wss_connect { - WLP_WSS_UNCONNECTED = 0, - WLP_WSS_CONNECTED, - WLP_WSS_CONNECT_FAILED, -}; - -extern struct kobj_type wss_ktype; -extern struct attribute_group wss_attr_group; - -extern int uwb_rc_ie_add(struct uwb_rc *, const struct uwb_ie_hdr *, size_t); -extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); - - -/* This should be changed to a dynamic array where entries are sorted - * by eth_addr and search is done in a binary form - * - * Although thinking twice about it: this technologie's maximum reach - * is 10 meters...unless you want to pack too much stuff in around - * your radio controller/WLP device, the list will probably not be - * too big. - * - * In any case, there is probably some data structure in the kernel - * than we could reused for that already. - * - * The below structure is really just good while we support one WSS per - * host. - */ -struct wlp_eda_node { - struct list_head list_node; - unsigned char eth_addr[ETH_ALEN]; - struct uwb_dev_addr dev_addr; - struct wlp_wss *wss; - unsigned char virt_addr[ETH_ALEN]; - u8 tag; - enum wlp_wss_connect state; -}; - -typedef int (*wlp_eda_for_each_f)(struct wlp *, struct wlp_eda_node *, void *); - -extern void wlp_eda_init(struct wlp_eda *); -extern void wlp_eda_release(struct wlp_eda *); -extern int wlp_eda_create_node(struct wlp_eda *, - const unsigned char eth_addr[ETH_ALEN], - const struct uwb_dev_addr *); -extern void wlp_eda_rm_node(struct wlp_eda *, const struct uwb_dev_addr *); -extern int wlp_eda_update_node(struct wlp_eda *, - const struct uwb_dev_addr *, - struct wlp_wss *, - const unsigned char virt_addr[ETH_ALEN], - const u8, const enum wlp_wss_connect); -extern int wlp_eda_update_node_state(struct wlp_eda *, - const struct uwb_dev_addr *, - const enum wlp_wss_connect); - -extern int wlp_copy_eda_node(struct wlp_eda *, struct uwb_dev_addr *, - struct wlp_eda_node *); -extern int wlp_eda_for_each(struct wlp_eda *, wlp_eda_for_each_f , void *); -extern int wlp_eda_for_virtual(struct wlp_eda *, - const unsigned char eth_addr[ETH_ALEN], - struct uwb_dev_addr *, - wlp_eda_for_each_f , void *); - - -extern void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *); - -extern size_t wlp_wss_key_print(char *, size_t, u8 *); - -/* Function called when no more references to WSS exists */ -extern void wlp_wss_release(struct kobject *); - -extern void wlp_wss_reset(struct wlp_wss *); -extern int wlp_wss_create_activate(struct wlp_wss *, struct wlp_uuid *, - char *, unsigned, unsigned); -extern int wlp_wss_enroll_activate(struct wlp_wss *, struct wlp_uuid *, - struct uwb_dev_addr *); -extern ssize_t wlp_discover(struct wlp *); - -extern int wlp_enroll_neighbor(struct wlp *, struct wlp_neighbor_e *, - struct wlp_wss *, struct wlp_uuid *); -extern int wlp_wss_is_active(struct wlp *, struct wlp_wss *, - struct uwb_dev_addr *); - -struct wlp_assoc_conn_ctx { - struct work_struct ws; - struct wlp *wlp; - struct sk_buff *skb; - struct wlp_eda_node eda_entry; -}; - - -extern int wlp_wss_connect_prep(struct wlp *, struct wlp_eda_node *, void *); -extern int wlp_wss_send_copy(struct wlp *, struct wlp_eda_node *, void *); - - -/* Message handling */ -struct wlp_assoc_frame_ctx { - struct work_struct ws; - struct wlp *wlp; - struct sk_buff *skb; - struct uwb_dev_addr src; -}; - -extern int wlp_wss_prep_hdr(struct wlp *, struct wlp_eda_node *, void *); -extern void wlp_handle_d1_frame(struct work_struct *); -extern int wlp_parse_d2_frame_to_cache(struct wlp *, struct sk_buff *, - struct wlp_neighbor_e *); -extern int wlp_parse_d2_frame_to_enroll(struct wlp_wss *, struct sk_buff *, - struct wlp_neighbor_e *, - struct wlp_uuid *); -extern void wlp_handle_c1_frame(struct work_struct *); -extern void wlp_handle_c3_frame(struct work_struct *); -extern int wlp_parse_c3c4_frame(struct wlp *, struct sk_buff *, - struct wlp_uuid *, u8 *, - struct uwb_mac_addr *); -extern int wlp_parse_f0(struct wlp *, struct sk_buff *); -extern int wlp_send_assoc_frame(struct wlp *, struct wlp_wss *, - struct uwb_dev_addr *, enum wlp_assoc_type); -extern ssize_t wlp_get_version(struct wlp *, struct wlp_attr_version *, - u8 *, ssize_t); -extern ssize_t wlp_get_wssid(struct wlp *, struct wlp_attr_wssid *, - struct wlp_uuid *, ssize_t); -extern int __wlp_alloc_device_info(struct wlp *); -extern int __wlp_setup_device_info(struct wlp *); - -extern struct wlp_wss_attribute wss_attribute_properties; -extern struct wlp_wss_attribute wss_attribute_members; -extern struct wlp_wss_attribute wss_attribute_state; - -static inline -size_t wlp_wss_uuid_print(char *buf, size_t bufsize, struct wlp_uuid *uuid) -{ - size_t result; - - result = scnprintf(buf, bufsize, - "%02x:%02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x", - uuid->data[0], uuid->data[1], - uuid->data[2], uuid->data[3], - uuid->data[4], uuid->data[5], - uuid->data[6], uuid->data[7], - uuid->data[8], uuid->data[9], - uuid->data[10], uuid->data[11], - uuid->data[12], uuid->data[13], - uuid->data[14], uuid->data[15]); - return result; -} - -/** - * FIXME: How should a nonce be displayed? - */ -static inline -size_t wlp_wss_nonce_print(char *buf, size_t bufsize, struct wlp_nonce *nonce) -{ - size_t result; - - result = scnprintf(buf, bufsize, - "%02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x", - nonce->data[0], nonce->data[1], - nonce->data[2], nonce->data[3], - nonce->data[4], nonce->data[5], - nonce->data[6], nonce->data[7], - nonce->data[8], nonce->data[9], - nonce->data[10], nonce->data[11], - nonce->data[12], nonce->data[13], - nonce->data[14], nonce->data[15]); - return result; -} - - -static inline -void wlp_session_cb(struct wlp *wlp) -{ - struct completion *completion = wlp->session->cb_priv; - complete(completion); -} - -static inline -int wlp_uuid_is_set(struct wlp_uuid *uuid) -{ - struct wlp_uuid zero_uuid = { .data = { 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} }; - - if (!memcmp(uuid, &zero_uuid, sizeof(*uuid))) - return 0; - return 1; -} - -#endif /* __WLP_INTERNAL_H__ */ diff --git a/trunk/drivers/uwb/wlp/wlp-lc.c b/trunk/drivers/uwb/wlp/wlp-lc.c deleted file mode 100644 index 0799402e73fb..000000000000 --- a/trunk/drivers/uwb/wlp/wlp-lc.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * - * Copyright (C) 2005-2006 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - */ - -#include -#define D_LOCAL 6 -#include -#include "wlp-internal.h" - - -static -void wlp_neighbor_init(struct wlp_neighbor_e *neighbor) -{ - INIT_LIST_HEAD(&neighbor->wssid); -} - -/** - * Create area for device information storage - * - * wlp->mutex must be held - */ -int __wlp_alloc_device_info(struct wlp *wlp) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - BUG_ON(wlp->dev_info != NULL); - wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL); - if (wlp->dev_info == NULL) { - dev_err(dev, "WLP: Unable to allocate memory for " - "device information.\n"); - return -ENOMEM; - } - return 0; -} - - -/** - * Fill in device information using function provided by driver - * - * wlp->mutex must be held - */ -static -void __wlp_fill_device_info(struct wlp *wlp) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - - BUG_ON(wlp->fill_device_info == NULL); - d_printf(6, dev, "Retrieving device information " - "from device driver.\n"); - wlp->fill_device_info(wlp, wlp->dev_info); -} - -/** - * Setup device information - * - * Allocate area for device information and populate it. - * - * wlp->mutex must be held - */ -int __wlp_setup_device_info(struct wlp *wlp) -{ - int result; - struct device *dev = &wlp->rc->uwb_dev.dev; - - result = __wlp_alloc_device_info(wlp); - if (result < 0) { - dev_err(dev, "WLP: Unable to allocate area for " - "device information.\n"); - return result; - } - __wlp_fill_device_info(wlp); - return 0; -} - -/** - * Remove information about neighbor stored temporarily - * - * Information learned during discovey should only be stored when the - * device enrolls in the neighbor's WSS. We do need to store this - * information temporarily in order to present it to the user. - * - * We are only interested in keeping neighbor WSS information if that - * neighbor is accepting enrollment. - * - * should be called with wlp->nbmutex held - */ -void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor) -{ - struct wlp_wssid_e *wssid_e, *next; - u8 keep; - if (!list_empty(&neighbor->wssid)) { - list_for_each_entry_safe(wssid_e, next, &neighbor->wssid, - node) { - if (wssid_e->info != NULL) { - keep = wssid_e->info->accept_enroll; - kfree(wssid_e->info); - wssid_e->info = NULL; - if (!keep) { - list_del(&wssid_e->node); - kfree(wssid_e); - } - } - } - } - if (neighbor->info != NULL) { - kfree(neighbor->info); - neighbor->info = NULL; - } -} - -/** - * Populate WLP neighborhood cache with neighbor information - * - * A new neighbor is found. If it is discoverable then we add it to the - * neighborhood cache. - * - */ -static -int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev) -{ - int result = 0; - int discoverable; - struct wlp_neighbor_e *neighbor; - - d_fnstart(6, &dev->dev, "uwb %p \n", dev); - d_printf(6, &dev->dev, "Found neighbor device %02x:%02x \n", - dev->dev_addr.data[1], dev->dev_addr.data[0]); - /** - * FIXME: - * Use contents of WLP IE found in beacon cache to determine if - * neighbor is discoverable. - * The device does not support WLP IE yet so this still needs to be - * done. Until then we assume all devices are discoverable. - */ - discoverable = 1; /* will be changed when FIXME disappears */ - if (discoverable) { - /* Add neighbor to cache for discovery */ - neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL); - if (neighbor == NULL) { - dev_err(&dev->dev, "Unable to create memory for " - "new neighbor. \n"); - result = -ENOMEM; - goto error_no_mem; - } - wlp_neighbor_init(neighbor); - uwb_dev_get(dev); - neighbor->uwb_dev = dev; - list_add(&neighbor->node, &wlp->neighbors); - } -error_no_mem: - d_fnend(6, &dev->dev, "uwb %p, result = %d \n", dev, result); - return result; -} - -/** - * Remove one neighbor from cache - */ -static -void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor) -{ - struct wlp_wssid_e *wssid_e, *next_wssid_e; - - list_for_each_entry_safe(wssid_e, next_wssid_e, - &neighbor->wssid, node) { - list_del(&wssid_e->node); - kfree(wssid_e); - } - uwb_dev_put(neighbor->uwb_dev); - list_del(&neighbor->node); - kfree(neighbor); -} - -/** - * Clear entire neighborhood cache. - */ -static -void __wlp_neighbors_release(struct wlp *wlp) -{ - struct wlp_neighbor_e *neighbor, *next; - if (list_empty(&wlp->neighbors)) - return; - list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) { - __wlp_neighbor_release(neighbor); - } -} - -static -void wlp_neighbors_release(struct wlp *wlp) -{ - mutex_lock(&wlp->nbmutex); - __wlp_neighbors_release(wlp); - mutex_unlock(&wlp->nbmutex); -} - - - -/** - * Send D1 message to neighbor, receive D2 message - * - * @neighbor: neighbor to which D1 message will be sent - * @wss: if not NULL, it is an enrollment request for this WSS - * @wssid: if wss not NULL, this is the wssid of the WSS in which we - * want to enroll - * - * A D1/D2 exchange is done for one of two reasons: discovery or - * enrollment. If done for discovery the D1 message is sent to the neighbor - * and the contents of the D2 response is stored in a temporary cache. - * If done for enrollment the @wss and @wssid are provided also. In this - * case the D1 message is sent to the neighbor, the D2 response is parsed - * for enrollment of the WSS with wssid. - * - * &wss->mutex is held - */ -static -int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor, - struct wlp_wss *wss, struct wlp_uuid *wssid) -{ - int result; - struct device *dev = &wlp->rc->uwb_dev.dev; - DECLARE_COMPLETION_ONSTACK(completion); - struct wlp_session session; - struct sk_buff *skb; - struct wlp_frame_assoc *resp; - struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr; - - mutex_lock(&wlp->mutex); - if (!wlp_uuid_is_set(&wlp->uuid)) { - dev_err(dev, "WLP: UUID is not set. Set via sysfs to " - "proceed.\n"); - result = -ENXIO; - goto out; - } - /* Send D1 association frame */ - result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1); - if (result < 0) { - dev_err(dev, "Unable to send D1 frame to neighbor " - "%02x:%02x (%d)\n", dev_addr->data[1], - dev_addr->data[0], result); - d_printf(6, dev, "Add placeholders into buffer next to " - "neighbor information we have (dev address).\n"); - goto out; - } - /* Create session, wait for response */ - session.exp_message = WLP_ASSOC_D2; - session.cb = wlp_session_cb; - session.cb_priv = &completion; - session.neighbor_addr = *dev_addr; - BUG_ON(wlp->session != NULL); - wlp->session = &session; - /* Wait for D2/F0 frame */ - result = wait_for_completion_interruptible_timeout(&completion, - WLP_PER_MSG_TIMEOUT * HZ); - if (result == 0) { - result = -ETIMEDOUT; - dev_err(dev, "Timeout while sending D1 to neighbor " - "%02x:%02x.\n", dev_addr->data[1], - dev_addr->data[0]); - goto error_session; - } - if (result < 0) { - dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - goto error_session; - } - /* Parse message in session->data: it will be either D2 or F0 */ - skb = session.data; - resp = (void *) skb->data; - d_printf(6, dev, "Received response to D1 frame. \n"); - d_dump(6, dev, skb->data, skb->len > 72 ? 72 : skb->len); - - if (resp->type == WLP_ASSOC_F0) { - result = wlp_parse_f0(wlp, skb); - if (result < 0) - dev_err(dev, "WLP: Unable to parse F0 from neighbor " - "%02x:%02x.\n", dev_addr->data[1], - dev_addr->data[0]); - result = -EINVAL; - goto error_resp_parse; - } - if (wss == NULL) { - /* Discovery */ - result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor); - if (result < 0) { - dev_err(dev, "WLP: Unable to parse D2 message from " - "neighbor %02x:%02x for discovery.\n", - dev_addr->data[1], dev_addr->data[0]); - goto error_resp_parse; - } - } else { - /* Enrollment */ - result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor, - wssid); - if (result < 0) { - dev_err(dev, "WLP: Unable to parse D2 message from " - "neighbor %02x:%02x for enrollment.\n", - dev_addr->data[1], dev_addr->data[0]); - goto error_resp_parse; - } - } -error_resp_parse: - kfree_skb(skb); -error_session: - wlp->session = NULL; -out: - mutex_unlock(&wlp->mutex); - return result; -} - -/** - * Enroll into WSS of provided WSSID by using neighbor as registrar - * - * &wss->mutex is held - */ -int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor, - struct wlp_wss *wss, struct wlp_uuid *wssid) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; - struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr; - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", - wlp, neighbor, wss, wssid, buf); - d_printf(6, dev, "Complete me.\n"); - result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid); - if (result < 0) { - dev_err(dev, "WLP: D1/D2 message exchange for enrollment " - "failed. result = %d \n", result); - goto out; - } - if (wss->state != WLP_WSS_STATE_PART_ENROLLED) { - dev_err(dev, "WLP: Unable to enroll into WSS %s using " - "neighbor %02x:%02x. \n", buf, - dev_addr->data[1], dev_addr->data[0]); - result = -EINVAL; - goto out; - } - if (wss->secure_status == WLP_WSS_SECURE) { - dev_err(dev, "FIXME: need to complete secure enrollment.\n"); - result = -EINVAL; - goto error; - } else { - wss->state = WLP_WSS_STATE_ENROLLED; - d_printf(2, dev, "WLP: Success Enrollment into unsecure WSS " - "%s using neighbor %02x:%02x. \n", buf, - dev_addr->data[1], dev_addr->data[0]); - } - - d_fnend(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", - wlp, neighbor, wss, wssid, buf); -out: - return result; -error: - wlp_wss_reset(wss); - return result; -} - -/** - * Discover WSS information of neighbor's active WSS - */ -static -int wlp_discover_neighbor(struct wlp *wlp, - struct wlp_neighbor_e *neighbor) -{ - return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL); -} - - -/** - * Each neighbor in the neighborhood cache is discoverable. Discover it. - * - * Discovery is done through sending of D1 association frame and parsing - * the D2 association frame response. Only wssid from D2 will be included - * in neighbor cache, rest is just displayed to user and forgotten. - * - * The discovery is not done in parallel. This is simple and enables us to - * maintain only one association context. - * - * The discovery of one neighbor does not affect the other, but if the - * discovery of a neighbor fails it is removed from the neighborhood cache. - */ -static -int wlp_discover_all_neighbors(struct wlp *wlp) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_neighbor_e *neighbor, *next; - - list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) { - result = wlp_discover_neighbor(wlp, neighbor); - if (result < 0) { - dev_err(dev, "WLP: Unable to discover neighbor " - "%02x:%02x, removing from neighborhood. \n", - neighbor->uwb_dev->dev_addr.data[1], - neighbor->uwb_dev->dev_addr.data[0]); - __wlp_neighbor_release(neighbor); - } - } - return result; -} - -static int wlp_add_neighbor_helper(struct device *dev, void *priv) -{ - struct wlp *wlp = priv; - struct uwb_dev *uwb_dev = to_uwb_dev(dev); - - return wlp_add_neighbor(wlp, uwb_dev); -} - -/** - * Discover WLP neighborhood - * - * Will send D1 association frame to all devices in beacon group that have - * discoverable bit set in WLP IE. D2 frames will be received, information - * displayed to user in @buf. Partial information (from D2 association - * frame) will be cached to assist with future association - * requests. - * - * The discovery of the WLP neighborhood is triggered by the user. This - * should occur infrequently and we thus free current cache and re-allocate - * memory if needed. - * - * If one neighbor fails during initial discovery (determining if it is a - * neighbor or not), we fail all - note that interaction with neighbor has - * not occured at this point so if a failure occurs we know something went wrong - * locally. We thus undo everything. - */ -ssize_t wlp_discover(struct wlp *wlp) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - - d_fnstart(6, dev, "wlp %p \n", wlp); - mutex_lock(&wlp->nbmutex); - /* Clear current neighborhood cache. */ - __wlp_neighbors_release(wlp); - /* Determine which devices in neighborhood. Repopulate cache. */ - result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp); - if (result < 0) { - /* May have partial neighbor information, release all. */ - __wlp_neighbors_release(wlp); - goto error_dev_for_each; - } - /* Discover the properties of devices in neighborhood. */ - result = wlp_discover_all_neighbors(wlp); - /* In case of failure we still print our partial results. */ - if (result < 0) { - dev_err(dev, "Unable to fully discover neighborhood. \n"); - result = 0; - } -error_dev_for_each: - mutex_unlock(&wlp->nbmutex); - d_fnend(6, dev, "wlp %p \n", wlp); - return result; -} - -/** - * Handle events from UWB stack - * - * We handle events conservatively. If a neighbor goes off the air we - * remove it from the neighborhood. If an association process is in - * progress this function will block waiting for the nbmutex to become - * free. The association process will thus be allowed to complete before it - * is removed. - */ -static -void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, - enum uwb_notifs event) -{ - struct wlp *wlp = _wlp; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_neighbor_e *neighbor, *next; - int result; - switch (event) { - case UWB_NOTIF_ONAIR: - d_printf(6, dev, "UWB device %02x:%02x is onair\n", - uwb_dev->dev_addr.data[1], - uwb_dev->dev_addr.data[0]); - result = wlp_eda_create_node(&wlp->eda, - uwb_dev->mac_addr.data, - &uwb_dev->dev_addr); - if (result < 0) - dev_err(dev, "WLP: Unable to add new neighbor " - "%02x:%02x to EDA cache.\n", - uwb_dev->dev_addr.data[1], - uwb_dev->dev_addr.data[0]); - break; - case UWB_NOTIF_OFFAIR: - d_printf(6, dev, "UWB device %02x:%02x is offair\n", - uwb_dev->dev_addr.data[1], - uwb_dev->dev_addr.data[0]); - wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr); - mutex_lock(&wlp->nbmutex); - list_for_each_entry_safe(neighbor, next, &wlp->neighbors, - node) { - if (neighbor->uwb_dev == uwb_dev) { - d_printf(6, dev, "Removing device from " - "neighborhood.\n"); - __wlp_neighbor_release(neighbor); - } - } - mutex_unlock(&wlp->nbmutex); - break; - default: - dev_err(dev, "don't know how to handle event %d from uwb\n", - event); - } -} - -int wlp_setup(struct wlp *wlp, struct uwb_rc *rc) -{ - struct device *dev = &rc->uwb_dev.dev; - int result; - - d_fnstart(6, dev, "wlp %p\n", wlp); - BUG_ON(wlp->fill_device_info == NULL); - BUG_ON(wlp->xmit_frame == NULL); - BUG_ON(wlp->stop_queue == NULL); - BUG_ON(wlp->start_queue == NULL); - wlp->rc = rc; - wlp_eda_init(&wlp->eda);/* Set up address cache */ - wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; - wlp->uwb_notifs_handler.data = wlp; - uwb_notifs_register(rc, &wlp->uwb_notifs_handler); - - uwb_pal_init(&wlp->pal); - result = uwb_pal_register(rc, &wlp->pal); - if (result < 0) - uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); - - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); - return result; -} -EXPORT_SYMBOL_GPL(wlp_setup); - -void wlp_remove(struct wlp *wlp) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(6, dev, "wlp %p\n", wlp); - wlp_neighbors_release(wlp); - uwb_pal_unregister(wlp->rc, &wlp->pal); - uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); - wlp_eda_release(&wlp->eda); - mutex_lock(&wlp->mutex); - if (wlp->dev_info != NULL) - kfree(wlp->dev_info); - mutex_unlock(&wlp->mutex); - wlp->rc = NULL; - /* We have to use NULL here because this function can be called - * when the device disappeared. */ - d_fnend(6, NULL, "wlp %p\n", wlp); -} -EXPORT_SYMBOL_GPL(wlp_remove); - -/** - * wlp_reset_all - reset the WLP hardware - * @wlp: the WLP device to reset. - * - * This schedules a full hardware reset of the WLP device. The radio - * controller and any other PALs will also be reset. - */ -void wlp_reset_all(struct wlp *wlp) -{ - uwb_rc_reset_all(wlp->rc); -} -EXPORT_SYMBOL_GPL(wlp_reset_all); diff --git a/trunk/drivers/uwb/wlp/wss-lc.c b/trunk/drivers/uwb/wlp/wss-lc.c deleted file mode 100644 index 96b18c9bd6e9..000000000000 --- a/trunk/drivers/uwb/wlp/wss-lc.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * - * Copyright (C) 2007 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * Implementation of the WLP association protocol. - * - * FIXME: Docs - * - * A UWB network interface will configure a WSS through wlp_wss_setup() after - * the interface has been assigned a MAC address, typically after - * "ifconfig" has been called. When the interface goes down it should call - * wlp_wss_remove(). - * - * When the WSS is ready for use the user interacts via sysfs to create, - * discover, and activate WSS. - * - * wlp_wss_enroll_activate() - * - * wlp_wss_create_activate() - * wlp_wss_set_wssid_hash() - * wlp_wss_comp_wssid_hash() - * wlp_wss_sel_bcast_addr() - * wlp_wss_sysfs_add() - * - * Called when no more references to WSS exist: - * wlp_wss_release() - * wlp_wss_reset() - */ - -#include /* for is_valid_ether_addr */ -#include -#include -#define D_LOCAL 5 -#include -#include "wlp-internal.h" - - -size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key) -{ - size_t result; - - result = scnprintf(buf, bufsize, - "%02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x", - key[0], key[1], key[2], key[3], - key[4], key[5], key[6], key[7], - key[8], key[9], key[10], key[11], - key[12], key[13], key[14], key[15]); - return result; -} - -/** - * Compute WSSID hash - * WLP Draft 0.99 [7.2.1] - * - * The WSSID hash for a WSSID is the result of an octet-wise exclusive-OR - * of all octets in the WSSID. - */ -static -u8 wlp_wss_comp_wssid_hash(struct wlp_uuid *wssid) -{ - return wssid->data[0] ^ wssid->data[1] ^ wssid->data[2] - ^ wssid->data[3] ^ wssid->data[4] ^ wssid->data[5] - ^ wssid->data[6] ^ wssid->data[7] ^ wssid->data[8] - ^ wssid->data[9] ^ wssid->data[10] ^ wssid->data[11] - ^ wssid->data[12] ^ wssid->data[13] ^ wssid->data[14] - ^ wssid->data[15]; -} - -/** - * Select a multicast EUI-48 for the WSS broadcast address. - * WLP Draft 0.99 [7.2.1] - * - * Selected based on the WiMedia Alliance OUI, 00-13-88, within the WLP - * range, [01-13-88-00-01-00, 01-13-88-00-01-FF] inclusive. - * - * This address is currently hardcoded. - * FIXME? - */ -static -struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss) -{ - struct uwb_mac_addr bcast = { - .data = { 0x01, 0x13, 0x88, 0x00, 0x01, 0x00 } - }; - return bcast; -} - -/** - * Clear the contents of the WSS structure - all except kobj, mutex, virtual - * - * We do not want to reinitialize - the internal kobj should not change as - * it still points to the parent received during setup. The mutex should - * remain also. We thus just reset values individually. - * The virutal address assigned to WSS will remain the same for the - * lifetime of the WSS. We only reset the fields that can change during its - * lifetime. - */ -void wlp_wss_reset(struct wlp_wss *wss) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(5, dev, "wss (%p) \n", wss); - memset(&wss->wssid, 0, sizeof(wss->wssid)); - wss->hash = 0; - memset(&wss->name[0], 0, sizeof(wss->name)); - memset(&wss->bcast, 0, sizeof(wss->bcast)); - wss->secure_status = WLP_WSS_UNSECURE; - memset(&wss->master_key[0], 0, sizeof(wss->master_key)); - wss->tag = 0; - wss->state = WLP_WSS_STATE_NONE; - d_fnend(5, dev, "wss (%p) \n", wss); -} - -/** - * Create sysfs infrastructure for WSS - * - * The WSS is configured to have the interface as parent (see wlp_wss_setup()) - * a new sysfs directory that includes wssid as its name is created in the - * interface's sysfs directory. The group of files interacting with WSS are - * created also. - */ -static -int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - int result; - - d_fnstart(5, dev, "wss (%p), wssid: %s\n", wss, wssid_str); - result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str); - if (result < 0) - return result; - wss->kobj.ktype = &wss_ktype; - result = kobject_init_and_add(&wss->kobj, - &wss_ktype, wss->kobj.parent, "wlp"); - if (result < 0) { - dev_err(dev, "WLP: Cannot register WSS kobject.\n"); - goto error_kobject_register; - } - result = sysfs_create_group(&wss->kobj, &wss_attr_group); - if (result < 0) { - dev_err(dev, "WLP: Cannot register WSS attributes: %d\n", - result); - goto error_sysfs_create_group; - } - d_fnend(5, dev, "Completed. result = %d \n", result); - return 0; -error_sysfs_create_group: - - kobject_put(&wss->kobj); /* will free name if needed */ - return result; -error_kobject_register: - kfree(wss->kobj.name); - wss->kobj.name = NULL; - wss->kobj.ktype = NULL; - return result; -} - - -/** - * Release WSS - * - * No more references exist to this WSS. We should undo everything that was - * done in wlp_wss_create_activate() except removing the group. The group - * is not removed because an object can be unregistered before the group is - * created. We also undo any additional operations on the WSS after this - * (addition of members). - * - * If memory was allocated for the kobject's name then it will - * be freed by the kobject system during this time. - * - * The EDA cache is removed and reinitilized when the WSS is removed. We - * thus loose knowledge of members of this WSS at that time and need not do - * it here. - */ -void wlp_wss_release(struct kobject *kobj) -{ - struct wlp_wss *wss = container_of(kobj, struct wlp_wss, kobj); - - wlp_wss_reset(wss); -} - -/** - * Enroll into a WSS using provided neighbor as registrar - * - * First search the neighborhood information to learn which neighbor is - * referred to, next proceed with enrollment. - * - * &wss->mutex is held - */ -static -int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid, - struct uwb_dev_addr *dest) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_neighbor_e *neighbor; - char buf[WLP_WSS_UUID_STRSIZE]; - int result = -ENXIO; - struct uwb_dev_addr *dev_addr; - - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wss %p, wssid %s, registrar %02x:%02x \n", - wss, buf, dest->data[1], dest->data[0]); - mutex_lock(&wlp->nbmutex); - list_for_each_entry(neighbor, &wlp->neighbors, node) { - dev_addr = &neighbor->uwb_dev->dev_addr; - if (!memcmp(dest, dev_addr, sizeof(*dest))) { - d_printf(5, dev, "Neighbor %02x:%02x is valid, " - "enrolling. \n", - dev_addr->data[1], dev_addr->data[0]); - result = wlp_enroll_neighbor(wlp, neighbor, wss, - wssid); - break; - } - } - if (result == -ENXIO) - dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n", - dest->data[1], dest->data[0]); - mutex_unlock(&wlp->nbmutex); - d_fnend(5, dev, "wss %p, wssid %s, registrar %02x:%02x, result %d \n", - wss, buf, dest->data[1], dest->data[0], result); - return result; -} - -/** - * Enroll into a WSS previously discovered - * - * User provides WSSID of WSS, search for neighbor that has this WSS - * activated and attempt to enroll. - * - * &wss->mutex is held - */ -static -int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - struct wlp_neighbor_e *neighbor; - struct wlp_wssid_e *wssid_e; - char buf[WLP_WSS_UUID_STRSIZE]; - int result = -ENXIO; - - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wss %p, wssid %s \n", wss, buf); - mutex_lock(&wlp->nbmutex); - list_for_each_entry(neighbor, &wlp->neighbors, node) { - list_for_each_entry(wssid_e, &neighbor->wssid, node) { - if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) { - d_printf(5, dev, "Found WSSID %s in neighbor " - "%02x:%02x cache. \n", buf, - neighbor->uwb_dev->dev_addr.data[1], - neighbor->uwb_dev->dev_addr.data[0]); - result = wlp_enroll_neighbor(wlp, neighbor, - wss, wssid); - if (result == 0) /* enrollment success */ - goto out; - break; - } - } - } -out: - if (result == -ENXIO) - dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf); - mutex_unlock(&wlp->nbmutex); - d_fnend(5, dev, "wss %p, wssid %s, result %d \n", wss, buf, result); - return result; -} - -/** - * Enroll into WSS with provided WSSID, registrar may be provided - * - * @wss: out WSS that will be enrolled - * @wssid: wssid of neighboring WSS that we want to enroll in - * @devaddr: registrar can be specified, will be broadcast (ff:ff) if any - * neighbor can be used as registrar. - * - * &wss->mutex is held - */ -static -int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid, - struct uwb_dev_addr *devaddr) -{ - int result; - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; - struct uwb_dev_addr bcast = {.data = {0xff, 0xff} }; - - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - if (wss->state != WLP_WSS_STATE_NONE) { - dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf); - result = -EEXIST; - goto error; - } - if (!memcmp(&bcast, devaddr, sizeof(bcast))) { - d_printf(5, dev, "Request to enroll in discovered WSS " - "with WSSID %s \n", buf); - result = wlp_wss_enroll_discovered(wss, wssid); - } else { - d_printf(5, dev, "Request to enroll in WSSID %s with " - "registrar %02x:%02x\n", buf, devaddr->data[1], - devaddr->data[0]); - result = wlp_wss_enroll_target(wss, wssid, devaddr); - } - if (result < 0) { - dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n", - buf, result); - goto error; - } - d_printf(2, dev, "Successfully enrolled into WSS %s \n", buf); - result = wlp_wss_sysfs_add(wss, buf); - if (result < 0) { - dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n"); - wlp_wss_reset(wss); - } -error: - return result; - -} - -/** - * Activate given WSS - * - * Prior to activation a WSS must be enrolled. To activate a WSS a device - * includes the WSS hash in the WLP IE in its beacon in each superframe. - * WLP 0.99 [7.2.5]. - * - * The WSS tag is also computed at this time. We only support one activated - * WSS so we can use the hash as a tag - there will never be a conflict. - * - * We currently only support one activated WSS so only one WSS hash is - * included in the WLP IE. - */ -static -int wlp_wss_activate(struct wlp_wss *wss) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - struct uwb_rc *uwb_rc = wlp->rc; - int result; - struct { - struct wlp_ie wlp_ie; - u8 hash; /* only include one hash */ - } ie_data; - - d_fnstart(5, dev, "Activating WSS %p. \n", wss); - BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED); - wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid); - wss->tag = wss->hash; - memset(&ie_data, 0, sizeof(ie_data)); - ie_data.wlp_ie.hdr.element_id = UWB_IE_WLP; - ie_data.wlp_ie.hdr.length = sizeof(ie_data) - sizeof(struct uwb_ie_hdr); - wlp_ie_set_hash_length(&ie_data.wlp_ie, sizeof(ie_data.hash)); - ie_data.hash = wss->hash; - result = uwb_rc_ie_add(uwb_rc, &ie_data.wlp_ie.hdr, - sizeof(ie_data)); - if (result < 0) { - dev_err(dev, "WLP: Unable to add WLP IE to beacon. " - "result = %d.\n", result); - goto error_wlp_ie; - } - wss->state = WLP_WSS_STATE_ACTIVE; - result = 0; -error_wlp_ie: - d_fnend(5, dev, "Activating WSS %p, result = %d \n", wss, result); - return result; -} - -/** - * Enroll in and activate WSS identified by provided WSSID - * - * The neighborhood cache should contain a list of all neighbors and the - * WSS they have activated. Based on that cache we search which neighbor we - * can perform the association process with. The user also has option to - * specify which neighbor it prefers as registrar. - * Successful enrollment is followed by activation. - * Successful activation will create the sysfs directory containing - * specific information regarding this WSS. - */ -int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, - struct uwb_dev_addr *devaddr) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - char buf[WLP_WSS_UUID_STRSIZE]; - - d_fnstart(5, dev, "Enrollment and activation requested. \n"); - mutex_lock(&wss->mutex); - result = wlp_wss_enroll(wss, wssid, devaddr); - if (result < 0) { - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - dev_err(dev, "WLP: Enrollment into WSS %s failed.\n", buf); - goto error_enroll; - } - result = wlp_wss_activate(wss); - if (result < 0) { - dev_err(dev, "WLP: Unable to activate WSS. Undoing enrollment " - "result = %d \n", result); - /* Undo enrollment */ - wlp_wss_reset(wss); - goto error_activate; - } -error_activate: -error_enroll: - mutex_unlock(&wss->mutex); - d_fnend(5, dev, "Completed. result = %d \n", result); - return result; -} - -/** - * Create, enroll, and activate a new WSS - * - * @wssid: new wssid provided by user - * @name: WSS name requested by used. - * @sec_status: security status requested by user - * - * A user requested the creation of a new WSS. All operations are done - * locally. The new WSS will be stored locally, the hash will be included - * in the WLP IE, and the sysfs infrastructure for this WSS will be - * created. - */ -int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, - char *name, unsigned sec_status, unsigned accept) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - char buf[WLP_WSS_UUID_STRSIZE]; - d_fnstart(5, dev, "Request to create new WSS.\n"); - result = wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_printf(5, dev, "Request to create WSS: WSSID=%s, name=%s, " - "sec_status=%u, accepting enrollment=%u \n", - buf, name, sec_status, accept); - if (!mutex_trylock(&wss->mutex)) { - dev_err(dev, "WLP: WLP association session in progress.\n"); - return -EBUSY; - } - if (wss->state != WLP_WSS_STATE_NONE) { - dev_err(dev, "WLP: WSS already exists. Not creating new.\n"); - result = -EEXIST; - goto out; - } - if (wss->kobj.parent == NULL) { - dev_err(dev, "WLP: WSS parent not ready. Is network interface " - "up?\n"); - result = -ENXIO; - goto out; - } - if (sec_status == WLP_WSS_SECURE) { - dev_err(dev, "WLP: FIXME Creation of secure WSS not " - "supported yet.\n"); - result = -EINVAL; - goto out; - } - wss->wssid = *wssid; - memcpy(wss->name, name, sizeof(wss->name)); - wss->bcast = wlp_wss_sel_bcast_addr(wss); - wss->secure_status = sec_status; - wss->accept_enroll = accept; - /*wss->virtual_addr is initialized in call to wlp_wss_setup*/ - /* sysfs infrastructure */ - result = wlp_wss_sysfs_add(wss, buf); - if (result < 0) { - dev_err(dev, "Cannot set up sysfs for WSS kobject.\n"); - wlp_wss_reset(wss); - goto out; - } else - result = 0; - wss->state = WLP_WSS_STATE_ENROLLED; - result = wlp_wss_activate(wss); - if (result < 0) { - dev_err(dev, "WLP: Unable to activate WSS. Undoing " - "enrollment\n"); - wlp_wss_reset(wss); - goto out; - } - result = 0; -out: - mutex_unlock(&wss->mutex); - d_fnend(5, dev, "Completed. result = %d \n", result); - return result; -} - -/** - * Determine if neighbor has WSS activated - * - * @returns: 1 if neighbor has WSS activated, zero otherwise - * - * This can be done in two ways: - * - send a C1 frame, parse C2/F0 response - * - examine the WLP IE sent by the neighbor - * - * The WLP IE is not fully supported in hardware so we use the C1/C2 frame - * exchange to determine if a WSS is activated. Using the WLP IE should be - * faster and should be used when it becomes possible. - */ -int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, - struct uwb_dev_addr *dev_addr) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; - DECLARE_COMPLETION_ONSTACK(completion); - struct wlp_session session; - struct sk_buff *skb; - struct wlp_frame_assoc *resp; - struct wlp_uuid wssid; - - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); - mutex_lock(&wlp->mutex); - /* Send C1 association frame */ - result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1); - if (result < 0) { - dev_err(dev, "Unable to send C1 frame to neighbor " - "%02x:%02x (%d)\n", dev_addr->data[1], - dev_addr->data[0], result); - result = 0; - goto out; - } - /* Create session, wait for response */ - session.exp_message = WLP_ASSOC_C2; - session.cb = wlp_session_cb; - session.cb_priv = &completion; - session.neighbor_addr = *dev_addr; - BUG_ON(wlp->session != NULL); - wlp->session = &session; - /* Wait for C2/F0 frame */ - result = wait_for_completion_interruptible_timeout(&completion, - WLP_PER_MSG_TIMEOUT * HZ); - if (result == 0) { - dev_err(dev, "Timeout while sending C1 to neighbor " - "%02x:%02x.\n", dev_addr->data[1], - dev_addr->data[0]); - goto out; - } - if (result < 0) { - dev_err(dev, "Unable to send C1 to neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - result = 0; - goto out; - } - /* Parse message in session->data: it will be either C2 or F0 */ - skb = session.data; - resp = (void *) skb->data; - d_printf(5, dev, "Received response to C1 frame. \n"); - d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); - if (resp->type == WLP_ASSOC_F0) { - result = wlp_parse_f0(wlp, skb); - if (result < 0) - dev_err(dev, "WLP: unable to parse incoming F0 " - "frame from neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - result = 0; - goto error_resp_parse; - } - /* WLP version and message type fields have already been parsed */ - result = wlp_get_wssid(wlp, (void *)resp + sizeof(*resp), &wssid, - skb->len - sizeof(*resp)); - if (result < 0) { - dev_err(dev, "WLP: unable to obtain WSSID from C2 frame.\n"); - result = 0; - goto error_resp_parse; - } - if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))) { - d_printf(5, dev, "WSSID in C2 frame matches local " - "active WSS.\n"); - result = 1; - } else { - dev_err(dev, "WLP: Received a C2 frame without matching " - "WSSID.\n"); - result = 0; - } -error_resp_parse: - kfree_skb(skb); -out: - wlp->session = NULL; - mutex_unlock(&wlp->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); - return result; -} - -/** - * Activate connection with neighbor by updating EDA cache - * - * @wss: local WSS to which neighbor wants to connect - * @dev_addr: neighbor's address - * @wssid: neighbor's WSSID - must be same as our WSS's WSSID - * @tag: neighbor's WSS tag used to identify frames transmitted by it - * @virt_addr: neighbor's virtual EUI-48 - */ -static -int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss, - struct uwb_dev_addr *dev_addr, - struct wlp_uuid *wssid, u8 *tag, - struct uwb_mac_addr *virt_addr) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - char buf[WLP_WSS_UUID_STRSIZE]; - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " - "%02x:%02x:%02x:%02x:%02x:%02x \n", wlp, wss, buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); - - if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) { - d_printf(5, dev, "WSSID from neighbor frame matches local " - "active WSS.\n"); - /* Update EDA cache */ - result = wlp_eda_update_node(&wlp->eda, dev_addr, wss, - (void *) virt_addr->data, *tag, - WLP_WSS_CONNECTED); - if (result < 0) - dev_err(dev, "WLP: Unable to update EDA cache " - "with new connected neighbor information.\n"); - } else { - dev_err(dev, "WLP: Neighbor does not have matching " - "WSSID.\n"); - result = -EINVAL; - } - - d_fnend(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " - "%02x:%02x:%02x:%02x:%02x:%02x, result = %d \n", - wlp, wss, buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5], - result); - - return result; -} - -/** - * Connect to WSS neighbor - * - * Use C3/C4 exchange to determine if neighbor has WSS activated and - * retrieve the WSS tag and virtual EUI-48 of the neighbor. - */ -static -int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, - struct uwb_dev_addr *dev_addr) -{ - int result; - struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; - struct wlp_uuid wssid; - u8 tag; - struct uwb_mac_addr virt_addr; - DECLARE_COMPLETION_ONSTACK(completion); - struct wlp_session session; - struct wlp_frame_assoc *resp; - struct sk_buff *skb; - - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); - mutex_lock(&wlp->mutex); - /* Send C3 association frame */ - result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3); - if (result < 0) { - dev_err(dev, "Unable to send C3 frame to neighbor " - "%02x:%02x (%d)\n", dev_addr->data[1], - dev_addr->data[0], result); - goto out; - } - /* Create session, wait for response */ - session.exp_message = WLP_ASSOC_C4; - session.cb = wlp_session_cb; - session.cb_priv = &completion; - session.neighbor_addr = *dev_addr; - BUG_ON(wlp->session != NULL); - wlp->session = &session; - /* Wait for C4/F0 frame */ - result = wait_for_completion_interruptible_timeout(&completion, - WLP_PER_MSG_TIMEOUT * HZ); - if (result == 0) { - dev_err(dev, "Timeout while sending C3 to neighbor " - "%02x:%02x.\n", dev_addr->data[1], - dev_addr->data[0]); - result = -ETIMEDOUT; - goto out; - } - if (result < 0) { - dev_err(dev, "Unable to send C3 to neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - goto out; - } - /* Parse message in session->data: it will be either C4 or F0 */ - skb = session.data; - resp = (void *) skb->data; - d_printf(5, dev, "Received response to C3 frame. \n"); - d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); - if (resp->type == WLP_ASSOC_F0) { - result = wlp_parse_f0(wlp, skb); - if (result < 0) - dev_err(dev, "WLP: unable to parse incoming F0 " - "frame from neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - result = -EINVAL; - goto error_resp_parse; - } - result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr); - if (result < 0) { - dev_err(dev, "WLP: Unable to parse C4 frame from neighbor.\n"); - goto error_resp_parse; - } - result = wlp_wss_activate_connection(wlp, wss, dev_addr, &wssid, &tag, - &virt_addr); - if (result < 0) { - dev_err(dev, "WLP: Unable to activate connection to " - "neighbor %02x:%02x.\n", dev_addr->data[1], - dev_addr->data[0]); - goto error_resp_parse; - } -error_resp_parse: - kfree_skb(skb); -out: - /* Record that we unsuccessfully tried to connect to this neighbor */ - if (result < 0) - wlp_eda_update_node_state(&wlp->eda, dev_addr, - WLP_WSS_CONNECT_FAILED); - wlp->session = NULL; - mutex_unlock(&wlp->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); - return result; -} - -/** - * Connect to neighbor with common WSS, send pending frame - * - * This function is scheduled when a frame is destined to a neighbor with - * which we do not have a connection. A copy of the EDA cache entry is - * provided - not the actual cache entry (because it is protected by a - * spinlock). - * - * First determine if neighbor has the same WSS activated, connect if it - * does. The C3/C4 exchange is dual purpose to determine if neighbor has - * WSS activated and proceed with the connection. - * - * The frame that triggered the connection setup is sent after connection - * setup. - * - * network queue is stopped - we need to restart when done - * - */ -static -void wlp_wss_connect_send(struct work_struct *ws) -{ - struct wlp_assoc_conn_ctx *conn_ctx = container_of(ws, - struct wlp_assoc_conn_ctx, - ws); - struct wlp *wlp = conn_ctx->wlp; - struct sk_buff *skb = conn_ctx->skb; - struct wlp_eda_node *eda_entry = &conn_ctx->eda_entry; - struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - struct wlp_wss *wss = &wlp->wss; - int result; - struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; - - mutex_lock(&wss->mutex); - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); - if (wss->state < WLP_WSS_STATE_ACTIVE) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Attempting to connect with " - "WSS that is not active or connected.\n"); - dev_kfree_skb(skb); - goto out; - } - /* Establish connection - send C3 rcv C4 */ - result = wlp_wss_connect_neighbor(wlp, wss, dev_addr); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to establish connection " - "with neighbor %02x:%02x.\n", - dev_addr->data[1], dev_addr->data[0]); - dev_kfree_skb(skb); - goto out; - } - /* EDA entry changed, update the local copy being used */ - result = wlp_copy_eda_node(&wlp->eda, dev_addr, eda_entry); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Cannot find EDA entry for " - "neighbor %02x:%02x \n", - dev_addr->data[1], dev_addr->data[0]); - } - result = wlp_wss_prep_hdr(wlp, eda_entry, skb); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to prepare frame header for " - "transmission (neighbor %02x:%02x). \n", - dev_addr->data[1], dev_addr->data[0]); - dev_kfree_skb(skb); - goto out; - } - BUG_ON(wlp->xmit_frame == NULL); - result = wlp->xmit_frame(wlp, skb, dev_addr); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to transmit frame: %d\n", - result); - if (result == -ENXIO) - dev_err(dev, "WLP: Is network interface up? \n"); - /* We could try again ... */ - dev_kfree_skb(skb);/*we need to free if tx fails */ - } -out: - kfree(conn_ctx); - BUG_ON(wlp->start_queue == NULL); - wlp->start_queue(wlp); - mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s)\n", wlp, wss, buf); -} - -/** - * Add WLP header to outgoing skb - * - * @eda_entry: pointer to neighbor's entry in the EDA cache - * @_skb: skb containing data destined to the neighbor - */ -int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, - void *_skb) -{ - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - unsigned char *eth_addr = eda_entry->eth_addr; - struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - struct sk_buff *skb = _skb; - struct wlp_frame_std_abbrv_hdr *std_hdr; - - d_fnstart(6, dev, "wlp %p \n", wlp); - if (eda_entry->state == WLP_WSS_CONNECTED) { - /* Add WLP header */ - BUG_ON(skb_headroom(skb) < sizeof(*std_hdr)); - std_hdr = (void *) __skb_push(skb, sizeof(*std_hdr)); - std_hdr->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); - std_hdr->hdr.type = WLP_FRAME_STANDARD; - std_hdr->tag = eda_entry->wss->tag; - } else { - if (printk_ratelimit()) - dev_err(dev, "WLP: Destination neighbor (Ethernet: " - "%02x:%02x:%02x:%02x:%02x:%02x, Dev: " - "%02x:%02x) is not connected. \n", eth_addr[0], - eth_addr[1], eth_addr[2], eth_addr[3], - eth_addr[4], eth_addr[5], dev_addr->data[1], - dev_addr->data[0]); - result = -EINVAL; - } - d_fnend(6, dev, "wlp %p \n", wlp); - return result; -} - - -/** - * Prepare skb for neighbor: connect if not already and prep WLP header - * - * This function is called in interrupt context, but it needs to sleep. We - * temporarily stop the net queue to establish the WLP connection. - * Setup of the WLP connection and restart of queue is scheduled - * on the default work queue. - * - * run with eda->lock held (spinlock) - */ -int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry, - void *_skb) -{ - int result = 0; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - unsigned char *eth_addr = eda_entry->eth_addr; - struct sk_buff *skb = _skb; - struct wlp_assoc_conn_ctx *conn_ctx; - - d_fnstart(5, dev, "wlp %p\n", wlp); - d_printf(5, dev, "To neighbor %02x:%02x with eth " - "%02x:%02x:%02x:%02x:%02x:%02x\n", dev_addr->data[1], - dev_addr->data[0], eth_addr[0], eth_addr[1], eth_addr[2], - eth_addr[3], eth_addr[4], eth_addr[5]); - if (eda_entry->state == WLP_WSS_UNCONNECTED) { - /* We don't want any more packets while we set up connection */ - BUG_ON(wlp->stop_queue == NULL); - wlp->stop_queue(wlp); - conn_ctx = kmalloc(sizeof(*conn_ctx), GFP_ATOMIC); - if (conn_ctx == NULL) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to allocate memory " - "for connection handling.\n"); - result = -ENOMEM; - goto out; - } - conn_ctx->wlp = wlp; - conn_ctx->skb = skb; - conn_ctx->eda_entry = *eda_entry; - INIT_WORK(&conn_ctx->ws, wlp_wss_connect_send); - schedule_work(&conn_ctx->ws); - result = 1; - } else if (eda_entry->state == WLP_WSS_CONNECT_FAILED) { - /* Previous connection attempts failed, don't retry - see - * conditions for connection in WLP 0.99 [7.6.2] */ - if (printk_ratelimit()) - dev_err(dev, "Could not connect to neighbor " - "previously. Not retrying. \n"); - result = -ENONET; - goto out; - } else { /* eda_entry->state == WLP_WSS_CONNECTED */ - d_printf(5, dev, "Neighbor is connected, preparing frame.\n"); - result = wlp_wss_prep_hdr(wlp, eda_entry, skb); - } -out: - d_fnend(5, dev, "wlp %p, result = %d \n", wlp, result); - return result; -} - -/** - * Emulate broadcast: copy skb, send copy to neighbor (connect if not already) - * - * We need to copy skbs in the case where we emulate broadcast through - * unicast. We copy instead of clone because we are modifying the data of - * the frame after copying ... clones share data so we cannot emulate - * broadcast using clones. - * - * run with eda->lock held (spinlock) - */ -int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry, - void *_skb) -{ - int result = -ENOMEM; - struct device *dev = &wlp->rc->uwb_dev.dev; - struct sk_buff *skb = _skb; - struct sk_buff *copy; - struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - - d_fnstart(5, dev, "to neighbor %02x:%02x, skb (%p) \n", - dev_addr->data[1], dev_addr->data[0], skb); - copy = skb_copy(skb, GFP_ATOMIC); - if (copy == NULL) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to copy skb for " - "transmission.\n"); - goto out; - } - result = wlp_wss_connect_prep(wlp, eda_entry, copy); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to connect/send skb " - "to neighbor.\n"); - dev_kfree_skb_irq(copy); - goto out; - } else if (result == 1) - /* Frame will be transmitted separately */ - goto out; - BUG_ON(wlp->xmit_frame == NULL); - result = wlp->xmit_frame(wlp, copy, dev_addr); - if (result < 0) { - if (printk_ratelimit()) - dev_err(dev, "WLP: Unable to transmit frame: %d\n", - result); - if ((result == -ENXIO) && printk_ratelimit()) - dev_err(dev, "WLP: Is network interface up? \n"); - /* We could try again ... */ - dev_kfree_skb_irq(copy);/*we need to free if tx fails */ - } -out: - d_fnend(5, dev, "to neighbor %02x:%02x \n", dev_addr->data[1], - dev_addr->data[0]); - return result; -} - - -/** - * Setup WSS - * - * Should be called by network driver after the interface has been given a - * MAC address. - */ -int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - int result = 0; - d_fnstart(5, dev, "wss (%p) \n", wss); - mutex_lock(&wss->mutex); - wss->kobj.parent = &net_dev->dev.kobj; - if (!is_valid_ether_addr(net_dev->dev_addr)) { - dev_err(dev, "WLP: Invalid MAC address. Cannot use for" - "virtual.\n"); - result = -EINVAL; - goto out; - } - memcpy(wss->virtual_addr.data, net_dev->dev_addr, - sizeof(wss->virtual_addr.data)); -out: - mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wss (%p) \n", wss); - return result; -} -EXPORT_SYMBOL_GPL(wlp_wss_setup); - -/** - * Remove WSS - * - * Called by client that configured WSS through wlp_wss_setup(). This - * function is called when client no longer needs WSS, eg. client shuts - * down. - * - * We remove the WLP IE from the beacon before initiating local cleanup. - */ -void wlp_wss_remove(struct wlp_wss *wss) -{ - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(5, dev, "wss (%p) \n", wss); - mutex_lock(&wss->mutex); - if (wss->state == WLP_WSS_STATE_ACTIVE) - uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP); - if (wss->state != WLP_WSS_STATE_NONE) { - sysfs_remove_group(&wss->kobj, &wss_attr_group); - kobject_put(&wss->kobj); - } - wss->kobj.parent = NULL; - memset(&wss->virtual_addr, 0, sizeof(wss->virtual_addr)); - /* Cleanup EDA cache */ - wlp_eda_release(&wlp->eda); - wlp_eda_init(&wlp->eda); - mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wss (%p) \n", wss); -} -EXPORT_SYMBOL_GPL(wlp_wss_remove); diff --git a/trunk/drivers/watchdog/w83697ug_wdt.c b/trunk/drivers/watchdog/w83697ug_wdt.c index ada8ad82d993..c73b5e2919c6 100644 --- a/trunk/drivers/watchdog/w83697ug_wdt.c +++ b/trunk/drivers/watchdog/w83697ug_wdt.c @@ -102,7 +102,7 @@ static void w83697ug_select_wd_register(void) } else { printk(KERN_ERR PFX "No W83697UG/UF could be found\n"); - return; + return -EIO; } outb_p(0x07, WDT_EFER); /* point to logical device number reg */ diff --git a/trunk/fs/binfmt_elf_fdpic.c b/trunk/fs/binfmt_elf_fdpic.c index 5b5424cb3391..0e8367c54624 100644 --- a/trunk/fs/binfmt_elf_fdpic.c +++ b/trunk/fs/binfmt_elf_fdpic.c @@ -1390,15 +1390,20 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_pgrp = task_pgrp_vnr(p); prstatus->pr_sid = task_session_vnr(p); if (thread_group_leader(p)) { - struct task_cputime cputime; - /* - * This is the record for the group leader. It shows the - * group-wide total, not its individual thread total. + * This is the record for the group leader. Add in the + * cumulative times of previous dead threads. This total + * won't include the time of each live thread whose state + * is included in the core dump. The final total reported + * to our parent process when it calls wait4 will include + * those sums as well as the little bit more time it takes + * this and each other thread to finish dying after the + * core dump synchronization phase. */ - thread_group_cputime(p, &cputime); - cputime_to_timeval(cputime.utime, &prstatus->pr_utime); - cputime_to_timeval(cputime.stime, &prstatus->pr_stime); + cputime_to_timeval(cputime_add(p->utime, p->signal->utime), + &prstatus->pr_utime); + cputime_to_timeval(cputime_add(p->stime, p->signal->stime), + &prstatus->pr_stime); } else { cputime_to_timeval(p->utime, &prstatus->pr_utime); cputime_to_timeval(p->stime, &prstatus->pr_stime); diff --git a/trunk/fs/ext3/ioctl.c b/trunk/fs/ext3/ioctl.c index b7394d05ee8e..0d0c70151642 100644 --- a/trunk/fs/ext3/ioctl.c +++ b/trunk/fs/ext3/ioctl.c @@ -239,7 +239,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, case EXT3_IOC_GROUP_EXTEND: { ext3_fsblk_t n_blocks_count; struct super_block *sb = inode->i_sb; - int err, err2; + int err; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; @@ -254,10 +254,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, } err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count); journal_lock_updates(EXT3_SB(sb)->s_journal); - err2 = journal_flush(EXT3_SB(sb)->s_journal); + journal_flush(EXT3_SB(sb)->s_journal); journal_unlock_updates(EXT3_SB(sb)->s_journal); - if (err == 0) - err = err2; group_extend_out: mnt_drop_write(filp->f_path.mnt); return err; @@ -265,7 +263,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, case EXT3_IOC_GROUP_ADD: { struct ext3_new_group_data input; struct super_block *sb = inode->i_sb; - int err, err2; + int err; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; @@ -282,10 +280,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, err = ext3_group_add(sb, &input); journal_lock_updates(EXT3_SB(sb)->s_journal); - err2 = journal_flush(EXT3_SB(sb)->s_journal); + journal_flush(EXT3_SB(sb)->s_journal); journal_unlock_updates(EXT3_SB(sb)->s_journal); - if (err == 0) - err = err2; group_add_out: mnt_drop_write(filp->f_path.mnt); return err; diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index cac29ee3b14a..3a260af5544d 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -393,8 +393,7 @@ static void ext3_put_super (struct super_block * sb) int i; ext3_xattr_put_super(sb); - if (journal_destroy(sbi->s_journal) < 0) - ext3_abort(sb, __func__, "Couldn't clean up the journal"); + journal_destroy(sbi->s_journal); if (!(sb->s_flags & MS_RDONLY)) { EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); es->s_state = cpu_to_le16(sbi->s_mount_state); @@ -2297,9 +2296,7 @@ static void ext3_mark_recovery_complete(struct super_block * sb, journal_t *journal = EXT3_SB(sb)->s_journal; journal_lock_updates(journal); - if (journal_flush(journal) < 0) - goto out; - + journal_flush(journal); lock_super(sb); if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) && sb->s_flags & MS_RDONLY) { @@ -2308,8 +2305,6 @@ static void ext3_mark_recovery_complete(struct super_block * sb, ext3_commit_super(sb, es, 1); } unlock_super(sb); - -out: journal_unlock_updates(journal); } @@ -2409,13 +2404,7 @@ static void ext3_write_super_lockfs(struct super_block *sb) /* Now we set up the journal barrier. */ journal_lock_updates(journal); - - /* - * We don't want to clear needs_recovery flag when we failed - * to flush the journal. - */ - if (journal_flush(journal) < 0) - return; + journal_flush(journal); /* Journal blocked and flushed, clear needs_recovery flag. */ EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); @@ -2833,12 +2822,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, * otherwise be livelocked... */ journal_lock_updates(EXT3_SB(sb)->s_journal); - err = journal_flush(EXT3_SB(sb)->s_journal); + journal_flush(EXT3_SB(sb)->s_journal); journal_unlock_updates(EXT3_SB(sb)->s_journal); - if (err) { - path_put(&nd.path); - return err; - } } err = vfs_quota_on_path(sb, type, format_id, &nd.path); diff --git a/trunk/fs/jbd/checkpoint.c b/trunk/fs/jbd/checkpoint.c index 1bd8d4acc6f2..a5432bbbfb88 100644 --- a/trunk/fs/jbd/checkpoint.c +++ b/trunk/fs/jbd/checkpoint.c @@ -93,8 +93,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) int ret = 0; struct buffer_head *bh = jh2bh(jh); - if (jh->b_jlist == BJ_None && !buffer_locked(bh) && - !buffer_dirty(bh) && !buffer_write_io_error(bh)) { + if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { JBUFFER_TRACE(jh, "remove from checkpoint list"); ret = __journal_remove_checkpoint(jh) + 1; jbd_unlock_bh_state(bh); @@ -127,29 +126,14 @@ void __log_wait_for_space(journal_t *journal) /* * Test again, another process may have checkpointed while we - * were waiting for the checkpoint lock. If there are no - * outstanding transactions there is nothing to checkpoint and - * we can't make progress. Abort the journal in this case. + * were waiting for the checkpoint lock */ spin_lock(&journal->j_state_lock); - spin_lock(&journal->j_list_lock); nblocks = jbd_space_needed(journal); if (__log_space_left(journal) < nblocks) { - int chkpt = journal->j_checkpoint_transactions != NULL; - - spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_state_lock); - if (chkpt) { - log_do_checkpoint(journal); - } else { - printk(KERN_ERR "%s: no transactions\n", - __func__); - journal_abort(journal, 0); - } - + log_do_checkpoint(journal); spin_lock(&journal->j_state_lock); - } else { - spin_unlock(&journal->j_list_lock); } mutex_unlock(&journal->j_checkpoint_mutex); } @@ -176,25 +160,21 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) * buffers. Note that we take the buffers in the opposite ordering * from the one in which they were submitted for IO. * - * Return 0 on success, and return <0 if some buffers have failed - * to be written out. - * * Called with j_list_lock held. */ -static int __wait_cp_io(journal_t *journal, transaction_t *transaction) +static void __wait_cp_io(journal_t *journal, transaction_t *transaction) { struct journal_head *jh; struct buffer_head *bh; tid_t this_tid; int released = 0; - int ret = 0; this_tid = transaction->t_tid; restart: /* Did somebody clean up the transaction in the meanwhile? */ if (journal->j_checkpoint_transactions != transaction || transaction->t_tid != this_tid) - return ret; + return; while (!released && transaction->t_checkpoint_io_list) { jh = transaction->t_checkpoint_io_list; bh = jh2bh(jh); @@ -214,9 +194,6 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction) spin_lock(&journal->j_list_lock); goto restart; } - if (unlikely(buffer_write_io_error(bh))) - ret = -EIO; - /* * Now in whatever state the buffer currently is, we know that * it has been written out and so we can drop it from the list @@ -226,8 +203,6 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction) journal_remove_journal_head(bh); __brelse(bh); } - - return ret; } #define NR_BATCH 64 @@ -251,8 +226,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) * Try to flush one buffer from the checkpoint list to disk. * * Return 1 if something happened which requires us to abort the current - * scan of the checkpoint list. Return <0 if the buffer has failed to - * be written out. + * scan of the checkpoint list. * * Called with j_list_lock held and drops it if 1 is returned * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it @@ -282,9 +256,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, log_wait_commit(journal, tid); ret = 1; } else if (!buffer_dirty(bh)) { - ret = 1; - if (unlikely(buffer_write_io_error(bh))) - ret = -EIO; J_ASSERT_JH(jh, !buffer_jbddirty(bh)); BUFFER_TRACE(bh, "remove from checkpoint"); __journal_remove_checkpoint(jh); @@ -292,6 +263,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, jbd_unlock_bh_state(bh); journal_remove_journal_head(bh); __brelse(bh); + ret = 1; } else { /* * Important: we are about to write the buffer, and @@ -323,7 +295,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, * to disk. We submit larger chunks of data at once. * * The journal should be locked before calling this function. - * Called with j_checkpoint_mutex held. */ int log_do_checkpoint(journal_t *journal) { @@ -347,7 +318,6 @@ int log_do_checkpoint(journal_t *journal) * OK, we need to start writing disk blocks. Take one transaction * and write it. */ - result = 0; spin_lock(&journal->j_list_lock); if (!journal->j_checkpoint_transactions) goto out; @@ -364,7 +334,7 @@ int log_do_checkpoint(journal_t *journal) int batch_count = 0; struct buffer_head *bhs[NR_BATCH]; struct journal_head *jh; - int retry = 0, err; + int retry = 0; while (!retry && transaction->t_checkpoint_list) { struct buffer_head *bh; @@ -377,8 +347,6 @@ int log_do_checkpoint(journal_t *journal) break; } retry = __process_buffer(journal, jh, bhs,&batch_count); - if (retry < 0 && !result) - result = retry; if (!retry && (need_resched() || spin_needbreak(&journal->j_list_lock))) { spin_unlock(&journal->j_list_lock); @@ -403,18 +371,14 @@ int log_do_checkpoint(journal_t *journal) * Now we have cleaned up the first transaction's checkpoint * list. Let's clean up the second one */ - err = __wait_cp_io(journal, transaction); - if (!result) - result = err; + __wait_cp_io(journal, transaction); } out: spin_unlock(&journal->j_list_lock); + result = cleanup_journal_tail(journal); if (result < 0) - journal_abort(journal, result); - else - result = cleanup_journal_tail(journal); - - return (result < 0) ? result : 0; + return result; + return 0; } /* @@ -430,9 +394,8 @@ int log_do_checkpoint(journal_t *journal) * This is the only part of the journaling code which really needs to be * aware of transaction aborts. Checkpointing involves writing to the * main filesystem area rather than to the journal, so it can proceed - * even in abort state, but we must not update the super block if - * checkpointing may have failed. Otherwise, we would lose some metadata - * buffers which should be written-back to the filesystem. + * even in abort state, but we must not update the journal superblock if + * we have an abort error outstanding. */ int cleanup_journal_tail(journal_t *journal) @@ -441,9 +404,6 @@ int cleanup_journal_tail(journal_t *journal) tid_t first_tid; unsigned long blocknr, freed; - if (is_journal_aborted(journal)) - return 1; - /* OK, work out the oldest transaction remaining in the log, and * the log block it starts at. * diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index 9e4fa52d7dc8..aa7143a8349b 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -1121,12 +1121,9 @@ int journal_load(journal_t *journal) * * Release a journal_t structure once it is no longer in use by the * journaled object. - * Return <0 if we couldn't clean up the journal. */ -int journal_destroy(journal_t *journal) +void journal_destroy(journal_t *journal) { - int err = 0; - /* Wait for the commit thread to wake up and die. */ journal_kill_thread(journal); @@ -1149,16 +1146,11 @@ int journal_destroy(journal_t *journal) J_ASSERT(journal->j_checkpoint_transactions == NULL); spin_unlock(&journal->j_list_lock); + /* We can now mark the journal as empty. */ + journal->j_tail = 0; + journal->j_tail_sequence = ++journal->j_transaction_sequence; if (journal->j_sb_buffer) { - if (!is_journal_aborted(journal)) { - /* We can now mark the journal as empty. */ - journal->j_tail = 0; - journal->j_tail_sequence = - ++journal->j_transaction_sequence; - journal_update_superblock(journal, 1); - } else { - err = -EIO; - } + journal_update_superblock(journal, 1); brelse(journal->j_sb_buffer); } @@ -1168,8 +1160,6 @@ int journal_destroy(journal_t *journal) journal_destroy_revoke(journal); kfree(journal->j_wbuf); kfree(journal); - - return err; } @@ -1369,16 +1359,10 @@ int journal_flush(journal_t *journal) spin_lock(&journal->j_list_lock); while (!err && journal->j_checkpoint_transactions != NULL) { spin_unlock(&journal->j_list_lock); - mutex_lock(&journal->j_checkpoint_mutex); err = log_do_checkpoint(journal); - mutex_unlock(&journal->j_checkpoint_mutex); spin_lock(&journal->j_list_lock); } spin_unlock(&journal->j_list_lock); - - if (is_journal_aborted(journal)) - return -EIO; - cleanup_journal_tail(journal); /* Finally, mark the journal as really needing no recovery. @@ -1400,7 +1384,7 @@ int journal_flush(journal_t *journal) J_ASSERT(journal->j_head == journal->j_tail); J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); spin_unlock(&journal->j_state_lock); - return 0; + return err; } /** diff --git a/trunk/fs/jbd/recovery.c b/trunk/fs/jbd/recovery.c index db5e982c5ddf..43bc5e5ed064 100644 --- a/trunk/fs/jbd/recovery.c +++ b/trunk/fs/jbd/recovery.c @@ -223,7 +223,7 @@ do { \ */ int journal_recover(journal_t *journal) { - int err, err2; + int err; journal_superblock_t * sb; struct recovery_info info; @@ -261,10 +261,7 @@ int journal_recover(journal_t *journal) journal->j_transaction_sequence = ++info.end_transaction; journal_clear_revoke(journal); - err2 = sync_blockdev(journal->j_fs_dev); - if (!err) - err = err2; - + sync_blockdev(journal->j_fs_dev); return err; } diff --git a/trunk/include/asm-generic/bug.h b/trunk/include/asm-generic/bug.h index 12c07c1866b2..0f6dabd4b517 100644 --- a/trunk/include/asm-generic/bug.h +++ b/trunk/include/asm-generic/bug.h @@ -41,7 +41,7 @@ extern void warn_slowpath(const char *file, const int line, #define __WARN() warn_on_slowpath(__FILE__, __LINE__) #define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg) #else -#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) +#define __WARN_printf(arg...) __WARN() #endif #ifndef WARN_ON diff --git a/trunk/include/asm-generic/mutex-dec.h b/trunk/include/asm-generic/mutex-dec.h index f104af7cf437..ed108be6743f 100644 --- a/trunk/include/asm-generic/mutex-dec.h +++ b/trunk/include/asm-generic/mutex-dec.h @@ -22,6 +22,8 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { if (unlikely(atomic_dec_return(count) < 0)) fail_fn(count); + else + smp_mb(); } /** @@ -39,7 +41,10 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { if (unlikely(atomic_dec_return(count) < 0)) return fail_fn(count); - return 0; + else { + smp_mb(); + return 0; + } } /** @@ -58,6 +63,7 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) static inline void __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) { + smp_mb(); if (unlikely(atomic_inc_return(count) <= 0)) fail_fn(count); } @@ -82,9 +88,25 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) static inline int __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) { - if (likely(atomic_cmpxchg(count, 1, 0) == 1)) + /* + * We have two variants here. The cmpxchg based one is the best one + * because it never induce a false contention state. It is included + * here because architectures using the inc/dec algorithms over the + * xchg ones are much more likely to support cmpxchg natively. + * + * If not we fall back to the spinlock based variant - that is + * just as efficient (and simpler) as a 'destructive' probing of + * the mutex state would be. + */ +#ifdef __HAVE_ARCH_CMPXCHG + if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { + smp_mb(); return 1; + } return 0; +#else + return fail_fn(count); +#endif } #endif diff --git a/trunk/include/asm-generic/mutex-xchg.h b/trunk/include/asm-generic/mutex-xchg.h index 580a6d35c700..7b9cd2cbfebe 100644 --- a/trunk/include/asm-generic/mutex-xchg.h +++ b/trunk/include/asm-generic/mutex-xchg.h @@ -27,6 +27,8 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) fail_fn(count); + else + smp_mb(); } /** @@ -44,7 +46,10 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) return fail_fn(count); - return 0; + else { + smp_mb(); + return 0; + } } /** @@ -62,6 +67,7 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) static inline void __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) { + smp_mb(); if (unlikely(atomic_xchg(count, 1) != 0)) fail_fn(count); } @@ -104,6 +110,7 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) if (prev < 0) prev = 0; } + smp_mb(); return prev; } diff --git a/trunk/arch/parisc/include/asm/Kbuild b/trunk/include/asm-parisc/Kbuild similarity index 100% rename from trunk/arch/parisc/include/asm/Kbuild rename to trunk/include/asm-parisc/Kbuild diff --git a/trunk/arch/parisc/include/asm/agp.h b/trunk/include/asm-parisc/agp.h similarity index 100% rename from trunk/arch/parisc/include/asm/agp.h rename to trunk/include/asm-parisc/agp.h diff --git a/trunk/arch/parisc/include/asm/asmregs.h b/trunk/include/asm-parisc/asmregs.h similarity index 100% rename from trunk/arch/parisc/include/asm/asmregs.h rename to trunk/include/asm-parisc/asmregs.h diff --git a/trunk/arch/parisc/include/asm/assembly.h b/trunk/include/asm-parisc/assembly.h similarity index 100% rename from trunk/arch/parisc/include/asm/assembly.h rename to trunk/include/asm-parisc/assembly.h diff --git a/trunk/arch/parisc/include/asm/atomic.h b/trunk/include/asm-parisc/atomic.h similarity index 100% rename from trunk/arch/parisc/include/asm/atomic.h rename to trunk/include/asm-parisc/atomic.h diff --git a/trunk/arch/parisc/include/asm/auxvec.h b/trunk/include/asm-parisc/auxvec.h similarity index 100% rename from trunk/arch/parisc/include/asm/auxvec.h rename to trunk/include/asm-parisc/auxvec.h diff --git a/trunk/arch/parisc/include/asm/bitops.h b/trunk/include/asm-parisc/bitops.h similarity index 100% rename from trunk/arch/parisc/include/asm/bitops.h rename to trunk/include/asm-parisc/bitops.h diff --git a/trunk/arch/parisc/include/asm/bug.h b/trunk/include/asm-parisc/bug.h similarity index 100% rename from trunk/arch/parisc/include/asm/bug.h rename to trunk/include/asm-parisc/bug.h diff --git a/trunk/arch/parisc/include/asm/bugs.h b/trunk/include/asm-parisc/bugs.h similarity index 100% rename from trunk/arch/parisc/include/asm/bugs.h rename to trunk/include/asm-parisc/bugs.h diff --git a/trunk/arch/parisc/include/asm/byteorder.h b/trunk/include/asm-parisc/byteorder.h similarity index 100% rename from trunk/arch/parisc/include/asm/byteorder.h rename to trunk/include/asm-parisc/byteorder.h diff --git a/trunk/arch/parisc/include/asm/cache.h b/trunk/include/asm-parisc/cache.h similarity index 100% rename from trunk/arch/parisc/include/asm/cache.h rename to trunk/include/asm-parisc/cache.h diff --git a/trunk/arch/parisc/include/asm/cacheflush.h b/trunk/include/asm-parisc/cacheflush.h similarity index 100% rename from trunk/arch/parisc/include/asm/cacheflush.h rename to trunk/include/asm-parisc/cacheflush.h diff --git a/trunk/arch/parisc/include/asm/checksum.h b/trunk/include/asm-parisc/checksum.h similarity index 100% rename from trunk/arch/parisc/include/asm/checksum.h rename to trunk/include/asm-parisc/checksum.h diff --git a/trunk/arch/parisc/include/asm/compat.h b/trunk/include/asm-parisc/compat.h similarity index 100% rename from trunk/arch/parisc/include/asm/compat.h rename to trunk/include/asm-parisc/compat.h diff --git a/trunk/arch/parisc/include/asm/compat_rt_sigframe.h b/trunk/include/asm-parisc/compat_rt_sigframe.h similarity index 100% rename from trunk/arch/parisc/include/asm/compat_rt_sigframe.h rename to trunk/include/asm-parisc/compat_rt_sigframe.h diff --git a/trunk/arch/parisc/include/asm/compat_signal.h b/trunk/include/asm-parisc/compat_signal.h similarity index 100% rename from trunk/arch/parisc/include/asm/compat_signal.h rename to trunk/include/asm-parisc/compat_signal.h diff --git a/trunk/arch/parisc/include/asm/compat_ucontext.h b/trunk/include/asm-parisc/compat_ucontext.h similarity index 100% rename from trunk/arch/parisc/include/asm/compat_ucontext.h rename to trunk/include/asm-parisc/compat_ucontext.h diff --git a/trunk/arch/parisc/include/asm/cputime.h b/trunk/include/asm-parisc/cputime.h similarity index 100% rename from trunk/arch/parisc/include/asm/cputime.h rename to trunk/include/asm-parisc/cputime.h diff --git a/trunk/arch/parisc/include/asm/current.h b/trunk/include/asm-parisc/current.h similarity index 100% rename from trunk/arch/parisc/include/asm/current.h rename to trunk/include/asm-parisc/current.h diff --git a/trunk/arch/parisc/include/asm/delay.h b/trunk/include/asm-parisc/delay.h similarity index 100% rename from trunk/arch/parisc/include/asm/delay.h rename to trunk/include/asm-parisc/delay.h diff --git a/trunk/arch/parisc/include/asm/device.h b/trunk/include/asm-parisc/device.h similarity index 100% rename from trunk/arch/parisc/include/asm/device.h rename to trunk/include/asm-parisc/device.h diff --git a/trunk/arch/parisc/include/asm/div64.h b/trunk/include/asm-parisc/div64.h similarity index 100% rename from trunk/arch/parisc/include/asm/div64.h rename to trunk/include/asm-parisc/div64.h diff --git a/trunk/arch/parisc/include/asm/dma-mapping.h b/trunk/include/asm-parisc/dma-mapping.h similarity index 100% rename from trunk/arch/parisc/include/asm/dma-mapping.h rename to trunk/include/asm-parisc/dma-mapping.h diff --git a/trunk/arch/parisc/include/asm/dma.h b/trunk/include/asm-parisc/dma.h similarity index 100% rename from trunk/arch/parisc/include/asm/dma.h rename to trunk/include/asm-parisc/dma.h diff --git a/trunk/arch/parisc/include/asm/eisa_bus.h b/trunk/include/asm-parisc/eisa_bus.h similarity index 100% rename from trunk/arch/parisc/include/asm/eisa_bus.h rename to trunk/include/asm-parisc/eisa_bus.h diff --git a/trunk/arch/parisc/include/asm/eisa_eeprom.h b/trunk/include/asm-parisc/eisa_eeprom.h similarity index 100% rename from trunk/arch/parisc/include/asm/eisa_eeprom.h rename to trunk/include/asm-parisc/eisa_eeprom.h diff --git a/trunk/arch/parisc/include/asm/elf.h b/trunk/include/asm-parisc/elf.h similarity index 100% rename from trunk/arch/parisc/include/asm/elf.h rename to trunk/include/asm-parisc/elf.h diff --git a/trunk/arch/parisc/include/asm/emergency-restart.h b/trunk/include/asm-parisc/emergency-restart.h similarity index 100% rename from trunk/arch/parisc/include/asm/emergency-restart.h rename to trunk/include/asm-parisc/emergency-restart.h diff --git a/trunk/arch/parisc/include/asm/errno.h b/trunk/include/asm-parisc/errno.h similarity index 100% rename from trunk/arch/parisc/include/asm/errno.h rename to trunk/include/asm-parisc/errno.h diff --git a/trunk/arch/parisc/include/asm/fb.h b/trunk/include/asm-parisc/fb.h similarity index 100% rename from trunk/arch/parisc/include/asm/fb.h rename to trunk/include/asm-parisc/fb.h diff --git a/trunk/arch/parisc/include/asm/fcntl.h b/trunk/include/asm-parisc/fcntl.h similarity index 100% rename from trunk/arch/parisc/include/asm/fcntl.h rename to trunk/include/asm-parisc/fcntl.h diff --git a/trunk/arch/parisc/include/asm/fixmap.h b/trunk/include/asm-parisc/fixmap.h similarity index 100% rename from trunk/arch/parisc/include/asm/fixmap.h rename to trunk/include/asm-parisc/fixmap.h diff --git a/trunk/arch/parisc/include/asm/floppy.h b/trunk/include/asm-parisc/floppy.h similarity index 100% rename from trunk/arch/parisc/include/asm/floppy.h rename to trunk/include/asm-parisc/floppy.h diff --git a/trunk/arch/parisc/include/asm/futex.h b/trunk/include/asm-parisc/futex.h similarity index 100% rename from trunk/arch/parisc/include/asm/futex.h rename to trunk/include/asm-parisc/futex.h diff --git a/trunk/arch/parisc/include/asm/grfioctl.h b/trunk/include/asm-parisc/grfioctl.h similarity index 100% rename from trunk/arch/parisc/include/asm/grfioctl.h rename to trunk/include/asm-parisc/grfioctl.h diff --git a/trunk/arch/parisc/include/asm/hardirq.h b/trunk/include/asm-parisc/hardirq.h similarity index 100% rename from trunk/arch/parisc/include/asm/hardirq.h rename to trunk/include/asm-parisc/hardirq.h diff --git a/trunk/arch/parisc/include/asm/hardware.h b/trunk/include/asm-parisc/hardware.h similarity index 100% rename from trunk/arch/parisc/include/asm/hardware.h rename to trunk/include/asm-parisc/hardware.h diff --git a/trunk/arch/parisc/include/asm/hw_irq.h b/trunk/include/asm-parisc/hw_irq.h similarity index 100% rename from trunk/arch/parisc/include/asm/hw_irq.h rename to trunk/include/asm-parisc/hw_irq.h diff --git a/trunk/arch/parisc/include/asm/ide.h b/trunk/include/asm-parisc/ide.h similarity index 100% rename from trunk/arch/parisc/include/asm/ide.h rename to trunk/include/asm-parisc/ide.h diff --git a/trunk/arch/parisc/include/asm/io.h b/trunk/include/asm-parisc/io.h similarity index 100% rename from trunk/arch/parisc/include/asm/io.h rename to trunk/include/asm-parisc/io.h diff --git a/trunk/arch/parisc/include/asm/ioctl.h b/trunk/include/asm-parisc/ioctl.h similarity index 100% rename from trunk/arch/parisc/include/asm/ioctl.h rename to trunk/include/asm-parisc/ioctl.h diff --git a/trunk/arch/parisc/include/asm/ioctls.h b/trunk/include/asm-parisc/ioctls.h similarity index 100% rename from trunk/arch/parisc/include/asm/ioctls.h rename to trunk/include/asm-parisc/ioctls.h diff --git a/trunk/arch/parisc/include/asm/ipcbuf.h b/trunk/include/asm-parisc/ipcbuf.h similarity index 100% rename from trunk/arch/parisc/include/asm/ipcbuf.h rename to trunk/include/asm-parisc/ipcbuf.h diff --git a/trunk/arch/parisc/include/asm/irq.h b/trunk/include/asm-parisc/irq.h similarity index 100% rename from trunk/arch/parisc/include/asm/irq.h rename to trunk/include/asm-parisc/irq.h diff --git a/trunk/arch/parisc/include/asm/irq_regs.h b/trunk/include/asm-parisc/irq_regs.h similarity index 100% rename from trunk/arch/parisc/include/asm/irq_regs.h rename to trunk/include/asm-parisc/irq_regs.h diff --git a/trunk/arch/parisc/include/asm/kdebug.h b/trunk/include/asm-parisc/kdebug.h similarity index 100% rename from trunk/arch/parisc/include/asm/kdebug.h rename to trunk/include/asm-parisc/kdebug.h diff --git a/trunk/arch/parisc/include/asm/kmap_types.h b/trunk/include/asm-parisc/kmap_types.h similarity index 100% rename from trunk/arch/parisc/include/asm/kmap_types.h rename to trunk/include/asm-parisc/kmap_types.h diff --git a/trunk/arch/parisc/include/asm/led.h b/trunk/include/asm-parisc/led.h similarity index 100% rename from trunk/arch/parisc/include/asm/led.h rename to trunk/include/asm-parisc/led.h diff --git a/trunk/arch/parisc/include/asm/linkage.h b/trunk/include/asm-parisc/linkage.h similarity index 100% rename from trunk/arch/parisc/include/asm/linkage.h rename to trunk/include/asm-parisc/linkage.h diff --git a/trunk/arch/parisc/include/asm/local.h b/trunk/include/asm-parisc/local.h similarity index 100% rename from trunk/arch/parisc/include/asm/local.h rename to trunk/include/asm-parisc/local.h diff --git a/trunk/arch/parisc/include/asm/machdep.h b/trunk/include/asm-parisc/machdep.h similarity index 100% rename from trunk/arch/parisc/include/asm/machdep.h rename to trunk/include/asm-parisc/machdep.h diff --git a/trunk/arch/parisc/include/asm/mc146818rtc.h b/trunk/include/asm-parisc/mc146818rtc.h similarity index 100% rename from trunk/arch/parisc/include/asm/mc146818rtc.h rename to trunk/include/asm-parisc/mc146818rtc.h diff --git a/trunk/arch/parisc/include/asm/mckinley.h b/trunk/include/asm-parisc/mckinley.h similarity index 100% rename from trunk/arch/parisc/include/asm/mckinley.h rename to trunk/include/asm-parisc/mckinley.h diff --git a/trunk/arch/parisc/include/asm/mman.h b/trunk/include/asm-parisc/mman.h similarity index 100% rename from trunk/arch/parisc/include/asm/mman.h rename to trunk/include/asm-parisc/mman.h diff --git a/trunk/arch/parisc/include/asm/mmu.h b/trunk/include/asm-parisc/mmu.h similarity index 100% rename from trunk/arch/parisc/include/asm/mmu.h rename to trunk/include/asm-parisc/mmu.h diff --git a/trunk/arch/parisc/include/asm/mmu_context.h b/trunk/include/asm-parisc/mmu_context.h similarity index 100% rename from trunk/arch/parisc/include/asm/mmu_context.h rename to trunk/include/asm-parisc/mmu_context.h diff --git a/trunk/arch/parisc/include/asm/mmzone.h b/trunk/include/asm-parisc/mmzone.h similarity index 100% rename from trunk/arch/parisc/include/asm/mmzone.h rename to trunk/include/asm-parisc/mmzone.h diff --git a/trunk/arch/parisc/include/asm/module.h b/trunk/include/asm-parisc/module.h similarity index 100% rename from trunk/arch/parisc/include/asm/module.h rename to trunk/include/asm-parisc/module.h diff --git a/trunk/arch/parisc/include/asm/msgbuf.h b/trunk/include/asm-parisc/msgbuf.h similarity index 100% rename from trunk/arch/parisc/include/asm/msgbuf.h rename to trunk/include/asm-parisc/msgbuf.h diff --git a/trunk/arch/parisc/include/asm/mutex.h b/trunk/include/asm-parisc/mutex.h similarity index 100% rename from trunk/arch/parisc/include/asm/mutex.h rename to trunk/include/asm-parisc/mutex.h diff --git a/trunk/arch/parisc/include/asm/page.h b/trunk/include/asm-parisc/page.h similarity index 100% rename from trunk/arch/parisc/include/asm/page.h rename to trunk/include/asm-parisc/page.h diff --git a/trunk/arch/parisc/include/asm/param.h b/trunk/include/asm-parisc/param.h similarity index 100% rename from trunk/arch/parisc/include/asm/param.h rename to trunk/include/asm-parisc/param.h diff --git a/trunk/arch/parisc/include/asm/parisc-device.h b/trunk/include/asm-parisc/parisc-device.h similarity index 100% rename from trunk/arch/parisc/include/asm/parisc-device.h rename to trunk/include/asm-parisc/parisc-device.h diff --git a/trunk/arch/parisc/include/asm/parport.h b/trunk/include/asm-parisc/parport.h similarity index 100% rename from trunk/arch/parisc/include/asm/parport.h rename to trunk/include/asm-parisc/parport.h diff --git a/trunk/arch/parisc/include/asm/pci.h b/trunk/include/asm-parisc/pci.h similarity index 100% rename from trunk/arch/parisc/include/asm/pci.h rename to trunk/include/asm-parisc/pci.h diff --git a/trunk/arch/parisc/include/asm/pdc.h b/trunk/include/asm-parisc/pdc.h similarity index 99% rename from trunk/arch/parisc/include/asm/pdc.h rename to trunk/include/asm-parisc/pdc.h index c584b00c6074..9eaa794c3e4a 100644 --- a/trunk/arch/parisc/include/asm/pdc.h +++ b/trunk/include/asm-parisc/pdc.h @@ -332,9 +332,6 @@ #define BOOT_CONSOLE_SPA_OFFSET 0x3c4 #define BOOT_CONSOLE_PATH_OFFSET 0x3a8 -/* size of the pdc_result buffer for firmware.c */ -#define NUM_PDC_RESULT 32 - #if !defined(__ASSEMBLY__) #ifdef __KERNEL__ @@ -603,7 +600,6 @@ int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsi int pdc_chassis_disp(unsigned long disp); int pdc_chassis_warn(unsigned long *warn); int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info); -int pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info); int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, void *iodc_data, unsigned int iodc_data_size); int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, @@ -642,7 +638,6 @@ int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr, #endif void set_firmware_width(void); -void set_firmware_width_unlocked(void); int pdc_do_firm_test_reset(unsigned long ftc_bitmap); int pdc_do_reset(void); int pdc_soft_power_info(unsigned long *power_reg); diff --git a/trunk/arch/parisc/include/asm/pdc_chassis.h b/trunk/include/asm-parisc/pdc_chassis.h similarity index 100% rename from trunk/arch/parisc/include/asm/pdc_chassis.h rename to trunk/include/asm-parisc/pdc_chassis.h diff --git a/trunk/arch/parisc/include/asm/pdcpat.h b/trunk/include/asm-parisc/pdcpat.h similarity index 100% rename from trunk/arch/parisc/include/asm/pdcpat.h rename to trunk/include/asm-parisc/pdcpat.h diff --git a/trunk/arch/parisc/include/asm/percpu.h b/trunk/include/asm-parisc/percpu.h similarity index 100% rename from trunk/arch/parisc/include/asm/percpu.h rename to trunk/include/asm-parisc/percpu.h diff --git a/trunk/arch/parisc/include/asm/perf.h b/trunk/include/asm-parisc/perf.h similarity index 100% rename from trunk/arch/parisc/include/asm/perf.h rename to trunk/include/asm-parisc/perf.h diff --git a/trunk/arch/parisc/include/asm/pgalloc.h b/trunk/include/asm-parisc/pgalloc.h similarity index 100% rename from trunk/arch/parisc/include/asm/pgalloc.h rename to trunk/include/asm-parisc/pgalloc.h diff --git a/trunk/arch/parisc/include/asm/pgtable.h b/trunk/include/asm-parisc/pgtable.h similarity index 100% rename from trunk/arch/parisc/include/asm/pgtable.h rename to trunk/include/asm-parisc/pgtable.h diff --git a/trunk/arch/parisc/include/asm/poll.h b/trunk/include/asm-parisc/poll.h similarity index 100% rename from trunk/arch/parisc/include/asm/poll.h rename to trunk/include/asm-parisc/poll.h diff --git a/trunk/arch/parisc/include/asm/posix_types.h b/trunk/include/asm-parisc/posix_types.h similarity index 100% rename from trunk/arch/parisc/include/asm/posix_types.h rename to trunk/include/asm-parisc/posix_types.h diff --git a/trunk/arch/parisc/include/asm/prefetch.h b/trunk/include/asm-parisc/prefetch.h similarity index 100% rename from trunk/arch/parisc/include/asm/prefetch.h rename to trunk/include/asm-parisc/prefetch.h diff --git a/trunk/arch/parisc/include/asm/processor.h b/trunk/include/asm-parisc/processor.h similarity index 100% rename from trunk/arch/parisc/include/asm/processor.h rename to trunk/include/asm-parisc/processor.h diff --git a/trunk/arch/parisc/include/asm/psw.h b/trunk/include/asm-parisc/psw.h similarity index 100% rename from trunk/arch/parisc/include/asm/psw.h rename to trunk/include/asm-parisc/psw.h diff --git a/trunk/arch/parisc/include/asm/ptrace.h b/trunk/include/asm-parisc/ptrace.h similarity index 85% rename from trunk/arch/parisc/include/asm/ptrace.h rename to trunk/include/asm-parisc/ptrace.h index afa5333187b4..3e94c5d85ff5 100644 --- a/trunk/arch/parisc/include/asm/ptrace.h +++ b/trunk/include/asm-parisc/ptrace.h @@ -47,16 +47,6 @@ struct pt_regs { #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) -#define __ARCH_WANT_COMPAT_SYS_PTRACE - -struct task_struct; -#define arch_has_single_step() 1 -void user_disable_single_step(struct task_struct *task); -void user_enable_single_step(struct task_struct *task); - -#define arch_has_block_step() 1 -void user_enable_block_step(struct task_struct *task); - /* XXX should we use iaoq[1] or iaoq[0] ? */ #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) #define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0) diff --git a/trunk/arch/parisc/include/asm/real.h b/trunk/include/asm-parisc/real.h similarity index 100% rename from trunk/arch/parisc/include/asm/real.h rename to trunk/include/asm-parisc/real.h diff --git a/trunk/arch/parisc/include/asm/resource.h b/trunk/include/asm-parisc/resource.h similarity index 100% rename from trunk/arch/parisc/include/asm/resource.h rename to trunk/include/asm-parisc/resource.h diff --git a/trunk/arch/parisc/include/asm/ropes.h b/trunk/include/asm-parisc/ropes.h similarity index 99% rename from trunk/arch/parisc/include/asm/ropes.h rename to trunk/include/asm-parisc/ropes.h index 09f51d5ab57c..007a880615eb 100644 --- a/trunk/arch/parisc/include/asm/ropes.h +++ b/trunk/include/asm-parisc/ropes.h @@ -1,7 +1,7 @@ #ifndef _ASM_PARISC_ROPES_H_ #define _ASM_PARISC_ROPES_H_ -#include +#include #ifdef CONFIG_64BIT /* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */ diff --git a/trunk/arch/parisc/include/asm/rt_sigframe.h b/trunk/include/asm-parisc/rt_sigframe.h similarity index 100% rename from trunk/arch/parisc/include/asm/rt_sigframe.h rename to trunk/include/asm-parisc/rt_sigframe.h diff --git a/trunk/arch/parisc/include/asm/rtc.h b/trunk/include/asm-parisc/rtc.h similarity index 100% rename from trunk/arch/parisc/include/asm/rtc.h rename to trunk/include/asm-parisc/rtc.h diff --git a/trunk/arch/parisc/include/asm/runway.h b/trunk/include/asm-parisc/runway.h similarity index 100% rename from trunk/arch/parisc/include/asm/runway.h rename to trunk/include/asm-parisc/runway.h diff --git a/trunk/arch/parisc/include/asm/scatterlist.h b/trunk/include/asm-parisc/scatterlist.h similarity index 100% rename from trunk/arch/parisc/include/asm/scatterlist.h rename to trunk/include/asm-parisc/scatterlist.h diff --git a/trunk/arch/parisc/include/asm/sections.h b/trunk/include/asm-parisc/sections.h similarity index 100% rename from trunk/arch/parisc/include/asm/sections.h rename to trunk/include/asm-parisc/sections.h diff --git a/trunk/arch/parisc/include/asm/segment.h b/trunk/include/asm-parisc/segment.h similarity index 100% rename from trunk/arch/parisc/include/asm/segment.h rename to trunk/include/asm-parisc/segment.h diff --git a/trunk/arch/parisc/include/asm/sembuf.h b/trunk/include/asm-parisc/sembuf.h similarity index 100% rename from trunk/arch/parisc/include/asm/sembuf.h rename to trunk/include/asm-parisc/sembuf.h diff --git a/trunk/arch/parisc/include/asm/serial.h b/trunk/include/asm-parisc/serial.h similarity index 100% rename from trunk/arch/parisc/include/asm/serial.h rename to trunk/include/asm-parisc/serial.h diff --git a/trunk/arch/parisc/include/asm/setup.h b/trunk/include/asm-parisc/setup.h similarity index 100% rename from trunk/arch/parisc/include/asm/setup.h rename to trunk/include/asm-parisc/setup.h diff --git a/trunk/arch/parisc/include/asm/shmbuf.h b/trunk/include/asm-parisc/shmbuf.h similarity index 100% rename from trunk/arch/parisc/include/asm/shmbuf.h rename to trunk/include/asm-parisc/shmbuf.h diff --git a/trunk/arch/parisc/include/asm/shmparam.h b/trunk/include/asm-parisc/shmparam.h similarity index 100% rename from trunk/arch/parisc/include/asm/shmparam.h rename to trunk/include/asm-parisc/shmparam.h diff --git a/trunk/arch/parisc/include/asm/sigcontext.h b/trunk/include/asm-parisc/sigcontext.h similarity index 100% rename from trunk/arch/parisc/include/asm/sigcontext.h rename to trunk/include/asm-parisc/sigcontext.h diff --git a/trunk/arch/parisc/include/asm/siginfo.h b/trunk/include/asm-parisc/siginfo.h similarity index 100% rename from trunk/arch/parisc/include/asm/siginfo.h rename to trunk/include/asm-parisc/siginfo.h diff --git a/trunk/arch/parisc/include/asm/signal.h b/trunk/include/asm-parisc/signal.h similarity index 100% rename from trunk/arch/parisc/include/asm/signal.h rename to trunk/include/asm-parisc/signal.h diff --git a/trunk/arch/parisc/include/asm/smp.h b/trunk/include/asm-parisc/smp.h similarity index 100% rename from trunk/arch/parisc/include/asm/smp.h rename to trunk/include/asm-parisc/smp.h diff --git a/trunk/arch/parisc/include/asm/socket.h b/trunk/include/asm-parisc/socket.h similarity index 100% rename from trunk/arch/parisc/include/asm/socket.h rename to trunk/include/asm-parisc/socket.h diff --git a/trunk/arch/parisc/include/asm/sockios.h b/trunk/include/asm-parisc/sockios.h similarity index 100% rename from trunk/arch/parisc/include/asm/sockios.h rename to trunk/include/asm-parisc/sockios.h diff --git a/trunk/arch/parisc/include/asm/spinlock.h b/trunk/include/asm-parisc/spinlock.h similarity index 100% rename from trunk/arch/parisc/include/asm/spinlock.h rename to trunk/include/asm-parisc/spinlock.h diff --git a/trunk/arch/parisc/include/asm/spinlock_types.h b/trunk/include/asm-parisc/spinlock_types.h similarity index 100% rename from trunk/arch/parisc/include/asm/spinlock_types.h rename to trunk/include/asm-parisc/spinlock_types.h diff --git a/trunk/arch/parisc/include/asm/stat.h b/trunk/include/asm-parisc/stat.h similarity index 100% rename from trunk/arch/parisc/include/asm/stat.h rename to trunk/include/asm-parisc/stat.h diff --git a/trunk/arch/parisc/include/asm/statfs.h b/trunk/include/asm-parisc/statfs.h similarity index 100% rename from trunk/arch/parisc/include/asm/statfs.h rename to trunk/include/asm-parisc/statfs.h diff --git a/trunk/arch/parisc/include/asm/string.h b/trunk/include/asm-parisc/string.h similarity index 100% rename from trunk/arch/parisc/include/asm/string.h rename to trunk/include/asm-parisc/string.h diff --git a/trunk/arch/parisc/include/asm/superio.h b/trunk/include/asm-parisc/superio.h similarity index 100% rename from trunk/arch/parisc/include/asm/superio.h rename to trunk/include/asm-parisc/superio.h diff --git a/trunk/arch/parisc/include/asm/system.h b/trunk/include/asm-parisc/system.h similarity index 100% rename from trunk/arch/parisc/include/asm/system.h rename to trunk/include/asm-parisc/system.h diff --git a/trunk/arch/parisc/include/asm/termbits.h b/trunk/include/asm-parisc/termbits.h similarity index 100% rename from trunk/arch/parisc/include/asm/termbits.h rename to trunk/include/asm-parisc/termbits.h diff --git a/trunk/arch/parisc/include/asm/termios.h b/trunk/include/asm-parisc/termios.h similarity index 100% rename from trunk/arch/parisc/include/asm/termios.h rename to trunk/include/asm-parisc/termios.h diff --git a/trunk/arch/parisc/include/asm/thread_info.h b/trunk/include/asm-parisc/thread_info.h similarity index 100% rename from trunk/arch/parisc/include/asm/thread_info.h rename to trunk/include/asm-parisc/thread_info.h diff --git a/trunk/arch/parisc/include/asm/timex.h b/trunk/include/asm-parisc/timex.h similarity index 100% rename from trunk/arch/parisc/include/asm/timex.h rename to trunk/include/asm-parisc/timex.h diff --git a/trunk/arch/parisc/include/asm/tlb.h b/trunk/include/asm-parisc/tlb.h similarity index 100% rename from trunk/arch/parisc/include/asm/tlb.h rename to trunk/include/asm-parisc/tlb.h diff --git a/trunk/arch/parisc/include/asm/tlbflush.h b/trunk/include/asm-parisc/tlbflush.h similarity index 100% rename from trunk/arch/parisc/include/asm/tlbflush.h rename to trunk/include/asm-parisc/tlbflush.h diff --git a/trunk/arch/parisc/include/asm/topology.h b/trunk/include/asm-parisc/topology.h similarity index 100% rename from trunk/arch/parisc/include/asm/topology.h rename to trunk/include/asm-parisc/topology.h diff --git a/trunk/arch/parisc/include/asm/traps.h b/trunk/include/asm-parisc/traps.h similarity index 100% rename from trunk/arch/parisc/include/asm/traps.h rename to trunk/include/asm-parisc/traps.h diff --git a/trunk/arch/parisc/include/asm/types.h b/trunk/include/asm-parisc/types.h similarity index 100% rename from trunk/arch/parisc/include/asm/types.h rename to trunk/include/asm-parisc/types.h diff --git a/trunk/arch/parisc/include/asm/uaccess.h b/trunk/include/asm-parisc/uaccess.h similarity index 100% rename from trunk/arch/parisc/include/asm/uaccess.h rename to trunk/include/asm-parisc/uaccess.h diff --git a/trunk/arch/parisc/include/asm/ucontext.h b/trunk/include/asm-parisc/ucontext.h similarity index 100% rename from trunk/arch/parisc/include/asm/ucontext.h rename to trunk/include/asm-parisc/ucontext.h diff --git a/trunk/arch/parisc/include/asm/unaligned.h b/trunk/include/asm-parisc/unaligned.h similarity index 100% rename from trunk/arch/parisc/include/asm/unaligned.h rename to trunk/include/asm-parisc/unaligned.h diff --git a/trunk/arch/parisc/include/asm/unistd.h b/trunk/include/asm-parisc/unistd.h similarity index 99% rename from trunk/arch/parisc/include/asm/unistd.h rename to trunk/include/asm-parisc/unistd.h index ef26b009dc5d..a7d857f0e4f4 100644 --- a/trunk/arch/parisc/include/asm/unistd.h +++ b/trunk/include/asm-parisc/unistd.h @@ -801,14 +801,8 @@ #define __NR_timerfd_create (__NR_Linux + 306) #define __NR_timerfd_settime (__NR_Linux + 307) #define __NR_timerfd_gettime (__NR_Linux + 308) -#define __NR_signalfd4 (__NR_Linux + 309) -#define __NR_eventfd2 (__NR_Linux + 310) -#define __NR_epoll_create1 (__NR_Linux + 311) -#define __NR_dup3 (__NR_Linux + 312) -#define __NR_pipe2 (__NR_Linux + 313) -#define __NR_inotify_init1 (__NR_Linux + 314) - -#define __NR_Linux_syscalls (__NR_inotify_init1 + 1) + +#define __NR_Linux_syscalls (__NR_timerfd_gettime + 1) #define __IGNORE_select /* newselect */ diff --git a/trunk/arch/parisc/include/asm/unwind.h b/trunk/include/asm-parisc/unwind.h similarity index 99% rename from trunk/arch/parisc/include/asm/unwind.h rename to trunk/include/asm-parisc/unwind.h index 52482e4fc20d..2f7e6e50a158 100644 --- a/trunk/arch/parisc/include/asm/unwind.h +++ b/trunk/include/asm-parisc/unwind.h @@ -74,6 +74,4 @@ void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *r int unwind_once(struct unwind_frame_info *info); int unwind_to_user(struct unwind_frame_info *info); -int unwind_init(void); - #endif diff --git a/trunk/arch/parisc/include/asm/user.h b/trunk/include/asm-parisc/user.h similarity index 100% rename from trunk/arch/parisc/include/asm/user.h rename to trunk/include/asm-parisc/user.h diff --git a/trunk/arch/parisc/include/asm/vga.h b/trunk/include/asm-parisc/vga.h similarity index 100% rename from trunk/arch/parisc/include/asm/vga.h rename to trunk/include/asm-parisc/vga.h diff --git a/trunk/arch/parisc/include/asm/xor.h b/trunk/include/asm-parisc/xor.h similarity index 100% rename from trunk/arch/parisc/include/asm/xor.h rename to trunk/include/asm-parisc/xor.h diff --git a/trunk/include/asm-xtensa/io.h b/trunk/include/asm-xtensa/io.h index 07b7299dab20..47c3616ea9ac 100644 --- a/trunk/include/asm-xtensa/io.h +++ b/trunk/include/asm-xtensa/io.h @@ -18,12 +18,10 @@ #include -#define XCHAL_KIO_CACHED_VADDR 0xe0000000 -#define XCHAL_KIO_BYPASS_VADDR 0xf0000000 +#define XCHAL_KIO_CACHED_VADDR 0xf0000000 +#define XCHAL_KIO_BYPASS_VADDR 0xf8000000 #define XCHAL_KIO_PADDR 0xf0000000 -#define XCHAL_KIO_SIZE 0x10000000 - -#define IOADDR(x) (XCHAL_KIO_BYPASS_VADDR + (x)) +#define XCHAL_KIO_SIZE 0x08000000 /* * swap functions to change byte order from little-endian to big-endian and diff --git a/trunk/include/asm-xtensa/rwsem.h b/trunk/include/asm-xtensa/rwsem.h index e39edf5c86f2..0aad3a587551 100644 --- a/trunk/include/asm-xtensa/rwsem.h +++ b/trunk/include/asm-xtensa/rwsem.h @@ -13,10 +13,6 @@ #ifndef _XTENSA_RWSEM_H #define _XTENSA_RWSEM_H -#ifndef _LINUX_RWSEM_H -#error "Please don't include directly, use instead." -#endif - #include #include #include diff --git a/trunk/include/asm-xtensa/variant-dc232b/core.h b/trunk/include/asm-xtensa/variant-dc232b/core.h deleted file mode 100644 index 525bd3d90154..000000000000 --- a/trunk/include/asm-xtensa/variant-dc232b/core.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Xtensa processor core configuration information. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 1999-2007 Tensilica Inc. - */ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 1 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 0 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_FP 0 /* floating point pkg */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ - - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 4 /* data width in bytes */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ - -#define XCHAL_SW_VERSION 701001 /* sw version of this header */ - -#define XCHAL_CORE_ID "dc232b" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_CORE_DESCRIPTION "Diamond 232L Standard Core Rev.B (LE)" -#define XCHAL_BUILD_UNIQUE_ID 0x0000BEEF /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC56307FE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x0D40BEEF /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX2.1.1" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2210 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 221001 /* major*100+minor */ -#define XCHAL_HW_REL_LX2 1 -#define XCHAL_HW_REL_LX2_1 1 -#define XCHAL_HW_REL_LX2_1_1 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2210 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 221001 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2210 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 221001 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 32 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 32 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 5 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 5 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 16384 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 7 -#define XCHAL_DCACHE_SETWIDTH 7 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 4 -#define XCHAL_DCACHE_WAYS 4 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY 0 -#define XCHAL_DCACHE_ECC_PARITY 0 - -/* Number of encoded cache attr bits (see for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 22 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 17 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x001F80FF -#define XCHAL_INTLEVEL2_MASK 0x00000100 -#define XCHAL_INTLEVEL3_MASK 0x00200E00 -#define XCHAL_INTLEVEL4_MASK 0x00001000 -#define XCHAL_INTLEVEL5_MASK 0x00002000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00004000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x001F80FF -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x001F81FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x003F8FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x003F9FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x003FBFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x003FBFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x003FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 1 -#define XCHAL_INT5_LEVEL 1 -#define XCHAL_INT6_LEVEL 1 -#define XCHAL_INT7_LEVEL 1 -#define XCHAL_INT8_LEVEL 2 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 5 -#define XCHAL_INT14_LEVEL 7 -#define XCHAL_INT15_LEVEL 1 -#define XCHAL_INT16_LEVEL 1 -#define XCHAL_INT17_LEVEL 1 -#define XCHAL_INT18_LEVEL 1 -#define XCHAL_INT19_LEVEL 1 -#define XCHAL_INT20_LEVEL 1 -#define XCHAL_INT21_LEVEL 3 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_EDGE -#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_EDGE - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000880 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x003F8000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F -#define XCHAL_INTTYPE_MASK_TIMER 0x00002440 -#define XCHAL_INTTYPE_MASK_NMI 0x00004000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 10 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 13 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL2_NUM 8 -#define XCHAL_INTLEVEL4_NUM 12 -#define XCHAL_INTLEVEL5_NUM 13 -#define XCHAL_INTLEVEL7_NUM 14 -/* (There are many interrupts each at level(s) 1, 3.) */ - - -/* - * External interrupt vectors/levels. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */ -#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ -#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ -#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ -#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ -#define XCHAL_EXTINT6_NUM 8 /* (intlevel 2) */ -#define XCHAL_EXTINT7_NUM 9 /* (intlevel 3) */ -#define XCHAL_EXTINT8_NUM 12 /* (intlevel 4) */ -#define XCHAL_EXTINT9_NUM 14 /* (intlevel 7) */ -#define XCHAL_EXTINT10_NUM 15 /* (intlevel 1) */ -#define XCHAL_EXTINT11_NUM 16 /* (intlevel 1) */ -#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */ -#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */ -#define XCHAL_EXTINT14_NUM 19 /* (intlevel 1) */ -#define XCHAL_EXTINT15_NUM 20 /* (intlevel 1) */ -#define XCHAL_EXTINT16_NUM 21 /* (intlevel 3) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0xD0000000 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0x00000000 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0xFE000000 -#define XCHAL_RESET_VECTOR0_PADDR 0xFE000000 -#define XCHAL_RESET_VECTOR1_VADDR 0xD8000500 -#define XCHAL_RESET_VECTOR1_PADDR 0x00000500 -#define XCHAL_RESET_VECTOR_VADDR 0xFE000000 -#define XCHAL_RESET_VECTOR_PADDR 0xFE000000 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0xD0000340 -#define XCHAL_USER_VECTOR_PADDR 0x00000340 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0xD0000300 -#define XCHAL_KERNEL_VECTOR_PADDR 0x00000300 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xD00003C0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x000003C0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0xD0000000 -#define XCHAL_WINDOW_VECTORS_PADDR 0x00000000 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xD0000180 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000180 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xD00001C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x000001C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xD0000200 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x00000200 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0xD0000240 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x00000240 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0xD0000280 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x00000280 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0xD00002C0 -#define XCHAL_NMI_VECTOR_PADDR 0x000002C0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ -#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 1 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ -/* If none of the above last 4 are set, it's a custom TLB configuration. */ -#define XCHAL_ITLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */ -#define XCHAL_DTLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */ - -#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 4 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 2 /* num of bits in RING field */ - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - diff --git a/trunk/include/asm-xtensa/variant-dc232b/tie-asm.h b/trunk/include/asm-xtensa/variant-dc232b/tie-asm.h deleted file mode 100644 index ed4f53f529db..000000000000 --- a/trunk/include/asm-xtensa/variant-dc232b/tie-asm.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This header file contains assembly-language definitions (assembly - * macros, etc.) for this specific Xtensa processor's TIE extensions - * and options. It is customized to this Xtensa processor configuration. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1999-2007 Tensilica Inc. - */ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ - - - -/* Macro to save all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Save area ptr (clobbered): ptr (1 byte aligned) - * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL - xchal_sa_start \continue, \ofs - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-8, 4, 4 - rsr \at1, ACCLO // MAC16 accumulator - rsr \at2, ACCHI - s32i \at1, \ptr, .Lxchal_ofs_ + 0 - s32i \at2, \ptr, .Lxchal_ofs_ + 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-16, 4, 4 - rsr \at1, M0 // MAC16 registers - rsr \at2, M1 - s32i \at1, \ptr, .Lxchal_ofs_ + 0 - s32i \at2, \ptr, .Lxchal_ofs_ + 4 - rsr \at1, M2 - rsr \at2, M3 - s32i \at1, \ptr, .Lxchal_ofs_ + 8 - s32i \at2, \ptr, .Lxchal_ofs_ + 12 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 16 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-4, 4, 4 - rsr \at1, SCOMPARE1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_ + 0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select - xchal_sa_align \ptr, 0, 1024-4, 4, 4 - rur \at1, THREADPTR // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_ + 0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - .endm // xchal_ncp_store - -/* Macro to save all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Save area ptr (clobbered): ptr (1 byte aligned) - * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL - xchal_sa_start \continue, \ofs - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-8, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_ + 0 - l32i \at2, \ptr, .Lxchal_ofs_ + 4 - wsr \at1, ACCLO // MAC16 accumulator - wsr \at2, ACCHI - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-16, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_ + 0 - l32i \at2, \ptr, .Lxchal_ofs_ + 4 - wsr \at1, M0 // MAC16 registers - wsr \at2, M1 - l32i \at1, \ptr, .Lxchal_ofs_ + 8 - l32i \at2, \ptr, .Lxchal_ofs_ + 12 - wsr \at1, M2 - wsr \at2, M3 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 16 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select - xchal_sa_align \ptr, 0, 1024-4, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_ + 0 - wsr \at1, SCOMPARE1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select - xchal_sa_align \ptr, 0, 1024-4, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_ + 0 - wur \at1, THREADPTR // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - .endm // xchal_ncp_load - - - -#define XCHAL_NCP_NUM_ATMPS 2 - - -#define XCHAL_SA_NUM_ATMPS 2 - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - diff --git a/trunk/include/asm-xtensa/variant-dc232b/tie.h b/trunk/include/asm-xtensa/variant-dc232b/tie.h deleted file mode 100644 index 018e81af4393..000000000000 --- a/trunk/include/asm-xtensa/variant-dc232b/tie.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This header file describes this specific Xtensa processor's TIE extensions - * that extend basic Xtensa core functionality. It is customized to this - * Xtensa processor configuration. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1999-2007 Tensilica Inc. - */ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 1 /* number of coprocessors */ -#define XCHAL_CP_MAX 8 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x80 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x80 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP7_NAME "XTIOP" -#define XCHAL_CP7_IDENT XTIOP -#define XCHAL_CP7_SA_SIZE 0 /* size of state save area */ -#define XCHAL_CP7_SA_ALIGN 1 /* min alignment of save area */ -#define XCHAL_CP_ID_XTIOP 7 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP0_SA_SIZE 0 -#define XCHAL_CP0_SA_ALIGN 1 -#define XCHAL_CP1_SA_SIZE 0 -#define XCHAL_CP1_SA_ALIGN 1 -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 32 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 32 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 4 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see ) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 8 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,0,0,1, acclo, 4, 4, 4,0x0210, sr,16 , 32,0,0,0) \ - XCHAL_SA_REG(s,1,0,0,1, acchi, 4, 4, 4,0x0211, sr,17 , 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m0, 4, 4, 4,0x0220, sr,32 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m1, 4, 4, 4,0x0221, sr,33 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m2, 4, 4, 4,0x0222, sr,34 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m3, 4, 4, 4,0x0223, sr,35 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 0 -#define XCHAL_CP0_SA_LIST(s) /* empty */ - -#define XCHAL_CP1_SA_NUM 0 -#define XCHAL_CP1_SA_LIST(s) /* empty */ - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3 - -#endif /*_XTENSA_CORE_TIE_H*/ - diff --git a/trunk/include/linux/bitmap.h b/trunk/include/linux/bitmap.h index a08c33a26ca9..1abfe664c444 100644 --- a/trunk/include/linux/bitmap.h +++ b/trunk/include/linux/bitmap.h @@ -129,7 +129,6 @@ extern void bitmap_fold(unsigned long *dst, const unsigned long *orig, extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order); extern void bitmap_release_region(unsigned long *bitmap, int pos, int order); extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order); -extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits); #define BITMAP_LAST_WORD_MASK(nbits) \ ( \ diff --git a/trunk/include/linux/i2c/twl4030.h b/trunk/include/linux/i2c/twl4030.h index fb604dcd38f1..cdb453162a97 100644 --- a/trunk/include/linux/i2c/twl4030.h +++ b/trunk/include/linux/i2c/twl4030.h @@ -228,12 +228,6 @@ struct twl4030_gpio_platform_data { int gpio_base; unsigned irq_base, irq_end; - /* package the two LED signals as output-only GPIOs? */ - bool use_leds; - - /* gpio-n should control VMMC(n+1) if BIT(n) in mmc_cd is set */ - u8 mmc_cd; - /* For gpio-N, bit (1 << N) in "pullups" is set if that pullup * should be enabled. Else, if that bit is set in "pulldowns", * that pulldown is enabled. Don't waste power by letting any @@ -283,8 +277,6 @@ struct twl4030_platform_data { /*----------------------------------------------------------------------*/ -int twl4030_sih_setup(int module); - /* * FIXME completely stop using TWL4030_IRQ_BASE ... instead, pass the * IRQ data to subsidiary devices using platform device resources. @@ -299,16 +291,16 @@ int twl4030_sih_setup(int module); #define TWL4030_MODIRQ_BCI (TWL4030_IRQ_BASE + 2) #define TWL4030_MODIRQ_MADC (TWL4030_IRQ_BASE + 3) /* #define TWL4030_MODIRQ_USB (TWL4030_IRQ_BASE + 4) */ -/* #define TWL4030_MODIRQ_PWR (TWL4030_IRQ_BASE + 5) */ +#define TWL4030_MODIRQ_PWR (TWL4030_IRQ_BASE + 5) #define TWL4030_PWRIRQ_PWRBTN (TWL4030_PWR_IRQ_BASE + 0) -/* #define TWL4030_PWRIRQ_CHG_PRES (TWL4030_PWR_IRQ_BASE + 1) */ -/* #define TWL4030_PWRIRQ_USB_PRES (TWL4030_PWR_IRQ_BASE + 2) */ -/* #define TWL4030_PWRIRQ_RTC (TWL4030_PWR_IRQ_BASE + 3) */ -/* #define TWL4030_PWRIRQ_HOT_DIE (TWL4030_PWR_IRQ_BASE + 4) */ -/* #define TWL4030_PWRIRQ_PWROK_TIMEOUT (TWL4030_PWR_IRQ_BASE + 5) */ -/* #define TWL4030_PWRIRQ_MBCHG (TWL4030_PWR_IRQ_BASE + 6) */ -/* #define TWL4030_PWRIRQ_SC_DETECT (TWL4030_PWR_IRQ_BASE + 7) */ +#define TWL4030_PWRIRQ_CHG_PRES (TWL4030_PWR_IRQ_BASE + 1) +#define TWL4030_PWRIRQ_USB_PRES (TWL4030_PWR_IRQ_BASE + 2) +#define TWL4030_PWRIRQ_RTC (TWL4030_PWR_IRQ_BASE + 3) +#define TWL4030_PWRIRQ_HOT_DIE (TWL4030_PWR_IRQ_BASE + 4) +#define TWL4030_PWRIRQ_PWROK_TIMEOUT (TWL4030_PWR_IRQ_BASE + 5) +#define TWL4030_PWRIRQ_MBCHG (TWL4030_PWR_IRQ_BASE + 6) +#define TWL4030_PWRIRQ_SC_DETECT (TWL4030_PWR_IRQ_BASE + 7) /* Rest are unsued currently*/ @@ -325,13 +317,17 @@ int twl4030_sih_setup(int module); /* TWL4030 GPIO interrupt definitions */ #define TWL4030_GPIO_IRQ_NO(n) (TWL4030_GPIO_IRQ_BASE + (n)) +#define TWL4030_GPIO_IS_ENABLE 1 /* * Exported TWL4030 GPIO APIs * * WARNING -- use standard GPIO and IRQ calls instead; these will vanish. */ +int twl4030_get_gpio_datain(int gpio); +int twl4030_request_gpio(int gpio); int twl4030_set_gpio_debounce(int gpio, int enable); +int twl4030_free_gpio(int gpio); #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) diff --git a/trunk/include/linux/jbd.h b/trunk/include/linux/jbd.h index 346e2b80be7d..35d4f6342fac 100644 --- a/trunk/include/linux/jbd.h +++ b/trunk/include/linux/jbd.h @@ -911,7 +911,7 @@ extern int journal_set_features (journal_t *, unsigned long, unsigned long, unsigned long); extern int journal_create (journal_t *); extern int journal_load (journal_t *journal); -extern int journal_destroy (journal_t *); +extern void journal_destroy (journal_t *); extern int journal_recover (journal_t *journal); extern int journal_wipe (journal_t *, int); extern int journal_skip_recovery (journal_t *); diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index c261aa0584b1..947cf84e555d 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -340,9 +340,6 @@ enum { ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET, - /* mask of flags to transfer *to* the slave link */ - ATA_EHI_TO_SLAVE_MASK = ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, - /* max tries if error condition is still set after ->error_handler */ ATA_EH_MAX_TRIES = 5, diff --git a/trunk/include/linux/mlx4/cmd.h b/trunk/include/linux/mlx4/cmd.h index cf9c679ab38b..77323a72dd3c 100644 --- a/trunk/include/linux/mlx4/cmd.h +++ b/trunk/include/linux/mlx4/cmd.h @@ -132,15 +132,6 @@ enum { MLX4_MAILBOX_SIZE = 4096 }; -enum { - /* set port opcode modifiers */ - MLX4_SET_PORT_GENERAL = 0x0, - MLX4_SET_PORT_RQP_CALC = 0x1, - MLX4_SET_PORT_MAC_TABLE = 0x2, - MLX4_SET_PORT_VLAN_TABLE = 0x3, - MLX4_SET_PORT_PRIO_MAP = 0x4, -}; - struct mlx4_dev; struct mlx4_cmd_mailbox { diff --git a/trunk/include/linux/mlx4/device.h b/trunk/include/linux/mlx4/device.h index bd9977b89490..b2f944468313 100644 --- a/trunk/include/linux/mlx4/device.h +++ b/trunk/include/linux/mlx4/device.h @@ -60,7 +60,6 @@ enum { MLX4_DEV_CAP_FLAG_IPOIB_CSUM = 1 << 7, MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR = 1 << 8, MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1 << 9, - MLX4_DEV_CAP_FLAG_DPDP = 1 << 12, MLX4_DEV_CAP_FLAG_MEM_WINDOW = 1 << 16, MLX4_DEV_CAP_FLAG_APM = 1 << 17, MLX4_DEV_CAP_FLAG_ATOMIC = 1 << 18, @@ -146,29 +145,6 @@ enum { MLX4_MTT_FLAG_PRESENT = 1 }; -enum mlx4_qp_region { - MLX4_QP_REGION_FW = 0, - MLX4_QP_REGION_ETH_ADDR, - MLX4_QP_REGION_FC_ADDR, - MLX4_QP_REGION_FC_EXCH, - MLX4_NUM_QP_REGION -}; - -enum mlx4_port_type { - MLX4_PORT_TYPE_IB = 1 << 0, - MLX4_PORT_TYPE_ETH = 1 << 1, -}; - -enum mlx4_special_vlan_idx { - MLX4_NO_VLAN_IDX = 0, - MLX4_VLAN_MISS_IDX, - MLX4_VLAN_REGULAR -}; - -enum { - MLX4_NUM_FEXCH = 64 * 1024, -}; - static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) { return (major << 32) | (minor << 16) | subminor; @@ -178,9 +154,7 @@ struct mlx4_caps { u64 fw_ver; int num_ports; int vl_cap[MLX4_MAX_PORTS + 1]; - int ib_mtu_cap[MLX4_MAX_PORTS + 1]; - u64 def_mac[MLX4_MAX_PORTS + 1]; - int eth_mtu_cap[MLX4_MAX_PORTS + 1]; + int mtu_cap[MLX4_MAX_PORTS + 1]; int gid_table_len[MLX4_MAX_PORTS + 1]; int pkey_table_len[MLX4_MAX_PORTS + 1]; int local_ca_ack_delay; @@ -195,6 +169,7 @@ struct mlx4_caps { int max_rq_desc_sz; int max_qp_init_rdma; int max_qp_dest_rdma; + int reserved_qps; int sqp_start; int num_srqs; int max_srq_wqes; @@ -226,15 +201,6 @@ struct mlx4_caps { u16 stat_rate_support; u8 port_width_cap[MLX4_MAX_PORTS + 1]; int max_gso_sz; - int reserved_qps_cnt[MLX4_NUM_QP_REGION]; - int reserved_qps; - int reserved_qps_base[MLX4_NUM_QP_REGION]; - int log_num_macs; - int log_num_vlans; - int log_num_prios; - enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1]; - u8 supported_type[MLX4_MAX_PORTS + 1]; - u32 port_mask; }; struct mlx4_buf_list { @@ -389,11 +355,6 @@ struct mlx4_init_port_param { u64 si_guid; }; -#define mlx4_foreach_port(port, dev, type) \ - for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ - if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \ - ~(dev)->caps.port_mask) & 1 << ((port) - 1)) - int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, struct mlx4_buf *buf); void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf); @@ -439,10 +400,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, int collapsed); void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq); -int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base); -void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); - -int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp); +int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp); void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp); int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, @@ -458,12 +416,6 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback); int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]); -int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index); -void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index); - -int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); -void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); - int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list, int npages, u64 iova, u32 *lkey, u32 *rkey); int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, diff --git a/trunk/include/linux/oprofile.h b/trunk/include/linux/oprofile.h index 5231861f357d..bcb8f725427c 100644 --- a/trunk/include/linux/oprofile.h +++ b/trunk/include/linux/oprofile.h @@ -85,6 +85,13 @@ int oprofile_arch_init(struct oprofile_operations * ops); */ void oprofile_arch_exit(void); +/** + * Add data to the event buffer. + * The data passed is free-form, but typically consists of + * file offsets, dcookies, context information, and ESCAPE codes. + */ +void add_event_entry(unsigned long data); + /** * Add a sample. This may be called from any context. Pass * smp_processor_id() as cpu. @@ -155,14 +162,5 @@ int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, siz /** lock for read/write safety */ extern spinlock_t oprofilefs_lock; - -/** - * Add the contents of a circular buffer to the event buffer. - */ -void oprofile_put_buff(unsigned long *buf, unsigned int start, - unsigned int stop, unsigned int max); - -unsigned long oprofile_get_cpu_buffer_size(void); -void oprofile_cpu_buffer_inc_smpl_lost(void); #endif /* OPROFILE_H */ diff --git a/trunk/include/linux/page_cgroup.h b/trunk/include/linux/page_cgroup.h index f546ad6fc028..0fd39f2231ec 100644 --- a/trunk/include/linux/page_cgroup.h +++ b/trunk/include/linux/page_cgroup.h @@ -99,10 +99,5 @@ static inline struct page_cgroup *lookup_page_cgroup(struct page *page) { return NULL; } - -static inline void page_cgroup_init(void) -{ -} - #endif #endif diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 369f44286353..e5d344bfcb7e 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1944,14 +1944,6 @@ #define PCI_VENDOR_ID_OXSEMI 0x1415 #define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403 -#define PCI_DEVICE_ID_OXSEMI_PCIe840 0xC000 -#define PCI_DEVICE_ID_OXSEMI_PCIe840_G 0xC004 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_0 0xC100 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G 0xC104 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1 0xC110 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G 0xC114 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U 0xC118 -#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU 0xC11C #define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501 #define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511 #define PCI_DEVICE_ID_OXSEMI_16PCI954PP 0x9513 diff --git a/trunk/include/linux/profile.h b/trunk/include/linux/profile.h index a0fc32279fc0..570045053ce9 100644 --- a/trunk/include/linux/profile.h +++ b/trunk/include/linux/profile.h @@ -19,16 +19,10 @@ struct notifier_block; #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS) void create_prof_cpu_mask(struct proc_dir_entry *de); -int create_proc_profile(void); #else static inline void create_prof_cpu_mask(struct proc_dir_entry *de) { } - -static inline int create_proc_profile(void) -{ - return 0; -} #endif enum profile_type { @@ -43,6 +37,7 @@ extern int prof_on __read_mostly; /* init basic kernel profiler */ int profile_init(void); int profile_setup(char *str); +int create_proc_profile(void); void profile_tick(int type); /* diff --git a/trunk/include/linux/usb/wusb-wa.h b/trunk/include/linux/usb/wusb-wa.h deleted file mode 100644 index a102561e7026..000000000000 --- a/trunk/include/linux/usb/wusb-wa.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Wireless USB Wire Adapter constants and structures. - * - * Copyright (C) 2005-2006 Intel Corporation. - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * FIXME: organize properly, group logically - * - * All the event structures are defined in uwb/spec.h, as they are - * common to the WHCI and WUSB radio control interfaces. - * - * References: - * [WUSB] Wireless Universal Serial Bus Specification, revision 1.0, ch8 - */ -#ifndef __LINUX_USB_WUSB_WA_H -#define __LINUX_USB_WUSB_WA_H - -/** - * Radio Command Request for the Radio Control Interface - * - * Radio Control Interface command and event codes are the same as - * WHCI, and listed in include/linux/uwb.h:UWB_RC_{CMD,EVT}_* - */ -enum { - WA_EXEC_RC_CMD = 40, /* Radio Control command Request */ -}; - -/* Wireless Adapter Requests ([WUSB] table 8-51) */ -enum { - WUSB_REQ_ADD_MMC_IE = 20, - WUSB_REQ_REMOVE_MMC_IE = 21, - WUSB_REQ_SET_NUM_DNTS = 22, - WUSB_REQ_SET_CLUSTER_ID = 23, - WUSB_REQ_SET_DEV_INFO = 24, - WUSB_REQ_GET_TIME = 25, - WUSB_REQ_SET_STREAM_IDX = 26, - WUSB_REQ_SET_WUSB_MAS = 27, -}; - - -/* Wireless Adapter WUSB Channel Time types ([WUSB] table 8-52) */ -enum { - WUSB_TIME_ADJ = 0, - WUSB_TIME_BPST = 1, - WUSB_TIME_WUSB = 2, -}; - -enum { - WA_ENABLE = 0x01, - WA_RESET = 0x02, - RPIPE_PAUSE = 0x1, -}; - -/* Responses from Get Status request ([WUSB] section 8.3.1.6) */ -enum { - WA_STATUS_ENABLED = 0x01, - WA_STATUS_RESETTING = 0x02 -}; - -enum rpipe_crs { - RPIPE_CRS_CTL = 0x01, - RPIPE_CRS_ISO = 0x02, - RPIPE_CRS_BULK = 0x04, - RPIPE_CRS_INTR = 0x08 -}; - -/** - * RPipe descriptor ([WUSB] section 8.5.2.11) - * - * FIXME: explain rpipes - */ -struct usb_rpipe_descriptor { - u8 bLength; - u8 bDescriptorType; - __le16 wRPipeIndex; - __le16 wRequests; - __le16 wBlocks; /* rw if 0 */ - __le16 wMaxPacketSize; /* rw? */ - u8 bHSHubAddress; /* reserved: 0 */ - u8 bHSHubPort; /* ??? FIXME ??? */ - u8 bSpeed; /* rw: xfer rate 'enum uwb_phy_rate' */ - u8 bDeviceAddress; /* rw: Target device address */ - u8 bEndpointAddress; /* rw: Target EP address */ - u8 bDataSequence; /* ro: Current Data sequence */ - __le32 dwCurrentWindow; /* ro */ - u8 bMaxDataSequence; /* ro?: max supported seq */ - u8 bInterval; /* rw: */ - u8 bOverTheAirInterval; /* rw: */ - u8 bmAttribute; /* ro? */ - u8 bmCharacteristics; /* ro? enum rpipe_attr, supported xsactions */ - u8 bmRetryOptions; /* rw? */ - __le16 wNumTransactionErrors; /* rw */ -} __attribute__ ((packed)); - -/** - * Wire Adapter Notification types ([WUSB] sections 8.4.5 & 8.5.4) - * - * These are the notifications coming on the notification endpoint of - * an HWA and a DWA. - */ -enum wa_notif_type { - DWA_NOTIF_RWAKE = 0x91, - DWA_NOTIF_PORTSTATUS = 0x92, - WA_NOTIF_TRANSFER = 0x93, - HWA_NOTIF_BPST_ADJ = 0x94, - HWA_NOTIF_DN = 0x95, -}; - -/** - * Wire Adapter notification header - * - * Notifications coming from a wire adapter use a common header - * defined in [WUSB] sections 8.4.5 & 8.5.4. - */ -struct wa_notif_hdr { - u8 bLength; - u8 bNotifyType; /* enum wa_notif_type */ -} __attribute__((packed)); - -/** - * HWA DN Received notification [(WUSB] section 8.5.4.2) - * - * The DNData is specified in WUSB1.0[7.6]. For each device - * notification we received, we just need to dispatch it. - * - * @dndata: this is really an array of notifications, but all start - * with the same header. - */ -struct hwa_notif_dn { - struct wa_notif_hdr hdr; - u8 bSourceDeviceAddr; /* from errata 2005/07 */ - u8 bmAttributes; - struct wusb_dn_hdr dndata[]; -} __attribute__((packed)); - -/* [WUSB] section 8.3.3 */ -enum wa_xfer_type { - WA_XFER_TYPE_CTL = 0x80, - WA_XFER_TYPE_BI = 0x81, /* bulk/interrupt */ - WA_XFER_TYPE_ISO = 0x82, - WA_XFER_RESULT = 0x83, - WA_XFER_ABORT = 0x84, -}; - -/* [WUSB] section 8.3.3 */ -struct wa_xfer_hdr { - u8 bLength; /* 0x18 */ - u8 bRequestType; /* 0x80 WA_REQUEST_TYPE_CTL */ - __le16 wRPipe; /* RPipe index */ - __le32 dwTransferID; /* Host-assigned ID */ - __le32 dwTransferLength; /* Length of data to xfer */ - u8 bTransferSegment; -} __attribute__((packed)); - -struct wa_xfer_ctl { - struct wa_xfer_hdr hdr; - u8 bmAttribute; - __le16 wReserved; - struct usb_ctrlrequest baSetupData; -} __attribute__((packed)); - -struct wa_xfer_bi { - struct wa_xfer_hdr hdr; - u8 bReserved; - __le16 wReserved; -} __attribute__((packed)); - -struct wa_xfer_hwaiso { - struct wa_xfer_hdr hdr; - u8 bReserved; - __le16 wPresentationTime; - __le32 dwNumOfPackets; - /* FIXME: u8 pktdata[]? */ -} __attribute__((packed)); - -/* [WUSB] section 8.3.3.5 */ -struct wa_xfer_abort { - u8 bLength; - u8 bRequestType; - __le16 wRPipe; /* RPipe index */ - __le32 dwTransferID; /* Host-assigned ID */ -} __attribute__((packed)); - -/** - * WA Transfer Complete notification ([WUSB] section 8.3.3.3) - * - */ -struct wa_notif_xfer { - struct wa_notif_hdr hdr; - u8 bEndpoint; - u8 Reserved; -} __attribute__((packed)); - -/** Transfer result basic codes [WUSB] table 8-15 */ -enum { - WA_XFER_STATUS_SUCCESS, - WA_XFER_STATUS_HALTED, - WA_XFER_STATUS_DATA_BUFFER_ERROR, - WA_XFER_STATUS_BABBLE, - WA_XFER_RESERVED, - WA_XFER_STATUS_NOT_FOUND, - WA_XFER_STATUS_INSUFFICIENT_RESOURCE, - WA_XFER_STATUS_TRANSACTION_ERROR, - WA_XFER_STATUS_ABORTED, - WA_XFER_STATUS_RPIPE_NOT_READY, - WA_XFER_INVALID_FORMAT, - WA_XFER_UNEXPECTED_SEGMENT_NUMBER, - WA_XFER_STATUS_RPIPE_TYPE_MISMATCH, -}; - -/** [WUSB] section 8.3.3.4 */ -struct wa_xfer_result { - struct wa_notif_hdr hdr; - __le32 dwTransferID; - __le32 dwTransferLength; - u8 bTransferSegment; - u8 bTransferStatus; - __le32 dwNumOfPackets; -} __attribute__((packed)); - -/** - * Wire Adapter Class Descriptor ([WUSB] section 8.5.2.7). - * - * NOTE: u16 fields are read Little Endian from the hardware. - * - * @bNumPorts is the original max number of devices that the host can - * connect; we might chop this so the stack can handle - * it. In case you need to access it, use wusbhc->ports_max - * if it is a Wireless USB WA. - */ -struct usb_wa_descriptor { - u8 bLength; - u8 bDescriptorType; - u16 bcdWAVersion; - u8 bNumPorts; /* don't use!! */ - u8 bmAttributes; /* Reserved == 0 */ - u16 wNumRPipes; - u16 wRPipeMaxBlock; - u8 bRPipeBlockSize; - u8 bPwrOn2PwrGood; - u8 bNumMMCIEs; - u8 DeviceRemovable; /* FIXME: in DWA this is up to 16 bytes */ -} __attribute__((packed)); - -/** - * HWA Device Information Buffer (WUSB1.0[T8.54]) - */ -struct hwa_dev_info { - u8 bmDeviceAvailability[32]; /* FIXME: ignored for now */ - u8 bDeviceAddress; - __le16 wPHYRates; - u8 bmDeviceAttribute; -} __attribute__((packed)); - -#endif /* #ifndef __LINUX_USB_WUSB_WA_H */ diff --git a/trunk/include/linux/usb/wusb.h b/trunk/include/linux/usb/wusb.h deleted file mode 100644 index 5f401b644ed5..000000000000 --- a/trunk/include/linux/usb/wusb.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Wireless USB Standard Definitions - * Event Size Tables - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * FIXME: organize properly, group logically - * - * All the event structures are defined in uwb/spec.h, as they are - * common to the WHCI and WUSB radio control interfaces. - */ - -#ifndef __WUSB_H__ -#define __WUSB_H__ - -#include -#include -#include -#include -#include - -/** - * WUSB Information Element header - * - * I don't know why, they decided to make it different to the MBOA MAC - * IE Header; beats me. - */ -struct wuie_hdr { - u8 bLength; - u8 bIEIdentifier; -} __attribute__((packed)); - -enum { - WUIE_ID_WCTA = 0x80, - WUIE_ID_CONNECTACK, - WUIE_ID_HOST_INFO, - WUIE_ID_CHANGE_ANNOUNCE, - WUIE_ID_DEVICE_DISCONNECT, - WUIE_ID_HOST_DISCONNECT, - WUIE_ID_KEEP_ALIVE = 0x89, - WUIE_ID_ISOCH_DISCARD, - WUIE_ID_RESET_DEVICE, -}; - -/** - * Maximum number of array elements in a WUSB IE. - * - * WUSB1.0[7.5 before table 7-38] says that in WUSB IEs that - * are "arrays" have to limited to 4 elements. So we define it - * like that to ease up and submit only the neeed size. - */ -#define WUIE_ELT_MAX 4 - -/** - * Wrapper for the data that defines a CHID, a CDID or a CK - * - * WUSB defines that CHIDs, CDIDs and CKs are a 16 byte string of - * data. In order to avoid confusion and enforce types, we wrap it. - * - * Make it packed, as we use it in some hw defintions. - */ -struct wusb_ckhdid { - u8 data[16]; -} __attribute__((packed)); - -const static -struct wusb_ckhdid wusb_ckhdid_zero = { .data = { 0 } }; - -#define WUSB_CKHDID_STRSIZE (3 * sizeof(struct wusb_ckhdid) + 1) - -/** - * WUSB IE: Host Information (WUSB1.0[7.5.2]) - * - * Used to provide information about the host to the Wireless USB - * devices in range (CHID can be used as an ASCII string). - */ -struct wuie_host_info { - struct wuie_hdr hdr; - __le16 attributes; - struct wusb_ckhdid CHID; -} __attribute__((packed)); - -/** - * WUSB IE: Connect Ack (WUSB1.0[7.5.1]) - * - * Used to acknowledge device connect requests. See note for - * WUIE_ELT_MAX. - */ -struct wuie_connect_ack { - struct wuie_hdr hdr; - struct { - struct wusb_ckhdid CDID; - u8 bDeviceAddress; /* 0 means unused */ - u8 bReserved; - } blk[WUIE_ELT_MAX]; -} __attribute__((packed)); - -/** - * WUSB IE Host Information Element, Connect Availability - * - * WUSB1.0[7.5.2], bmAttributes description - */ -enum { - WUIE_HI_CAP_RECONNECT = 0, - WUIE_HI_CAP_LIMITED, - WUIE_HI_CAP_RESERVED, - WUIE_HI_CAP_ALL, -}; - -/** - * WUSB IE: Channel Stop (WUSB1.0[7.5.8]) - * - * Tells devices the host is going to stop sending MMCs and will dissapear. - */ -struct wuie_channel_stop { - struct wuie_hdr hdr; - u8 attributes; - u8 timestamp[3]; -} __attribute__((packed)); - -/** - * WUSB IE: Keepalive (WUSB1.0[7.5.9]) - * - * Ask device(s) to send keepalives. - */ -struct wuie_keep_alive { - struct wuie_hdr hdr; - u8 bDeviceAddress[WUIE_ELT_MAX]; -} __attribute__((packed)); - -/** - * WUSB IE: Reset device (WUSB1.0[7.5.11]) - * - * Tell device to reset; in all truth, we can fit 4 CDIDs, but we only - * use it for one at the time... - * - * In any case, this request is a wee bit silly: why don't they target - * by address?? - */ -struct wuie_reset { - struct wuie_hdr hdr; - struct wusb_ckhdid CDID; -} __attribute__((packed)); - -/** - * WUSB IE: Disconnect device (WUSB1.0[7.5.11]) - * - * Tell device to disconnect; we can fit 4 addresses, but we only use - * it for one at the time... - */ -struct wuie_disconnect { - struct wuie_hdr hdr; - u8 bDeviceAddress; - u8 padding; -} __attribute__((packed)); - -/** - * WUSB IE: Host disconnect ([WUSB] section 7.5.5) - * - * Tells all connected devices to disconnect. - */ -struct wuie_host_disconnect { - struct wuie_hdr hdr; -} __attribute__((packed)); - -/** - * WUSB Device Notification header (WUSB1.0[7.6]) - */ -struct wusb_dn_hdr { - u8 bType; - u8 notifdata[]; -} __attribute__((packed)); - -/** Device Notification codes (WUSB1.0[Table 7-54]) */ -enum WUSB_DN { - WUSB_DN_CONNECT = 0x01, - WUSB_DN_DISCONNECT = 0x02, - WUSB_DN_EPRDY = 0x03, - WUSB_DN_MASAVAILCHANGED = 0x04, - WUSB_DN_RWAKE = 0x05, - WUSB_DN_SLEEP = 0x06, - WUSB_DN_ALIVE = 0x07, -}; - -/** WUSB Device Notification Connect */ -struct wusb_dn_connect { - struct wusb_dn_hdr hdr; - __le16 attributes; - struct wusb_ckhdid CDID; -} __attribute__((packed)); - -static inline int wusb_dn_connect_prev_dev_addr(const struct wusb_dn_connect *dn) -{ - return le16_to_cpu(dn->attributes) & 0xff; -} - -static inline int wusb_dn_connect_new_connection(const struct wusb_dn_connect *dn) -{ - return (le16_to_cpu(dn->attributes) >> 8) & 0x1; -} - -static inline int wusb_dn_connect_beacon_behavior(const struct wusb_dn_connect *dn) -{ - return (le16_to_cpu(dn->attributes) >> 9) & 0x03; -} - -/** Device is alive (aka: pong) (WUSB1.0[7.6.7]) */ -struct wusb_dn_alive { - struct wusb_dn_hdr hdr; -} __attribute__((packed)); - -/** Device is disconnecting (WUSB1.0[7.6.2]) */ -struct wusb_dn_disconnect { - struct wusb_dn_hdr hdr; -} __attribute__((packed)); - -/* General constants */ -enum { - WUSB_TRUST_TIMEOUT_MS = 4000, /* [WUSB] section 4.15.1 */ -}; - -static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, - const struct wusb_ckhdid *ckhdid) -{ - return scnprintf(pr_ckhdid, size, - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", - ckhdid->data[0], ckhdid->data[1], - ckhdid->data[2], ckhdid->data[3], - ckhdid->data[4], ckhdid->data[5], - ckhdid->data[6], ckhdid->data[7], - ckhdid->data[8], ckhdid->data[9], - ckhdid->data[10], ckhdid->data[11], - ckhdid->data[12], ckhdid->data[13], - ckhdid->data[14], ckhdid->data[15]); -} - -/* - * WUSB Crypto stuff (WUSB1.0[6]) - */ - -extern const char *wusb_et_name(u8); - -/** - * WUSB key index WUSB1.0[7.3.2.4], for usage when setting keys for - * the host or the device. - */ -static inline u8 wusb_key_index(int index, int type, int originator) -{ - return (originator << 6) | (type << 4) | index; -} - -#define WUSB_KEY_INDEX_TYPE_PTK 0 /* for HWA only */ -#define WUSB_KEY_INDEX_TYPE_ASSOC 1 -#define WUSB_KEY_INDEX_TYPE_GTK 2 -#define WUSB_KEY_INDEX_ORIGINATOR_HOST 0 -#define WUSB_KEY_INDEX_ORIGINATOR_DEVICE 1 - -/* A CCM Nonce, defined in WUSB1.0[6.4.1] */ -struct aes_ccm_nonce { - u8 sfn[6]; /* Little Endian */ - u8 tkid[3]; /* LE */ - struct uwb_dev_addr dest_addr; - struct uwb_dev_addr src_addr; -} __attribute__((packed)); - -/* A CCM operation label, defined on WUSB1.0[6.5.x] */ -struct aes_ccm_label { - u8 data[14]; -} __attribute__((packed)); - -/* - * Input to the key derivation sequence defined in - * WUSB1.0[6.5.1]. Rest of the data is in the CCM Nonce passed to the - * PRF function. - */ -struct wusb_keydvt_in { - u8 hnonce[16]; - u8 dnonce[16]; -} __attribute__((packed)); - -/* - * Output from the key derivation sequence defined in - * WUSB1.0[6.5.1]. - */ -struct wusb_keydvt_out { - u8 kck[16]; - u8 ptk[16]; -} __attribute__((packed)); - -/* Pseudo Random Function WUSB1.0[6.5] */ -extern int wusb_crypto_init(void); -extern void wusb_crypto_exit(void); -extern ssize_t wusb_prf(void *out, size_t out_size, - const u8 key[16], const struct aes_ccm_nonce *_n, - const struct aes_ccm_label *a, - const void *b, size_t blen, size_t len); - -static inline int wusb_prf_64(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 64); -} - -static inline int wusb_prf_128(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 128); -} - -static inline int wusb_prf_256(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 256); -} - -/* Key derivation WUSB1.0[6.5.1] */ -static inline int wusb_key_derive(struct wusb_keydvt_out *keydvt_out, - const u8 key[16], - const struct aes_ccm_nonce *n, - const struct wusb_keydvt_in *keydvt_in) -{ - const struct aes_ccm_label a = { .data = "Pair-wise keys" }; - return wusb_prf_256(keydvt_out, sizeof(*keydvt_out), key, n, &a, - keydvt_in, sizeof(*keydvt_in)); -} - -/* - * Out-of-band MIC Generation WUSB1.0[6.5.2] - * - * Compute the MIC over @key, @n and @hs and place it in @mic_out. - * - * @mic_out: Where to place the 8 byte MIC tag - * @key: KCK from the derivation process - * @n: CCM nonce, n->sfn == 0, TKID as established in the - * process. - * @hs: Handshake struct for phase 2 of the 4-way. - * hs->bStatus and hs->bReserved are zero. - * hs->bMessageNumber is 2 (WUSB1.0[7.3.2.5.2] - * hs->dest_addr is the device's USB address padded with 0 - * hs->src_addr is the hosts's UWB device address - * hs->mic is ignored (as we compute that value). - */ -static inline int wusb_oob_mic(u8 mic_out[8], const u8 key[16], - const struct aes_ccm_nonce *n, - const struct usb_handshake *hs) -{ - const struct aes_ccm_label a = { .data = "out-of-bandMIC" }; - return wusb_prf_64(mic_out, 8, key, n, &a, - hs, sizeof(*hs) - sizeof(hs->MIC)); -} - -#endif /* #ifndef __WUSB_H__ */ diff --git a/trunk/include/linux/uwb.h b/trunk/include/linux/uwb.h deleted file mode 100644 index f9ccbd9a2ced..000000000000 --- a/trunk/include/linux/uwb.h +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Ultra Wide Band - * UWB API - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: doc: overview of the API, different parts and pointers - */ - -#ifndef __LINUX__UWB_H__ -#define __LINUX__UWB_H__ - -#include -#include -#include -#include -#include -#include - -struct uwb_dev; -struct uwb_beca_e; -struct uwb_rc; -struct uwb_rsv; -struct uwb_dbg; - -/** - * struct uwb_dev - a UWB Device - * @rc: UWB Radio Controller that discovered the device (kind of its - * parent). - * @bce: a beacon cache entry for this device; or NULL if the device - * is a local radio controller. - * @mac_addr: the EUI-48 address of this device. - * @dev_addr: the current DevAddr used by this device. - * @beacon_slot: the slot number the beacon is using. - * @streams: bitmap of streams allocated to reservations targeted at - * this device. For an RC, this is the streams allocated for - * reservations targeted at DevAddrs. - * - * A UWB device may either by a neighbor or part of a local radio - * controller. - */ -struct uwb_dev { - struct mutex mutex; - struct list_head list_node; - struct device dev; - struct uwb_rc *rc; /* radio controller */ - struct uwb_beca_e *bce; /* Beacon Cache Entry */ - - struct uwb_mac_addr mac_addr; - struct uwb_dev_addr dev_addr; - int beacon_slot; - DECLARE_BITMAP(streams, UWB_NUM_STREAMS); -}; -#define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) - -/** - * UWB HWA/WHCI Radio Control {Command|Event} Block context IDs - * - * RC[CE]Bs have a 'context ID' field that matches the command with - * the event received to confirm it. - * - * Maximum number of context IDs - */ -enum { UWB_RC_CTX_MAX = 256 }; - - -/** Notification chain head for UWB generated events to listeners */ -struct uwb_notifs_chain { - struct list_head list; - struct mutex mutex; -}; - -/** - * struct uwb_mas_bm - a bitmap of all MAS in a superframe - * @bm: a bitmap of length #UWB_NUM_MAS - */ -struct uwb_mas_bm { - DECLARE_BITMAP(bm, UWB_NUM_MAS); -}; - -/** - * uwb_rsv_state - UWB Reservation state. - * - * NONE - reservation is not active (no DRP IE being transmitted). - * - * Owner reservation states: - * - * INITIATED - owner has sent an initial DRP request. - * PENDING - target responded with pending Reason Code. - * MODIFIED - reservation manager is modifying an established - * reservation with a different MAS allocation. - * ESTABLISHED - the reservation has been successfully negotiated. - * - * Target reservation states: - * - * DENIED - request is denied. - * ACCEPTED - request is accepted. - * PENDING - PAL has yet to make a decision to whether to accept or - * deny. - * - * FIXME: further target states TBD. - */ -enum uwb_rsv_state { - UWB_RSV_STATE_NONE, - UWB_RSV_STATE_O_INITIATED, - UWB_RSV_STATE_O_PENDING, - UWB_RSV_STATE_O_MODIFIED, - UWB_RSV_STATE_O_ESTABLISHED, - UWB_RSV_STATE_T_ACCEPTED, - UWB_RSV_STATE_T_DENIED, - UWB_RSV_STATE_T_PENDING, - - UWB_RSV_STATE_LAST, -}; - -enum uwb_rsv_target_type { - UWB_RSV_TARGET_DEV, - UWB_RSV_TARGET_DEVADDR, -}; - -/** - * struct uwb_rsv_target - the target of a reservation. - * - * Reservations unicast and targeted at a single device - * (UWB_RSV_TARGET_DEV); or (e.g., in the case of WUSB) targeted at a - * specific (private) DevAddr (UWB_RSV_TARGET_DEVADDR). - */ -struct uwb_rsv_target { - enum uwb_rsv_target_type type; - union { - struct uwb_dev *dev; - struct uwb_dev_addr devaddr; - }; -}; - -/* - * Number of streams reserved for reservations targeted at DevAddrs. - */ -#define UWB_NUM_GLOBAL_STREAMS 1 - -typedef void (*uwb_rsv_cb_f)(struct uwb_rsv *rsv); - -/** - * struct uwb_rsv - a DRP reservation - * - * Data structure management: - * - * @rc: the radio controller this reservation is for - * (as target or owner) - * @rc_node: a list node for the RC - * @pal_node: a list node for the PAL - * - * Owner and target parameters: - * - * @owner: the UWB device owning this reservation - * @target: the target UWB device - * @type: reservation type - * - * Owner parameters: - * - * @max_mas: maxiumum number of MAS - * @min_mas: minimum number of MAS - * @sparsity: owner selected sparsity - * @is_multicast: true iff multicast - * - * @callback: callback function when the reservation completes - * @pal_priv: private data for the PAL making the reservation - * - * Reservation status: - * - * @status: negotiation status - * @stream: stream index allocated for this reservation - * @mas: reserved MAS - * @drp_ie: the DRP IE - * @ie_valid: true iff the DRP IE matches the reservation parameters - * - * DRP reservations are uniquely identified by the owner, target and - * stream index. However, when using a DevAddr as a target (e.g., for - * a WUSB cluster reservation) the responses may be received from - * devices with different DevAddrs. In this case, reservations are - * uniquely identified by just the stream index. A number of stream - * indexes (UWB_NUM_GLOBAL_STREAMS) are reserved for this. - */ -struct uwb_rsv { - struct uwb_rc *rc; - struct list_head rc_node; - struct list_head pal_node; - - struct uwb_dev *owner; - struct uwb_rsv_target target; - enum uwb_drp_type type; - int max_mas; - int min_mas; - int sparsity; - bool is_multicast; - - uwb_rsv_cb_f callback; - void *pal_priv; - - enum uwb_rsv_state state; - u8 stream; - struct uwb_mas_bm mas; - struct uwb_ie_drp *drp_ie; - bool ie_valid; - struct timer_list timer; - bool expired; -}; - -static const -struct uwb_mas_bm uwb_mas_bm_zero = { .bm = { 0 } }; - -static inline void uwb_mas_bm_copy_le(void *dst, const struct uwb_mas_bm *mas) -{ - bitmap_copy_le(dst, mas->bm, UWB_NUM_MAS); -} - -/** - * struct uwb_drp_avail - a radio controller's view of MAS usage - * @global: MAS unused by neighbors (excluding reservations targetted - * or owned by the local radio controller) or the beaon period - * @local: MAS unused by local established reservations - * @pending: MAS unused by local pending reservations - * @ie: DRP Availability IE to be included in the beacon - * @ie_valid: true iff @ie is valid and does not need to regenerated from - * @global and @local - * - * Each radio controller maintains a view of MAS usage or - * availability. MAS available for a new reservation are determined - * from the intersection of @global, @local, and @pending. - * - * The radio controller must transmit a DRP Availability IE that's the - * intersection of @global and @local. - * - * A set bit indicates the MAS is unused and available. - * - * rc->rsvs_mutex should be held before accessing this data structure. - * - * [ECMA-368] section 17.4.3. - */ -struct uwb_drp_avail { - DECLARE_BITMAP(global, UWB_NUM_MAS); - DECLARE_BITMAP(local, UWB_NUM_MAS); - DECLARE_BITMAP(pending, UWB_NUM_MAS); - struct uwb_ie_drp_avail ie; - bool ie_valid; -}; - - -const char *uwb_rsv_state_str(enum uwb_rsv_state state); -const char *uwb_rsv_type_str(enum uwb_drp_type type); - -struct uwb_rsv *uwb_rsv_create(struct uwb_rc *rc, uwb_rsv_cb_f cb, - void *pal_priv); -void uwb_rsv_destroy(struct uwb_rsv *rsv); - -int uwb_rsv_establish(struct uwb_rsv *rsv); -int uwb_rsv_modify(struct uwb_rsv *rsv, - int max_mas, int min_mas, int sparsity); -void uwb_rsv_terminate(struct uwb_rsv *rsv); - -void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); - -/** - * Radio Control Interface instance - * - * - * Life cycle rules: those of the UWB Device. - * - * @index: an index number for this radio controller, as used in the - * device name. - * @version: version of protocol supported by this device - * @priv: Backend implementation; rw with uwb_dev.dev.sem taken. - * @cmd: Backend implementation to execute commands; rw and call - * only with uwb_dev.dev.sem taken. - * @reset: Hardware reset of radio controller and any PAL controllers. - * @filter: Backend implementation to manipulate data to and from device - * to be compliant to specification assumed by driver (WHCI - * 0.95). - * - * uwb_dev.dev.mutex is used to execute commands and update - * the corresponding structures; can't use a spinlock - * because rc->cmd() can sleep. - * @ies: This is a dynamically allocated array cacheing the - * IEs (settable by the host) that the beacon of this - * radio controller is currently sending. - * - * In reality, we store here the full command we set to - * the radio controller (which is basically a command - * prefix followed by all the IEs the beacon currently - * contains). This way we don't have to realloc and - * memcpy when setting it. - * - * We set this up in uwb_rc_ie_setup(), where we alloc - * this struct, call get_ie() [so we know which IEs are - * currently being sent, if any]. - * - * @ies_capacity:Amount of space (in bytes) allocated in @ies. The - * amount used is given by sizeof(*ies) plus ies->wIELength - * (which is a little endian quantity all the time). - * @ies_mutex: protect the IE cache - * @dbg: information for the debug interface - */ -struct uwb_rc { - struct uwb_dev uwb_dev; - int index; - u16 version; - - struct module *owner; - void *priv; - int (*start)(struct uwb_rc *rc); - void (*stop)(struct uwb_rc *rc); - int (*cmd)(struct uwb_rc *, const struct uwb_rccb *, size_t); - int (*reset)(struct uwb_rc *rc); - int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **, size_t *); - int (*filter_event)(struct uwb_rc *, struct uwb_rceb **, const size_t, - size_t *, size_t *); - - spinlock_t neh_lock; /* protects neh_* and ctx_* */ - struct list_head neh_list; /* Open NE handles */ - unsigned long ctx_bm[UWB_RC_CTX_MAX / 8 / sizeof(unsigned long)]; - u8 ctx_roll; - - int beaconing; /* Beaconing state [channel number] */ - int scanning; - enum uwb_scan_type scan_type:3; - unsigned ready:1; - struct uwb_notifs_chain notifs_chain; - - struct uwb_drp_avail drp_avail; - struct list_head reservations; - struct mutex rsvs_mutex; - struct workqueue_struct *rsv_workq; - struct work_struct rsv_update_work; - - struct mutex ies_mutex; - struct uwb_rc_cmd_set_ie *ies; - size_t ies_capacity; - - spinlock_t pal_lock; - struct list_head pals; - - struct uwb_dbg *dbg; -}; - - -/** - * struct uwb_pal - a UWB PAL - * @name: descriptive name for this PAL (wushc, wlp, etc.). - * @device: a device for the PAL. Used to link the PAL and the radio - * controller in sysfs. - * @new_rsv: called when a peer requests a reservation (may be NULL if - * the PAL cannot accept reservation requests). - * - * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB - * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). - * - * The PALs using a radio controller must register themselves to - * permit the UWB stack to coordinate usage of the radio between the - * various PALs or to allow PALs to response to certain requests from - * peers. - * - * A struct uwb_pal should be embedded in a containing structure - * belonging to the PAL and initialized with uwb_pal_init()). Fields - * should be set appropriately by the PAL before registering the PAL - * with uwb_pal_register(). - */ -struct uwb_pal { - struct list_head node; - const char *name; - struct device *device; - void (*new_rsv)(struct uwb_rsv *rsv); -}; - -void uwb_pal_init(struct uwb_pal *pal); -int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal); -void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal); - -/* - * General public API - * - * This API can be used by UWB device drivers or by those implementing - * UWB Radio Controllers - */ -struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, - const struct uwb_dev_addr *devaddr); -struct uwb_dev *uwb_dev_get_by_rc(struct uwb_dev *, struct uwb_rc *); -static inline void uwb_dev_get(struct uwb_dev *uwb_dev) -{ - get_device(&uwb_dev->dev); -} -static inline void uwb_dev_put(struct uwb_dev *uwb_dev) -{ - put_device(&uwb_dev->dev); -} -struct uwb_dev *uwb_dev_try_get(struct uwb_rc *rc, struct uwb_dev *uwb_dev); - -/** - * Callback function for 'uwb_{dev,rc}_foreach()'. - * - * @dev: Linux device instance - * 'uwb_dev = container_of(dev, struct uwb_dev, dev)' - * @priv: Data passed by the caller to 'uwb_{dev,rc}_foreach()'. - * - * @returns: 0 to continue the iterations, any other val to stop - * iterating and return the value to the caller of - * _foreach(). - */ -typedef int (*uwb_dev_for_each_f)(struct device *dev, void *priv); -int uwb_dev_for_each(struct uwb_rc *rc, uwb_dev_for_each_f func, void *priv); - -struct uwb_rc *uwb_rc_alloc(void); -struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *); -struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *); -void uwb_rc_put(struct uwb_rc *rc); - -typedef void (*uwb_rc_cmd_cb_f)(struct uwb_rc *rc, void *arg, - struct uwb_rceb *reply, ssize_t reply_size); - -int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - uwb_rc_cmd_cb_f cb, void *arg); -ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - struct uwb_rceb *reply, size_t reply_size); -ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - struct uwb_rceb **preply); -ssize_t uwb_rc_get_ie(struct uwb_rc *, struct uwb_rc_evt_get_ie **); -int uwb_bg_joined(struct uwb_rc *rc); - -size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); - -int uwb_rc_dev_addr_set(struct uwb_rc *, const struct uwb_dev_addr *); -int uwb_rc_dev_addr_get(struct uwb_rc *, struct uwb_dev_addr *); -int uwb_rc_mac_addr_set(struct uwb_rc *, const struct uwb_mac_addr *); -int uwb_rc_mac_addr_get(struct uwb_rc *, struct uwb_mac_addr *); -int __uwb_mac_addr_assigned_check(struct device *, void *); -int __uwb_dev_addr_assigned_check(struct device *, void *); - -/* Print in @buf a pretty repr of @addr */ -static inline size_t uwb_dev_addr_print(char *buf, size_t buf_size, - const struct uwb_dev_addr *addr) -{ - return __uwb_addr_print(buf, buf_size, addr->data, 0); -} - -/* Print in @buf a pretty repr of @addr */ -static inline size_t uwb_mac_addr_print(char *buf, size_t buf_size, - const struct uwb_mac_addr *addr) -{ - return __uwb_addr_print(buf, buf_size, addr->data, 1); -} - -/* @returns 0 if device addresses @addr2 and @addr1 are equal */ -static inline int uwb_dev_addr_cmp(const struct uwb_dev_addr *addr1, - const struct uwb_dev_addr *addr2) -{ - return memcmp(addr1, addr2, sizeof(*addr1)); -} - -/* @returns 0 if MAC addresses @addr2 and @addr1 are equal */ -static inline int uwb_mac_addr_cmp(const struct uwb_mac_addr *addr1, - const struct uwb_mac_addr *addr2) -{ - return memcmp(addr1, addr2, sizeof(*addr1)); -} - -/* @returns !0 if a MAC @addr is a broadcast address */ -static inline int uwb_mac_addr_bcast(const struct uwb_mac_addr *addr) -{ - struct uwb_mac_addr bcast = { - .data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } - }; - return !uwb_mac_addr_cmp(addr, &bcast); -} - -/* @returns !0 if a MAC @addr is all zeroes*/ -static inline int uwb_mac_addr_unset(const struct uwb_mac_addr *addr) -{ - struct uwb_mac_addr unset = { - .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }; - return !uwb_mac_addr_cmp(addr, &unset); -} - -/* @returns !0 if the address is in use. */ -static inline unsigned __uwb_dev_addr_assigned(struct uwb_rc *rc, - struct uwb_dev_addr *addr) -{ - return uwb_dev_for_each(rc, __uwb_dev_addr_assigned_check, addr); -} - -/* - * UWB Radio Controller API - * - * This API is used (in addition to the general API) to implement UWB - * Radio Controllers. - */ -void uwb_rc_init(struct uwb_rc *); -int uwb_rc_add(struct uwb_rc *, struct device *dev, void *rc_priv); -void uwb_rc_rm(struct uwb_rc *); -void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); -void uwb_rc_neh_error(struct uwb_rc *, int); -void uwb_rc_reset_all(struct uwb_rc *rc); - -/** - * uwb_rsv_is_owner - is the owner of this reservation the RC? - * @rsv: the reservation - */ -static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) -{ - return rsv->owner == &rsv->rc->uwb_dev; -} - -/** - * Events generated by UWB that can be passed to any listeners - * - * Higher layers can register callback functions with the radio - * controller using uwb_notifs_register(). The radio controller - * maintains a list of all registered handlers and will notify all - * nodes when an event occurs. - */ -enum uwb_notifs { - UWB_NOTIF_BG_JOIN = 0, /* radio controller joined a beacon group */ - UWB_NOTIF_BG_LEAVE = 1, /* radio controller left a beacon group */ - UWB_NOTIF_ONAIR, - UWB_NOTIF_OFFAIR, -}; - -/* Callback function registered with UWB */ -struct uwb_notifs_handler { - struct list_head list_node; - void (*cb)(void *, struct uwb_dev *, enum uwb_notifs); - void *data; -}; - -int uwb_notifs_register(struct uwb_rc *, struct uwb_notifs_handler *); -int uwb_notifs_deregister(struct uwb_rc *, struct uwb_notifs_handler *); - - -/** - * UWB radio controller Event Size Entry (for creating entry tables) - * - * WUSB and WHCI define events and notifications, and they might have - * fixed or variable size. - * - * Each event/notification has a size which is not necessarily known - * in advance based on the event code. As well, vendor specific - * events/notifications will have a size impossible to determine - * unless we know about the device's specific details. - * - * It was way too smart of the spec writers not to think that it would - * be impossible for a generic driver to skip over vendor specific - * events/notifications if there are no LENGTH fields in the HEADER of - * each message...the transaction size cannot be counted on as the - * spec does not forbid to pack more than one event in a single - * transaction. - * - * Thus, we guess sizes with tables (or for events, when you know the - * size ahead of time you can use uwb_rc_neh_extra_size*()). We - * register tables with the known events and their sizes, and then we - * traverse those tables. For those with variable length, we provide a - * way to lookup the size inside the event/notification's - * payload. This allows device-specific event size tables to be - * registered. - * - * @size: Size of the payload - * - * @offset: if != 0, at offset @offset-1 starts a field with a length - * that has to be added to @size. The format of the field is - * given by @type. - * - * @type: Type and length of the offset field. Most common is LE 16 - * bits (that's why that is zero); others are there mostly to - * cover for bugs and weirdos. - */ -struct uwb_est_entry { - size_t size; - unsigned offset; - enum { UWB_EST_16 = 0, UWB_EST_8 = 1 } type; -}; - -int uwb_est_register(u8 type, u8 code_high, u16 vendor, u16 product, - const struct uwb_est_entry *, size_t entries); -int uwb_est_unregister(u8 type, u8 code_high, u16 vendor, u16 product, - const struct uwb_est_entry *, size_t entries); -ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, - size_t len); - -/* -- Misc */ - -enum { - EDC_MAX_ERRORS = 10, - EDC_ERROR_TIMEFRAME = HZ, -}; - -/* error density counter */ -struct edc { - unsigned long timestart; - u16 errorcount; -}; - -static inline -void edc_init(struct edc *edc) -{ - edc->timestart = jiffies; -} - -/* Called when an error occured. - * This is way to determine if the number of acceptable errors per time - * period has been exceeded. It is not accurate as there are cases in which - * this scheme will not work, for example if there are periodic occurences - * of errors that straddle updates to the start time. This scheme is - * sufficient for our usage. - * - * @returns 1 if maximum acceptable errors per timeframe has been exceeded. - */ -static inline int edc_inc(struct edc *err_hist, u16 max_err, u16 timeframe) -{ - unsigned long now; - - now = jiffies; - if (now - err_hist->timestart > timeframe) { - err_hist->errorcount = 1; - err_hist->timestart = now; - } else if (++err_hist->errorcount > max_err) { - err_hist->errorcount = 0; - err_hist->timestart = now; - return 1; - } - return 0; -} - - -/* Information Element handling */ - -/* For representing the state of writing to a buffer when iterating */ -struct uwb_buf_ctx { - char *buf; - size_t bytes, size; -}; - -typedef int (*uwb_ie_f)(struct uwb_dev *, const struct uwb_ie_hdr *, - size_t, void *); -struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); -ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, - const void *buf, size_t size); -int uwb_ie_dump_hex(struct uwb_dev *, const struct uwb_ie_hdr *, - size_t, void *); -int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); -struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); - - -/* - * Transmission statistics - * - * UWB uses LQI and RSSI (one byte values) for reporting radio signal - * strength and line quality indication. We do quick and dirty - * averages of those. They are signed values, btw. - * - * For 8 bit quantities, we keep the min, the max, an accumulator - * (@sigma) and a # of samples. When @samples gets to 255, we compute - * the average (@sigma / @samples), place it in @sigma and reset - * @samples to 1 (so we use it as the first sample). - * - * Now, statistically speaking, probably I am kicking the kidneys of - * some books I have in my shelves collecting dust, but I just want to - * get an approx, not the Nobel. - * - * LOCKING: there is no locking per se, but we try to keep a lockless - * schema. Only _add_samples() modifies the values--as long as you - * have other locking on top that makes sure that no two calls of - * _add_sample() happen at the same time, then we are fine. Now, for - * resetting the values we just set @samples to 0 and that makes the - * next _add_sample() to start with defaults. Reading the values in - * _show() currently can race, so you need to make sure the calls are - * under the same lock that protects calls to _add_sample(). FIXME: - * currently unlocked (It is not ultraprecise but does the trick. Bite - * me). - */ -struct stats { - s8 min, max; - s16 sigma; - atomic_t samples; -}; - -static inline -void stats_init(struct stats *stats) -{ - atomic_set(&stats->samples, 0); - wmb(); -} - -static inline -void stats_add_sample(struct stats *stats, s8 sample) -{ - s8 min, max; - s16 sigma; - unsigned samples = atomic_read(&stats->samples); - if (samples == 0) { /* it was zero before, so we initialize */ - min = 127; - max = -128; - sigma = 0; - } else { - min = stats->min; - max = stats->max; - sigma = stats->sigma; - } - - if (sample < min) /* compute new values */ - min = sample; - else if (sample > max) - max = sample; - sigma += sample; - - stats->min = min; /* commit */ - stats->max = max; - stats->sigma = sigma; - if (atomic_add_return(1, &stats->samples) > 255) { - /* wrapped around! reset */ - stats->sigma = sigma / 256; - atomic_set(&stats->samples, 1); - } -} - -static inline ssize_t stats_show(struct stats *stats, char *buf) -{ - int min, max, avg; - int samples = atomic_read(&stats->samples); - if (samples == 0) - min = max = avg = 0; - else { - min = stats->min; - max = stats->max; - avg = stats->sigma / samples; - } - return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", min, max, avg); -} - -static inline ssize_t stats_store(struct stats *stats, const char *buf, - size_t size) -{ - stats_init(stats); - return size; -} - -#endif /* #ifndef __LINUX__UWB_H__ */ diff --git a/trunk/include/linux/uwb/debug-cmd.h b/trunk/include/linux/uwb/debug-cmd.h deleted file mode 100644 index 1141f41bab5c..000000000000 --- a/trunk/include/linux/uwb/debug-cmd.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Ultra Wide Band - * Debug interface commands - * - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __LINUX__UWB__DEBUG_CMD_H__ -#define __LINUX__UWB__DEBUG_CMD_H__ - -#include - -/* - * Debug interface commands - * - * UWB_DBG_CMD_RSV_ESTABLISH: Establish a new unicast reservation. - * - * UWB_DBG_CMD_RSV_TERMINATE: Terminate the Nth reservation. - */ - -enum uwb_dbg_cmd_type { - UWB_DBG_CMD_RSV_ESTABLISH = 1, - UWB_DBG_CMD_RSV_TERMINATE = 2, -}; - -struct uwb_dbg_cmd_rsv_establish { - __u8 target[6]; - __u8 type; - __u16 max_mas; - __u16 min_mas; - __u8 sparsity; -}; - -struct uwb_dbg_cmd_rsv_terminate { - int index; -}; - -struct uwb_dbg_cmd { - __u32 type; - union { - struct uwb_dbg_cmd_rsv_establish rsv_establish; - struct uwb_dbg_cmd_rsv_terminate rsv_terminate; - }; -}; - -#endif /* #ifndef __LINUX__UWB__DEBUG_CMD_H__ */ diff --git a/trunk/include/linux/uwb/debug.h b/trunk/include/linux/uwb/debug.h deleted file mode 100644 index a86a73fe303f..000000000000 --- a/trunk/include/linux/uwb/debug.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Ultra Wide Band - * Debug Support - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: doc - * Invoke like: - * - * #define D_LOCAL 4 - * #include - * - * At the end of your include files. - */ -#include - -struct device; -extern void dump_bytes(struct device *dev, const void *_buf, size_t rsize); - -/* Master debug switch; !0 enables, 0 disables */ -#define D_MASTER (!0) - -/* Local (per-file) debug switch; #define before #including */ -#ifndef D_LOCAL -#define D_LOCAL 0 -#endif - -#undef __d_printf -#undef d_fnstart -#undef d_fnend -#undef d_printf -#undef d_dump - -#define __d_printf(l, _tag, _dev, f, a...) \ -do { \ - struct device *__dev = (_dev); \ - if (D_MASTER && D_LOCAL >= (l)) { \ - char __head[64] = ""; \ - if (_dev != NULL) { \ - if ((unsigned long)__dev < 4096) \ - printk(KERN_ERR "E: Corrupt dev %p\n", \ - __dev); \ - else \ - snprintf(__head, sizeof(__head), \ - "%s %s: ", \ - dev_driver_string(__dev), \ - __dev->bus_id); \ - } \ - printk(KERN_ERR "%s%s" _tag ": " f, __head, \ - __func__, ## a); \ - } \ -} while (0 && _dev) - -#define d_fnstart(l, _dev, f, a...) \ - __d_printf(l, " FNSTART", _dev, f, ## a) -#define d_fnend(l, _dev, f, a...) \ - __d_printf(l, " FNEND", _dev, f, ## a) -#define d_printf(l, _dev, f, a...) \ - __d_printf(l, "", _dev, f, ## a) -#define d_dump(l, _dev, ptr, size) \ -do { \ - struct device *__dev = _dev; \ - if (D_MASTER && D_LOCAL >= (l)) \ - dump_bytes(__dev, ptr, size); \ -} while (0 && _dev) -#define d_test(l) (D_MASTER && D_LOCAL >= (l)) diff --git a/trunk/include/linux/uwb/spec.h b/trunk/include/linux/uwb/spec.h deleted file mode 100644 index 198c15f8e251..000000000000 --- a/trunk/include/linux/uwb/spec.h +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Ultra Wide Band - * UWB Standard definitions - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * All these definitions are based on the ECMA-368 standard. - * - * Note all definitions are Little Endian in the wire, and we will - * convert them to host order before operating on the bitfields (that - * yes, we use extensively). - */ - -#ifndef __LINUX__UWB_SPEC_H__ -#define __LINUX__UWB_SPEC_H__ - -#include -#include - -#define i1480_FW 0x00000303 -/* #define i1480_FW 0x00000302 */ - -/** - * Number of Medium Access Slots in a superframe. - * - * UWB divides time in SuperFrames, each one divided in 256 pieces, or - * Medium Access Slots. See MBOA MAC[5.4.5] for details. The MAS is the - * basic bandwidth allocation unit in UWB. - */ -enum { UWB_NUM_MAS = 256 }; - -/** - * Number of Zones in superframe. - * - * UWB divides the superframe into zones with numbering starting from BPST. - * See MBOA MAC[16.8.6] - */ -enum { UWB_NUM_ZONES = 16 }; - -/* - * Number of MAS in a zone. - */ -#define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) - -/* - * Number of streams per DRP reservation between a pair of devices. - * - * [ECMA-368] section 16.8.6. - */ -enum { UWB_NUM_STREAMS = 8 }; - -/* - * mMasLength - * - * The length of a MAS in microseconds. - * - * [ECMA-368] section 17.16. - */ -enum { UWB_MAS_LENGTH_US = 256 }; - -/* - * mBeaconSlotLength - * - * The length of the beacon slot in microseconds. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_BEACON_SLOT_LENGTH_US = 85 }; - -/* - * mMaxLostBeacons - * - * The number beacons missing in consecutive superframes before a - * device can be considered as unreachable. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_MAX_LOST_BEACONS = 3 }; - -/* - * Length of a superframe in microseconds. - */ -#define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) - -/** - * UWB MAC address - * - * It is *imperative* that this struct is exactly 6 packed bytes (as - * it is also used to define headers sent down and up the wire/radio). - */ -struct uwb_mac_addr { - u8 data[6]; -} __attribute__((packed)); - - -/** - * UWB device address - * - * It is *imperative* that this struct is exactly 6 packed bytes (as - * it is also used to define headers sent down and up the wire/radio). - */ -struct uwb_dev_addr { - u8 data[2]; -} __attribute__((packed)); - - -/** - * Types of UWB addresses - * - * Order matters (by size). - */ -enum uwb_addr_type { - UWB_ADDR_DEV = 0, - UWB_ADDR_MAC = 1, -}; - - -/** Size of a char buffer for printing a MAC/device address */ -enum { UWB_ADDR_STRSIZE = 32 }; - - -/** UWB WiMedia protocol IDs. */ -enum uwb_prid { - UWB_PRID_WLP_RESERVED = 0x0000, - UWB_PRID_WLP = 0x0001, - UWB_PRID_WUSB_BOT = 0x0010, - UWB_PRID_WUSB = 0x0010, - UWB_PRID_WUSB_TOP = 0x001F, -}; - - -/** PHY Rate (MBOA MAC[7.8.12, Table 61]) */ -enum uwb_phy_rate { - UWB_PHY_RATE_53 = 0, - UWB_PHY_RATE_80, - UWB_PHY_RATE_106, - UWB_PHY_RATE_160, - UWB_PHY_RATE_200, - UWB_PHY_RATE_320, - UWB_PHY_RATE_400, - UWB_PHY_RATE_480, - UWB_PHY_RATE_INVALID -}; - - -/** - * Different ways to scan (MBOA MAC[6.2.2, Table 8], WUSB[Table 8-78]) - */ -enum uwb_scan_type { - UWB_SCAN_ONLY = 0, - UWB_SCAN_OUTSIDE_BP, - UWB_SCAN_WHILE_INACTIVE, - UWB_SCAN_DISABLED, - UWB_SCAN_ONLY_STARTTIME, - UWB_SCAN_TOP -}; - - -/** ACK Policy types (MBOA MAC[7.2.1.3]) */ -enum uwb_ack_pol { - UWB_ACK_NO = 0, - UWB_ACK_INM = 1, - UWB_ACK_B = 2, - UWB_ACK_B_REQ = 3, -}; - - -/** DRP reservation types ([ECMA-368 table 106) */ -enum uwb_drp_type { - UWB_DRP_TYPE_ALIEN_BP = 0, - UWB_DRP_TYPE_HARD, - UWB_DRP_TYPE_SOFT, - UWB_DRP_TYPE_PRIVATE, - UWB_DRP_TYPE_PCA, -}; - - -/** DRP Reason Codes ([ECMA-368] table 107) */ -enum uwb_drp_reason { - UWB_DRP_REASON_ACCEPTED = 0, - UWB_DRP_REASON_CONFLICT, - UWB_DRP_REASON_PENDING, - UWB_DRP_REASON_DENIED, - UWB_DRP_REASON_MODIFIED, -}; - -/** - * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) - */ -enum uwb_drp_notif_reason { - UWB_DRP_NOTIF_DRP_IE_RCVD = 0, - UWB_DRP_NOTIF_CONFLICT, - UWB_DRP_NOTIF_TERMINATE, -}; - - -/** Allocation of MAS slots in a DRP request MBOA MAC[7.8.7] */ -struct uwb_drp_alloc { - __le16 zone_bm; - __le16 mas_bm; -} __attribute__((packed)); - - -/** General MAC Header format (ECMA-368[16.2]) */ -struct uwb_mac_frame_hdr { - __le16 Frame_Control; - struct uwb_dev_addr DestAddr; - struct uwb_dev_addr SrcAddr; - __le16 Sequence_Control; - __le16 Access_Information; -} __attribute__((packed)); - - -/** - * uwb_beacon_frame - a beacon frame including MAC headers - * - * [ECMA] section 16.3. - */ -struct uwb_beacon_frame { - struct uwb_mac_frame_hdr hdr; - struct uwb_mac_addr Device_Identifier; /* may be a NULL EUI-48 */ - u8 Beacon_Slot_Number; - u8 Device_Control; - u8 IEData[]; -} __attribute__((packed)); - - -/** Information Element codes (MBOA MAC[T54]) */ -enum uwb_ie { - UWB_PCA_AVAILABILITY = 2, - UWB_IE_DRP_AVAILABILITY = 8, - UWB_IE_DRP = 9, - UWB_BP_SWITCH_IE = 11, - UWB_MAC_CAPABILITIES_IE = 12, - UWB_PHY_CAPABILITIES_IE = 13, - UWB_APP_SPEC_PROBE_IE = 15, - UWB_IDENTIFICATION_IE = 19, - UWB_MASTER_KEY_ID_IE = 20, - UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ - UWB_APP_SPEC_IE = 255, -}; - - -/** - * Header common to all Information Elements (IEs) - */ -struct uwb_ie_hdr { - u8 element_id; /* enum uwb_ie */ - u8 length; -} __attribute__((packed)); - - -/** Dynamic Reservation Protocol IE (MBOA MAC[7.8.6]) */ -struct uwb_ie_drp { - struct uwb_ie_hdr hdr; - __le16 drp_control; - struct uwb_dev_addr dev_addr; - struct uwb_drp_alloc allocs[]; -} __attribute__((packed)); - -static inline int uwb_ie_drp_type(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 0) & 0x7; -} - -static inline int uwb_ie_drp_stream_index(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 3) & 0x7; -} - -static inline int uwb_ie_drp_reason_code(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 6) & 0x7; -} - -static inline int uwb_ie_drp_status(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 9) & 0x1; -} - -static inline int uwb_ie_drp_owner(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 10) & 0x1; -} - -static inline int uwb_ie_drp_tiebreaker(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 11) & 0x1; -} - -static inline int uwb_ie_drp_unsafe(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 12) & 0x1; -} - -static inline void uwb_ie_drp_set_type(struct uwb_ie_drp *ie, enum uwb_drp_type type) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x7 << 0)) | (type << 0); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_stream_index(struct uwb_ie_drp *ie, int stream_index) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x7 << 3)) | (stream_index << 3); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_reason_code(struct uwb_ie_drp *ie, - enum uwb_drp_reason reason_code) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (ie->drp_control & ~(0x7 << 6)) | (reason_code << 6); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_status(struct uwb_ie_drp *ie, int status) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 9)) | (status << 9); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_owner(struct uwb_ie_drp *ie, int owner) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 10)) | (owner << 10); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_tiebreaker(struct uwb_ie_drp *ie, int tiebreaker) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 11)) | (tiebreaker << 11); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_unsafe(struct uwb_ie_drp *ie, int unsafe) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 12)) | (unsafe << 12); - ie->drp_control = cpu_to_le16(drp_control); -} - -/** Dynamic Reservation Protocol IE (MBOA MAC[7.8.7]) */ -struct uwb_ie_drp_avail { - struct uwb_ie_hdr hdr; - DECLARE_BITMAP(bmp, UWB_NUM_MAS); -} __attribute__((packed)); - -/** - * The Vendor ID is set to an OUI that indicates the vendor of the device. - * ECMA-368 [16.8.10] - */ -struct uwb_vendor_id { - u8 data[3]; -} __attribute__((packed)); - -/** - * The device type ID - * FIXME: clarify what this means - * ECMA-368 [16.8.10] - */ -struct uwb_device_type_id { - u8 data[3]; -} __attribute__((packed)); - - -/** - * UWB device information types - * ECMA-368 [16.8.10] - */ -enum uwb_dev_info_type { - UWB_DEV_INFO_VENDOR_ID = 0, - UWB_DEV_INFO_VENDOR_TYPE, - UWB_DEV_INFO_NAME, -}; - -/** - * UWB device information found in Identification IE - * ECMA-368 [16.8.10] - */ -struct uwb_dev_info { - u8 type; /* enum uwb_dev_info_type */ - u8 length; - u8 data[]; -} __attribute__((packed)); - -/** - * UWB Identification IE - * ECMA-368 [16.8.10] - */ -struct uwb_identification_ie { - struct uwb_ie_hdr hdr; - struct uwb_dev_info info[]; -} __attribute__((packed)); - -/* - * UWB Radio Controller - * - * These definitions are common to the Radio Control layers as - * exported by the WUSB1.0 HWA and WHCI interfaces. - */ - -/** Radio Control Command Block (WUSB1.0[Table 8-65] and WHCI 0.95) */ -struct uwb_rccb { - u8 bCommandType; /* enum hwa_cet */ - __le16 wCommand; /* Command code */ - u8 bCommandContext; /* Context ID */ -} __attribute__((packed)); - - -/** Radio Control Event Block (WUSB[table 8-66], WHCI 0.95) */ -struct uwb_rceb { - u8 bEventType; /* enum hwa_cet */ - __le16 wEvent; /* Event code */ - u8 bEventContext; /* Context ID */ -} __attribute__((packed)); - - -enum { - UWB_RC_CET_GENERAL = 0, /* General Command/Event type */ - UWB_RC_CET_EX_TYPE_1 = 1, /* Extended Type 1 Command/Event type */ -}; - -/* Commands to the radio controller */ -enum uwb_rc_cmd { - UWB_RC_CMD_CHANNEL_CHANGE = 16, - UWB_RC_CMD_DEV_ADDR_MGMT = 17, /* Device Address Management */ - UWB_RC_CMD_GET_IE = 18, /* GET Information Elements */ - UWB_RC_CMD_RESET = 19, - UWB_RC_CMD_SCAN = 20, /* Scan management */ - UWB_RC_CMD_SET_BEACON_FILTER = 21, - UWB_RC_CMD_SET_DRP_IE = 22, /* Dynamic Reservation Protocol IEs */ - UWB_RC_CMD_SET_IE = 23, /* Information Element management */ - UWB_RC_CMD_SET_NOTIFICATION_FILTER = 24, - UWB_RC_CMD_SET_TX_POWER = 25, - UWB_RC_CMD_SLEEP = 26, - UWB_RC_CMD_START_BEACON = 27, - UWB_RC_CMD_STOP_BEACON = 28, - UWB_RC_CMD_BP_MERGE = 29, - UWB_RC_CMD_SEND_COMMAND_FRAME = 30, - UWB_RC_CMD_SET_ASIE_NOTIF = 31, -}; - -/* Notifications from the radio controller */ -enum uwb_rc_evt { - UWB_RC_EVT_IE_RCV = 0, - UWB_RC_EVT_BEACON = 1, - UWB_RC_EVT_BEACON_SIZE = 2, - UWB_RC_EVT_BPOIE_CHANGE = 3, - UWB_RC_EVT_BP_SLOT_CHANGE = 4, - UWB_RC_EVT_BP_SWITCH_IE_RCV = 5, - UWB_RC_EVT_DEV_ADDR_CONFLICT = 6, - UWB_RC_EVT_DRP_AVAIL = 7, - UWB_RC_EVT_DRP = 8, - UWB_RC_EVT_BP_SWITCH_STATUS = 9, - UWB_RC_EVT_CMD_FRAME_RCV = 10, - UWB_RC_EVT_CHANNEL_CHANGE_IE_RCV = 11, - /* Events (command responses) use the same code as the command */ - UWB_RC_EVT_UNKNOWN_CMD_RCV = 65535, -}; - -enum uwb_rc_extended_type_1_cmd { - UWB_RC_SET_DAA_ENERGY_MASK = 32, - UWB_RC_SET_NOTIFICATION_FILTER_EX = 33, -}; - -enum uwb_rc_extended_type_1_evt { - UWB_RC_DAA_ENERGY_DETECTED = 0, -}; - -/* Radio Control Result Code. [WHCI] table 3-3. */ -enum { - UWB_RC_RES_SUCCESS = 0, - UWB_RC_RES_FAIL, - UWB_RC_RES_FAIL_HARDWARE, - UWB_RC_RES_FAIL_NO_SLOTS, - UWB_RC_RES_FAIL_BEACON_TOO_LARGE, - UWB_RC_RES_FAIL_INVALID_PARAMETER, - UWB_RC_RES_FAIL_UNSUPPORTED_PWR_LEVEL, - UWB_RC_RES_FAIL_INVALID_IE_DATA, - UWB_RC_RES_FAIL_BEACON_SIZE_EXCEEDED, - UWB_RC_RES_FAIL_CANCELLED, - UWB_RC_RES_FAIL_INVALID_STATE, - UWB_RC_RES_FAIL_INVALID_SIZE, - UWB_RC_RES_FAIL_ACK_NOT_RECEIVED, - UWB_RC_RES_FAIL_NO_MORE_ASIE_NOTIF, - UWB_RC_RES_FAIL_TIME_OUT = 255, -}; - -/* Confirm event. [WHCI] section 3.1.3.1 etc. */ -struct uwb_rc_evt_confirm { - struct uwb_rceb rceb; - u8 bResultCode; -} __attribute__((packed)); - -/* Device Address Management event. [WHCI] section 3.1.3.2. */ -struct uwb_rc_evt_dev_addr_mgmt { - struct uwb_rceb rceb; - u8 baAddr[6]; - u8 bResultCode; -} __attribute__((packed)); - - -/* Get IE Event. [WHCI] section 3.1.3.3. */ -struct uwb_rc_evt_get_ie { - struct uwb_rceb rceb; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Set DRP IE Event. [WHCI] section 3.1.3.7. */ -struct uwb_rc_evt_set_drp_ie { - struct uwb_rceb rceb; - __le16 wRemainingSpace; - u8 bResultCode; -} __attribute__((packed)); - -/* Set IE Event. [WHCI] section 3.1.3.8. */ -struct uwb_rc_evt_set_ie { - struct uwb_rceb rceb; - __le16 RemainingSpace; - u8 bResultCode; -} __attribute__((packed)); - -/* Scan command. [WHCI] 3.1.3.5. */ -struct uwb_rc_cmd_scan { - struct uwb_rccb rccb; - u8 bChannelNumber; - u8 bScanState; - __le16 wStartTime; -} __attribute__((packed)); - -/* Set DRP IE command. [WHCI] section 3.1.3.7. */ -struct uwb_rc_cmd_set_drp_ie { - struct uwb_rccb rccb; - __le16 wIELength; - struct uwb_ie_drp IEData[]; -} __attribute__((packed)); - -/* Set IE command. [WHCI] section 3.1.3.8. */ -struct uwb_rc_cmd_set_ie { - struct uwb_rccb rccb; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Set DAA Energy Mask event. [WHCI 0.96] section 3.1.3.17. */ -struct uwb_rc_evt_set_daa_energy_mask { - struct uwb_rceb rceb; - __le16 wLength; - u8 result; -} __attribute__((packed)); - -/* Set Notification Filter Extended event. [WHCI 0.96] section 3.1.3.18. */ -struct uwb_rc_evt_set_notification_filter_ex { - struct uwb_rceb rceb; - __le16 wLength; - u8 result; -} __attribute__((packed)); - -/* IE Received notification. [WHCI] section 3.1.4.1. */ -struct uwb_rc_evt_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr SrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Type of the received beacon. [WHCI] section 3.1.4.2. */ -enum uwb_rc_beacon_type { - UWB_RC_BEACON_TYPE_SCAN = 0, - UWB_RC_BEACON_TYPE_NEIGHBOR, - UWB_RC_BEACON_TYPE_OL_ALIEN, - UWB_RC_BEACON_TYPE_NOL_ALIEN, -}; - -/* Beacon received notification. [WHCI] 3.1.4.2. */ -struct uwb_rc_evt_beacon { - struct uwb_rceb rceb; - u8 bChannelNumber; - u8 bBeaconType; - __le16 wBPSTOffset; - u8 bLQI; - u8 bRSSI; - __le16 wBeaconInfoLength; - u8 BeaconInfo[]; -} __attribute__((packed)); - - -/* Beacon Size Change notification. [WHCI] section 3.1.4.3 */ -struct uwb_rc_evt_beacon_size { - struct uwb_rceb rceb; - __le16 wNewBeaconSize; -} __attribute__((packed)); - - -/* BPOIE Change notification. [WHCI] section 3.1.4.4. */ -struct uwb_rc_evt_bpoie_change { - struct uwb_rceb rceb; - __le16 wBPOIELength; - u8 BPOIE[]; -} __attribute__((packed)); - - -/* Beacon Slot Change notification. [WHCI] section 3.1.4.5. */ -struct uwb_rc_evt_bp_slot_change { - struct uwb_rceb rceb; - u8 slot_info; -} __attribute__((packed)); - -static inline int uwb_rc_evt_bp_slot_change_slot_num( - const struct uwb_rc_evt_bp_slot_change *evt) -{ - return evt->slot_info & 0x7f; -} - -static inline int uwb_rc_evt_bp_slot_change_no_slot( - const struct uwb_rc_evt_bp_slot_change *evt) -{ - return (evt->slot_info & 0x80) >> 7; -} - -/* BP Switch IE Received notification. [WHCI] section 3.1.4.6. */ -struct uwb_rc_evt_bp_switch_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr wSrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* DevAddr Conflict notification. [WHCI] section 3.1.4.7. */ -struct uwb_rc_evt_dev_addr_conflict { - struct uwb_rceb rceb; -} __attribute__((packed)); - -/* DRP notification. [WHCI] section 3.1.4.9. */ -struct uwb_rc_evt_drp { - struct uwb_rceb rceb; - struct uwb_dev_addr src_addr; - u8 reason; - u8 beacon_slot_number; - __le16 ie_length; - u8 ie_data[]; -} __attribute__((packed)); - -static inline enum uwb_drp_notif_reason uwb_rc_evt_drp_reason(struct uwb_rc_evt_drp *evt) -{ - return evt->reason & 0x0f; -} - - -/* DRP Availability Change notification. [WHCI] section 3.1.4.8. */ -struct uwb_rc_evt_drp_avail { - struct uwb_rceb rceb; - DECLARE_BITMAP(bmp, UWB_NUM_MAS); -} __attribute__((packed)); - -/* BP switch status notification. [WHCI] section 3.1.4.10. */ -struct uwb_rc_evt_bp_switch_status { - struct uwb_rceb rceb; - u8 status; - u8 slot_offset; - __le16 bpst_offset; - u8 move_countdown; -} __attribute__((packed)); - -/* Command Frame Received notification. [WHCI] section 3.1.4.11. */ -struct uwb_rc_evt_cmd_frame_rcv { - struct uwb_rceb rceb; - __le16 receive_time; - struct uwb_dev_addr wSrcAddr; - struct uwb_dev_addr wDstAddr; - __le16 control; - __le16 reserved; - __le16 dataLength; - u8 data[]; -} __attribute__((packed)); - -/* Channel Change IE Received notification. [WHCI] section 3.1.4.12. */ -struct uwb_rc_evt_channel_change_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr wSrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* DAA Energy Detected notification. [WHCI 0.96] section 3.1.4.14. */ -struct uwb_rc_evt_daa_energy_detected { - struct uwb_rceb rceb; - __le16 wLength; - u8 bandID; - u8 reserved; - u8 toneBmp[16]; -} __attribute__((packed)); - - -/** - * Radio Control Interface Class Descriptor - * - * WUSB 1.0 [8.6.1.2] - */ -struct uwb_rc_control_intf_class_desc { - u8 bLength; - u8 bDescriptorType; - __le16 bcdRCIVersion; -} __attribute__((packed)); - -#endif /* #ifndef __LINUX__UWB_SPEC_H__ */ diff --git a/trunk/include/linux/uwb/umc.h b/trunk/include/linux/uwb/umc.h deleted file mode 100644 index 36a39e34f8d7..000000000000 --- a/trunk/include/linux/uwb/umc.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * UWB Multi-interface Controller support. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * This file is released under the GPLv2 - * - * UMC (UWB Multi-interface Controller) capabilities (e.g., radio - * controller, host controller) are presented as devices on the "umc" - * bus. - * - * The radio controller is not strictly a UMC capability but it's - * useful to present it as such. - * - * References: - * - * [WHCI] Wireless Host Controller Interface Specification for - * Certified Wireless Universal Serial Bus, revision 0.95. - * - * How this works is kind of convoluted but simple. The whci.ko driver - * loads when WHCI devices are detected. These WHCI devices expose - * many devices in the same PCI function (they couldn't have reused - * functions, no), so for each PCI function that exposes these many - * devices, whci ceates a umc_dev [whci_probe() -> whci_add_cap()] - * with umc_device_create() and adds it to the bus with - * umc_device_register(). - * - * umc_device_register() calls device_register() which will push the - * bus management code to load your UMC driver's somehting_probe() - * that you have registered for that capability code. - * - * Now when the WHCI device is removed, whci_remove() will go over - * each umc_dev assigned to each of the PCI function's capabilities - * and through whci_del_cap() call umc_device_unregister() each - * created umc_dev. Of course, if you are bound to the device, your - * driver's something_remove() will be called. - */ - -#ifndef _LINUX_UWB_UMC_H_ -#define _LINUX_UWB_UMC_H_ - -#include -#include - -/* - * UMC capability IDs. - * - * 0x00 is reserved so use it for the radio controller device. - * - * [WHCI] table 2-8 - */ -#define UMC_CAP_ID_WHCI_RC 0x00 /* radio controller */ -#define UMC_CAP_ID_WHCI_WUSB_HC 0x01 /* WUSB host controller */ - -/** - * struct umc_dev - UMC capability device - * - * @version: version of the specification this capability conforms to. - * @cap_id: capability ID. - * @bar: PCI Bar (64 bit) where the resource lies - * @resource: register space resource. - * @irq: interrupt line. - */ -struct umc_dev { - u16 version; - u8 cap_id; - u8 bar; - struct resource resource; - unsigned irq; - struct device dev; -}; - -#define to_umc_dev(d) container_of(d, struct umc_dev, dev) - -/** - * struct umc_driver - UMC capability driver - * @cap_id: supported capability ID. - * @match: driver specific capability matching function. - * @match_data: driver specific data for match() (e.g., a - * table of pci_device_id's if umc_match_pci_id() is used). - */ -struct umc_driver { - char *name; - u8 cap_id; - int (*match)(struct umc_driver *, struct umc_dev *); - const void *match_data; - - int (*probe)(struct umc_dev *); - void (*remove)(struct umc_dev *); - int (*suspend)(struct umc_dev *, pm_message_t state); - int (*resume)(struct umc_dev *); - - struct device_driver driver; -}; - -#define to_umc_driver(d) container_of(d, struct umc_driver, driver) - -extern struct bus_type umc_bus_type; - -struct umc_dev *umc_device_create(struct device *parent, int n); -int __must_check umc_device_register(struct umc_dev *umc); -void umc_device_unregister(struct umc_dev *umc); - -int __must_check __umc_driver_register(struct umc_driver *umc_drv, - struct module *mod, - const char *mod_name); - -/** - * umc_driver_register - register a UMC capabiltity driver. - * @umc_drv: pointer to the driver. - */ -static inline int __must_check umc_driver_register(struct umc_driver *umc_drv) -{ - return __umc_driver_register(umc_drv, THIS_MODULE, KBUILD_MODNAME); -} -void umc_driver_unregister(struct umc_driver *umc_drv); - -/* - * Utility function you can use to match (umc_driver->match) against a - * null-terminated array of 'struct pci_device_id' in - * umc_driver->match_data. - */ -int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc); - -/** - * umc_parent_pci_dev - return the UMC's parent PCI device or NULL if none - * @umc_dev: UMC device whose parent PCI device we are looking for - * - * DIRTY!!! DON'T RELY ON THIS - * - * FIXME: This is as dirty as it gets, but we need some way to check - * the correct type of umc_dev->parent (so that for example, we can - * cast to pci_dev). Casting to pci_dev is necesary because at some - * point we need to request resources from the device. Mapping is - * easily over come (ioremap and stuff are bus agnostic), but hooking - * up to some error handlers (such as pci error handlers) might need - * this. - * - * THIS might (probably will) be removed in the future, so don't count - * on it. - */ -static inline struct pci_dev *umc_parent_pci_dev(struct umc_dev *umc_dev) -{ - struct pci_dev *pci_dev = NULL; - if (umc_dev->dev.parent->bus == &pci_bus_type) - pci_dev = to_pci_dev(umc_dev->dev.parent); - return pci_dev; -} - -/** - * umc_dev_get() - reference a UMC device. - * @umc_dev: Pointer to UMC device. - * - * NOTE: we are assuming in this whole scheme that the parent device - * is referenced at _probe() time and unreferenced at _remove() - * time by the parent's subsystem. - */ -static inline struct umc_dev *umc_dev_get(struct umc_dev *umc_dev) -{ - get_device(&umc_dev->dev); - return umc_dev; -} - -/** - * umc_dev_put() - unreference a UMC device. - * @umc_dev: Pointer to UMC device. - */ -static inline void umc_dev_put(struct umc_dev *umc_dev) -{ - put_device(&umc_dev->dev); -} - -/** - * umc_set_drvdata - set UMC device's driver data. - * @umc_dev: Pointer to UMC device. - * @data: Data to set. - */ -static inline void umc_set_drvdata(struct umc_dev *umc_dev, void *data) -{ - dev_set_drvdata(&umc_dev->dev, data); -} - -/** - * umc_get_drvdata - recover UMC device's driver data. - * @umc_dev: Pointer to UMC device. - */ -static inline void *umc_get_drvdata(struct umc_dev *umc_dev) -{ - return dev_get_drvdata(&umc_dev->dev); -} - -int umc_controller_reset(struct umc_dev *umc); - -#endif /* #ifndef _LINUX_UWB_UMC_H_ */ diff --git a/trunk/include/linux/uwb/whci.h b/trunk/include/linux/uwb/whci.h deleted file mode 100644 index 915ec23042d4..000000000000 --- a/trunk/include/linux/uwb/whci.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Wireless Host Controller Interface for Ultra-Wide-Band and Wireless USB - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * - * References: - * [WHCI] Wireless Host Controller Interface Specification for - * Certified Wireless Universal Serial Bus, revision 0.95. - */ -#ifndef _LINUX_UWB_WHCI_H_ -#define _LINUX_UWB_WHCI_H_ - -#include - -/* - * UWB interface capability registers (offsets from UWBBASE) - * - * [WHCI] section 2.2 - */ -#define UWBCAPINFO 0x00 /* == UWBCAPDATA(0) */ -# define UWBCAPINFO_TO_N_CAPS(c) (((c) >> 0) & 0xFull) -#define UWBCAPDATA(n) (8*(n)) -# define UWBCAPDATA_TO_VERSION(c) (((c) >> 32) & 0xFFFFull) -# define UWBCAPDATA_TO_OFFSET(c) (((c) >> 18) & 0x3FFFull) -# define UWBCAPDATA_TO_BAR(c) (((c) >> 16) & 0x3ull) -# define UWBCAPDATA_TO_SIZE(c) ((((c) >> 8) & 0xFFull) * sizeof(u32)) -# define UWBCAPDATA_TO_CAP_ID(c) (((c) >> 0) & 0xFFull) - -/* Size of the WHCI capability data (including the RC capability) for - a device with n capabilities. */ -#define UWBCAPDATA_SIZE(n) (8 + 8*(n)) - - -/* - * URC registers (offsets from URCBASE) - * - * [WHCI] section 2.3 - */ -#define URCCMD 0x00 -# define URCCMD_RESET (1 << 31) /* UMC Hardware reset */ -# define URCCMD_RS (1 << 30) /* Run/Stop */ -# define URCCMD_EARV (1 << 29) /* Event Address Register Valid */ -# define URCCMD_ACTIVE (1 << 15) /* Command is active */ -# define URCCMD_IWR (1 << 14) /* Interrupt When Ready */ -# define URCCMD_SIZE_MASK 0x00000fff /* Command size mask */ -#define URCSTS 0x04 -# define URCSTS_EPS (1 << 17) /* Event Processing Status */ -# define URCSTS_HALTED (1 << 16) /* RC halted */ -# define URCSTS_HSE (1 << 10) /* Host System Error...fried */ -# define URCSTS_ER (1 << 9) /* Event Ready */ -# define URCSTS_RCI (1 << 8) /* Ready for Command Interrupt */ -# define URCSTS_INT_MASK 0x00000700 /* URC interrupt sources */ -# define URCSTS_ISI 0x000000ff /* Interrupt Source Identification */ -#define URCINTR 0x08 -# define URCINTR_EN_ALL 0x000007ff /* Enable all interrupt sources */ -#define URCCMDADDR 0x10 -#define URCEVTADDR 0x18 -# define URCEVTADDR_OFFSET_MASK 0xfff /* Event pointer offset mask */ - - -/** Write 32 bit @value to little endian register at @addr */ -static inline -void le_writel(u32 value, void __iomem *addr) -{ - iowrite32(value, addr); -} - - -/** Read from 32 bit little endian register at @addr */ -static inline -u32 le_readl(void __iomem *addr) -{ - return ioread32(addr); -} - - -/** Write 64 bit @value to little endian register at @addr */ -static inline -void le_writeq(u64 value, void __iomem *addr) -{ - iowrite32(value, addr); - iowrite32(value >> 32, addr + 4); -} - - -/** Read from 64 bit little endian register at @addr */ -static inline -u64 le_readq(void __iomem *addr) -{ - u64 value; - value = ioread32(addr); - value |= (u64)ioread32(addr + 4) << 32; - return value; -} - -extern int whci_wait_for(struct device *dev, u32 __iomem *reg, - u32 mask, u32 result, - unsigned long max_ms, const char *tag); - -#endif /* #ifndef _LINUX_UWB_WHCI_H_ */ diff --git a/trunk/include/linux/wlp.h b/trunk/include/linux/wlp.h deleted file mode 100644 index 033545e145c7..000000000000 --- a/trunk/include/linux/wlp.h +++ /dev/null @@ -1,735 +0,0 @@ -/* - * WiMedia Logical Link Control Protocol (WLP) - * - * Copyright (C) 2005-2006 Intel Corporation - * Reinette Chatre - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * - * - Does not (yet) include support for WLP control frames - * WLP Draft 0.99 [6.5]. - * - * A visual representation of the data structures. - * - * wssidB wssidB - * ^ ^ - * | | - * wssidA wssidA - * wlp interface { ^ ^ - * ... | | - * ... ... wssid wssid ... - * wlp --- ... | | - * }; neighbors --> neighbA --> neighbB - * ... - * wss - * ... - * eda cache --> neighborA --> neighborB --> neighborC ... - */ - -#ifndef __LINUX__WLP_H_ -#define __LINUX__WLP_H_ - -#include -#include -#include -#include - -/** - * WLP Protocol ID - * WLP Draft 0.99 [6.2] - * - * The MUX header for all WLP frames - */ -#define WLP_PROTOCOL_ID 0x0100 - -/** - * WLP Version - * WLP version placed in the association frames (WLP 0.99 [6.6]) - */ -#define WLP_VERSION 0x10 - -/** - * Bytes needed to print UUID as string - */ -#define WLP_WSS_UUID_STRSIZE 48 - -/** - * Bytes needed to print nonce as string - */ -#define WLP_WSS_NONCE_STRSIZE 48 - - -/** - * Size used for WLP name size - * - * The WSS name is set to 65 bytes, 1 byte larger than the maximum - * allowed by the WLP spec. This is to have a null terminated string - * for display to the user. A maximum of 64 bytes will still be used - * when placing the WSS name field in association frames. - */ -#define WLP_WSS_NAME_SIZE 65 - -/** - * Number of bytes added by WLP to data frame - * - * A data frame transmitted from a host will be placed in a Standard or - * Abbreviated WLP frame. These have an extra 4 bytes of header (struct - * wlp_frame_std_abbrv_hdr). - * When the stack sends this data frame for transmission it needs to ensure - * there is enough headroom for this header. - */ -#define WLP_DATA_HLEN 4 - -/** - * State of device regarding WLP Service Set - * - * WLP_WSS_STATE_NONE: the host does not participate in any WSS - * WLP_WSS_STATE_PART_ENROLLED: used as part of the enrollment sequence - * ("Partial Enroll"). This state is used to - * indicate the first part of enrollment that is - * unsecure. If the WSS is unsecure then the - * state will promptly go to WLP_WSS_STATE_ENROLLED, - * if the WSS is not secure then the enrollment - * procedure is a few more steps before we are - * enrolled. - * WLP_WSS_STATE_ENROLLED: the host is enrolled in a WSS - * WLP_WSS_STATE_ACTIVE: WSS is activated - * WLP_WSS_STATE_CONNECTED: host is connected to neighbor in WSS - * - */ -enum wlp_wss_state { - WLP_WSS_STATE_NONE = 0, - WLP_WSS_STATE_PART_ENROLLED, - WLP_WSS_STATE_ENROLLED, - WLP_WSS_STATE_ACTIVE, - WLP_WSS_STATE_CONNECTED, -}; - -/** - * WSS Secure status - * WLP 0.99 Table 6 - * - * Set to one if the WSS is secure, zero if it is not secure - */ -enum wlp_wss_sec_status { - WLP_WSS_UNSECURE = 0, - WLP_WSS_SECURE, -}; - -/** - * WLP frame type - * WLP Draft 0.99 [6.2 Table 1] - */ -enum wlp_frame_type { - WLP_FRAME_STANDARD = 0, - WLP_FRAME_ABBREVIATED, - WLP_FRAME_CONTROL, - WLP_FRAME_ASSOCIATION, -}; - -/** - * WLP Association Message Type - * WLP Draft 0.99 [6.6.1.2 Table 8] - */ -enum wlp_assoc_type { - WLP_ASSOC_D1 = 2, - WLP_ASSOC_D2 = 3, - WLP_ASSOC_M1 = 4, - WLP_ASSOC_M2 = 5, - WLP_ASSOC_M3 = 7, - WLP_ASSOC_M4 = 8, - WLP_ASSOC_M5 = 9, - WLP_ASSOC_M6 = 10, - WLP_ASSOC_M7 = 11, - WLP_ASSOC_M8 = 12, - WLP_ASSOC_F0 = 14, - WLP_ASSOC_E1 = 32, - WLP_ASSOC_E2 = 33, - WLP_ASSOC_C1 = 34, - WLP_ASSOC_C2 = 35, - WLP_ASSOC_C3 = 36, - WLP_ASSOC_C4 = 37, -}; - -/** - * WLP Attribute Type - * WLP Draft 0.99 [6.6.1 Table 6] - */ -enum wlp_attr_type { - WLP_ATTR_AUTH = 0x1005, /* Authenticator */ - WLP_ATTR_DEV_NAME = 0x1011, /* Device Name */ - WLP_ATTR_DEV_PWD_ID = 0x1012, /* Device Password ID */ - WLP_ATTR_E_HASH1 = 0x1014, /* E-Hash1 */ - WLP_ATTR_E_HASH2 = 0x1015, /* E-Hash2 */ - WLP_ATTR_E_SNONCE1 = 0x1016, /* E-SNonce1 */ - WLP_ATTR_E_SNONCE2 = 0x1017, /* E-SNonce2 */ - WLP_ATTR_ENCR_SET = 0x1018, /* Encrypted Settings */ - WLP_ATTR_ENRL_NONCE = 0x101A, /* Enrollee Nonce */ - WLP_ATTR_KEYWRAP_AUTH = 0x101E, /* Key Wrap Authenticator */ - WLP_ATTR_MANUF = 0x1021, /* Manufacturer */ - WLP_ATTR_MSG_TYPE = 0x1022, /* Message Type */ - WLP_ATTR_MODEL_NAME = 0x1023, /* Model Name */ - WLP_ATTR_MODEL_NR = 0x1024, /* Model Number */ - WLP_ATTR_PUB_KEY = 0x1032, /* Public Key */ - WLP_ATTR_REG_NONCE = 0x1039, /* Registrar Nonce */ - WLP_ATTR_R_HASH1 = 0x103D, /* R-Hash1 */ - WLP_ATTR_R_HASH2 = 0x103E, /* R-Hash2 */ - WLP_ATTR_R_SNONCE1 = 0x103F, /* R-SNonce1 */ - WLP_ATTR_R_SNONCE2 = 0x1040, /* R-SNonce2 */ - WLP_ATTR_SERIAL = 0x1042, /* Serial number */ - WLP_ATTR_UUID_E = 0x1047, /* UUID-E */ - WLP_ATTR_UUID_R = 0x1048, /* UUID-R */ - WLP_ATTR_PRI_DEV_TYPE = 0x1054, /* Primary Device Type */ - WLP_ATTR_SEC_DEV_TYPE = 0x1055, /* Secondary Device Type */ - WLP_ATTR_PORT_DEV = 0x1056, /* Portable Device */ - WLP_ATTR_APP_EXT = 0x1058, /* Application Extension */ - WLP_ATTR_WLP_VER = 0x2000, /* WLP Version */ - WLP_ATTR_WSSID = 0x2001, /* WSSID */ - WLP_ATTR_WSS_NAME = 0x2002, /* WSS Name */ - WLP_ATTR_WSS_SEC_STAT = 0x2003, /* WSS Secure Status */ - WLP_ATTR_WSS_BCAST = 0x2004, /* WSS Broadcast Address */ - WLP_ATTR_WSS_M_KEY = 0x2005, /* WSS Master Key */ - WLP_ATTR_ACC_ENRL = 0x2006, /* Accepting Enrollment */ - WLP_ATTR_WSS_INFO = 0x2007, /* WSS Information */ - WLP_ATTR_WSS_SEL_MTHD = 0x2008, /* WSS Selection Method */ - WLP_ATTR_ASSC_MTHD_LIST = 0x2009, /* Association Methods List */ - WLP_ATTR_SEL_ASSC_MTHD = 0x200A, /* Selected Association Method */ - WLP_ATTR_ENRL_HASH_COMM = 0x200B, /* Enrollee Hash Commitment */ - WLP_ATTR_WSS_TAG = 0x200C, /* WSS Tag */ - WLP_ATTR_WSS_VIRT = 0x200D, /* WSS Virtual EUI-48 */ - WLP_ATTR_WLP_ASSC_ERR = 0x200E, /* WLP Association Error */ - WLP_ATTR_VNDR_EXT = 0x200F, /* Vendor Extension */ -}; - -/** - * WLP Category ID of primary/secondary device - * WLP Draft 0.99 [6.6.1.8 Table 12] - */ -enum wlp_dev_category_id { - WLP_DEV_CAT_COMPUTER = 1, - WLP_DEV_CAT_INPUT, - WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER, - WLP_DEV_CAT_CAMERA, - WLP_DEV_CAT_STORAGE, - WLP_DEV_CAT_INFRASTRUCTURE, - WLP_DEV_CAT_DISPLAY, - WLP_DEV_CAT_MULTIM, - WLP_DEV_CAT_GAMING, - WLP_DEV_CAT_TELEPHONE, - WLP_DEV_CAT_OTHER = 65535, -}; - -/** - * WLP WSS selection method - * WLP Draft 0.99 [6.6.1.6 Table 10] - */ -enum wlp_wss_sel_mthd { - WLP_WSS_ENRL_SELECT = 1, /* Enrollee selects */ - WLP_WSS_REG_SELECT, /* Registrar selects */ -}; - -/** - * WLP association error values - * WLP Draft 0.99 [6.6.1.5 Table 9] - */ -enum wlp_assc_error { - WLP_ASSOC_ERROR_NONE, - WLP_ASSOC_ERROR_AUTH, /* Authenticator Failure */ - WLP_ASSOC_ERROR_ROGUE, /* Rogue activity suspected */ - WLP_ASSOC_ERROR_BUSY, /* Device busy */ - WLP_ASSOC_ERROR_LOCK, /* Setup Locked */ - WLP_ASSOC_ERROR_NOT_READY, /* Registrar not ready */ - WLP_ASSOC_ERROR_INV, /* Invalid WSS selection */ - WLP_ASSOC_ERROR_MSG_TIME, /* Message timeout */ - WLP_ASSOC_ERROR_ENR_TIME, /* Enrollment session timeout */ - WLP_ASSOC_ERROR_PW, /* Device password invalid */ - WLP_ASSOC_ERROR_VER, /* Unsupported version */ - WLP_ASSOC_ERROR_INT, /* Internal error */ - WLP_ASSOC_ERROR_UNDEF, /* Undefined error */ - WLP_ASSOC_ERROR_NUM, /* Numeric comparison failure */ - WLP_ASSOC_ERROR_WAIT, /* Waiting for user input */ -}; - -/** - * WLP Parameters - * WLP 0.99 [7.7] - */ -enum wlp_parameters { - WLP_PER_MSG_TIMEOUT = 15, /* Seconds to wait for response to - association message. */ -}; - -/** - * WLP IE - * - * The WLP IE should be included in beacons by all devices. - * - * The driver can set only a few of the fields in this information element, - * most fields are managed by the device self. When the driver needs to set - * a field it will only provide values for the fields of interest, the rest - * will be filled with zeroes. The fields of interest are: - * - * Element ID - * Length - * Capabilities (only to include WSSID Hash list length) - * WSSID Hash List fields - * - * WLP 0.99 [6.7] - * - * Only the fields that will be used are detailed in this structure, rest - * are not detailed or marked as "notused". - */ -struct wlp_ie { - struct uwb_ie_hdr hdr; - __le16 capabilities; - __le16 cycle_param; - __le16 acw_anchor_addr; - u8 wssid_hash_list[]; -} __attribute__((packed)); - -static inline int wlp_ie_hash_length(struct wlp_ie *ie) -{ - return (le16_to_cpu(ie->capabilities) >> 12) & 0xf; -} - -static inline void wlp_ie_set_hash_length(struct wlp_ie *ie, int hash_length) -{ - u16 caps = le16_to_cpu(ie->capabilities); - caps = (caps & ~(0xf << 12)) | (hash_length << 12); - ie->capabilities = cpu_to_le16(caps); -} - -/** - * WLP nonce - * WLP Draft 0.99 [6.6.1 Table 6] - * - * A 128-bit random number often used (E-SNonce1, E-SNonce2, Enrollee - * Nonce, Registrar Nonce, R-SNonce1, R-SNonce2). It is passed to HW so - * it is packed. - */ -struct wlp_nonce { - u8 data[16]; -} __attribute__((packed)); - -/** - * WLP UUID - * WLP Draft 0.99 [6.6.1 Table 6] - * - * Universally Unique Identifier (UUID) encoded as an octet string in the - * order the octets are shown in string representation in RFC4122. A UUID - * is often used (UUID-E, UUID-R, WSSID). It is passed to HW so it is packed. - */ -struct wlp_uuid { - u8 data[16]; -} __attribute__((packed)); - - -/** - * Primary and secondary device type attributes - * WLP Draft 0.99 [6.6.1.8] - */ -struct wlp_dev_type { - enum wlp_dev_category_id category:16; - u8 OUI[3]; - u8 OUIsubdiv; - __le16 subID; -} __attribute__((packed)); - -/** - * WLP frame header - * WLP Draft 0.99 [6.2] - */ -struct wlp_frame_hdr { - __le16 mux_hdr; /* WLP_PROTOCOL_ID */ - enum wlp_frame_type type:8; -} __attribute__((packed)); - -/** - * WLP attribute field header - * WLP Draft 0.99 [6.6.1] - * - * Header of each attribute found in an association frame - */ -struct wlp_attr_hdr { - __le16 type; - __le16 length; -} __attribute__((packed)); - -/** - * Device information commonly used together - * - * Each of these device information elements has a specified range in which it - * should fit (WLP 0.99 [Table 6]). This range provided in the spec does not - * include the termination null '\0' character (when used in the - * association protocol the attribute fields are accompanied - * with a "length" field so the full range from the spec can be used for - * the value). We thus allocate an extra byte to be able to store a string - * of max length with a terminating '\0'. - */ -struct wlp_device_info { - char name[33]; - char model_name[33]; - char manufacturer[65]; - char model_nr[33]; - char serial[33]; - struct wlp_dev_type prim_dev_type; -}; - -/** - * Macros for the WLP attributes - * - * There are quite a few attributes (total is 43). The attribute layout can be - * in one of three categories: one value, an array, an enum forced to 8 bits. - * These macros help with their definitions. - */ -#define wlp_attr(type, name) \ -struct wlp_attr_##name { \ - struct wlp_attr_hdr hdr; \ - type name; \ -} __attribute__((packed)); - -#define wlp_attr_array(type, name) \ -struct wlp_attr_##name { \ - struct wlp_attr_hdr hdr; \ - type name[]; \ -} __attribute__((packed)); - -/** - * WLP association attribute fields - * WLP Draft 0.99 [6.6.1 Table 6] - * - * Attributes appear in same order as the Table in the spec - * FIXME Does not define all attributes yet - */ - -/* Device name: Friendly name of sending device */ -wlp_attr_array(u8, dev_name) - -/* Enrollee Nonce: Random number generated by enrollee for an enrollment - * session */ -wlp_attr(struct wlp_nonce, enonce) - -/* Manufacturer name: Name of manufacturer of the sending device */ -wlp_attr_array(u8, manufacturer) - -/* WLP Message Type */ -wlp_attr(u8, msg_type) - -/* WLP Model name: Model name of sending device */ -wlp_attr_array(u8, model_name) - -/* WLP Model number: Model number of sending device */ -wlp_attr_array(u8, model_nr) - -/* Registrar Nonce: Random number generated by registrar for an enrollment - * session */ -wlp_attr(struct wlp_nonce, rnonce) - -/* Serial number of device */ -wlp_attr_array(u8, serial) - -/* UUID of enrollee */ -wlp_attr(struct wlp_uuid, uuid_e) - -/* UUID of registrar */ -wlp_attr(struct wlp_uuid, uuid_r) - -/* WLP Primary device type */ -wlp_attr(struct wlp_dev_type, prim_dev_type) - -/* WLP Secondary device type */ -wlp_attr(struct wlp_dev_type, sec_dev_type) - -/* WLP protocol version */ -wlp_attr(u8, version) - -/* WLP service set identifier */ -wlp_attr(struct wlp_uuid, wssid) - -/* WLP WSS name */ -wlp_attr_array(u8, wss_name) - -/* WLP WSS Secure Status */ -wlp_attr(u8, wss_sec_status) - -/* WSS Broadcast Address */ -wlp_attr(struct uwb_mac_addr, wss_bcast) - -/* WLP Accepting Enrollment */ -wlp_attr(u8, accept_enrl) - -/** - * WSS information attributes - * WLP Draft 0.99 [6.6.3 Table 15] - */ -struct wlp_wss_info { - struct wlp_attr_wssid wssid; - struct wlp_attr_wss_name name; - struct wlp_attr_accept_enrl accept; - struct wlp_attr_wss_sec_status sec_stat; - struct wlp_attr_wss_bcast bcast; -} __attribute__((packed)); - -/* WLP WSS Information */ -wlp_attr_array(struct wlp_wss_info, wss_info) - -/* WLP WSS Selection method */ -wlp_attr(u8, wss_sel_mthd) - -/* WLP WSS tag */ -wlp_attr(u8, wss_tag) - -/* WSS Virtual Address */ -wlp_attr(struct uwb_mac_addr, wss_virt) - -/* WLP association error */ -wlp_attr(u8, wlp_assc_err) - -/** - * WLP standard and abbreviated frames - * - * WLP Draft 0.99 [6.3] and [6.4] - * - * The difference between the WLP standard frame and the WLP - * abbreviated frame is that the standard frame includes the src - * and dest addresses from the Ethernet header, the abbreviated frame does - * not. - * The src/dest (as well as the type/length and client data) are already - * defined as part of the Ethernet header, we do not do this here. - * From this perspective the standard and abbreviated frames appear the - * same - they will be treated differently though. - * - * The size of this header is also captured in WLP_DATA_HLEN to enable - * interfaces to prepare their headroom. - */ -struct wlp_frame_std_abbrv_hdr { - struct wlp_frame_hdr hdr; - u8 tag; -} __attribute__((packed)); - -/** - * WLP association frames - * - * WLP Draft 0.99 [6.6] - */ -struct wlp_frame_assoc { - struct wlp_frame_hdr hdr; - enum wlp_assoc_type type:8; - struct wlp_attr_version version; - struct wlp_attr_msg_type msg_type; - u8 attr[]; -} __attribute__((packed)); - -/* Ethernet to dev address mapping */ -struct wlp_eda { - spinlock_t lock; - struct list_head cache; /* Eth<->Dev Addr cache */ -}; - -/** - * WSS information temporary storage - * - * This information is only stored temporarily during discovery. It should - * not be stored unless the device is enrolled in the advertised WSS. This - * is done mainly because we follow the letter of the spec in this regard. - * See WLP 0.99 [7.2.3]. - * When the device does become enrolled in a WSS the WSS information will - * be stored as part of the more comprehensive struct wlp_wss. - */ -struct wlp_wss_tmp_info { - char name[WLP_WSS_NAME_SIZE]; - u8 accept_enroll; - u8 sec_status; - struct uwb_mac_addr bcast; -}; - -struct wlp_wssid_e { - struct list_head node; - struct wlp_uuid wssid; - struct wlp_wss_tmp_info *info; -}; - -/** - * A cache entry of WLP neighborhood - * - * @node: head of list is wlp->neighbors - * @wssid: list of wssids of this neighbor, element is wlp_wssid_e - * @info: temporary storage for information learned during discovery. This - * storage is used together with the wssid_e temporary storage - * during discovery. - */ -struct wlp_neighbor_e { - struct list_head node; - struct wlp_uuid uuid; - struct uwb_dev *uwb_dev; - struct list_head wssid; /* Elements are wlp_wssid_e */ - struct wlp_device_info *info; -}; - -struct wlp; -/** - * Information for an association session in progress. - * - * @exp_message: The type of the expected message. Both this message and a - * F0 message (which can be sent in response to any - * association frame) will be accepted as a valid message for - * this session. - * @cb: The function that will be called upon receipt of this - * message. - * @cb_priv: Private data of callback - * @data: Data used in association process (always a sk_buff?) - * @neighbor: Address of neighbor with which association session is in - * progress. - */ -struct wlp_session { - enum wlp_assoc_type exp_message; - void (*cb)(struct wlp *); - void *cb_priv; - void *data; - struct uwb_dev_addr neighbor_addr; -}; - -/** - * WLP Service Set - * - * @mutex: used to protect entire WSS structure. - * - * @name: The WSS name is set to 65 bytes, 1 byte larger than the maximum - * allowed by the WLP spec. This is to have a null terminated string - * for display to the user. A maximum of 64 bytes will still be used - * when placing the WSS name field in association frames. - * - * @accept_enroll: Accepting enrollment: Set to one if registrar is - * accepting enrollment in WSS, or zero otherwise. - * - * Global and local information for each WSS in which we are enrolled. - * WLP 0.99 Section 7.2.1 and Section 7.2.2 - */ -struct wlp_wss { - struct mutex mutex; - struct kobject kobj; - /* Global properties. */ - struct wlp_uuid wssid; - u8 hash; - char name[WLP_WSS_NAME_SIZE]; - struct uwb_mac_addr bcast; - u8 secure_status:1; - u8 master_key[16]; - /* Local properties. */ - u8 tag; - struct uwb_mac_addr virtual_addr; - /* Extra */ - u8 accept_enroll:1; - enum wlp_wss_state state; -}; - -/** - * WLP main structure - * @mutex: protect changes to WLP structure. We only allow changes to the - * uuid, so currently this mutex only protects this field. - */ -struct wlp { - struct mutex mutex; - struct uwb_rc *rc; /* UWB radio controller */ - struct uwb_pal pal; - struct wlp_eda eda; - struct wlp_uuid uuid; - struct wlp_session *session; - struct wlp_wss wss; - struct mutex nbmutex; /* Neighbor mutex protects neighbors list */ - struct list_head neighbors; /* Elements are wlp_neighbor_e */ - struct uwb_notifs_handler uwb_notifs_handler; - struct wlp_device_info *dev_info; - void (*fill_device_info)(struct wlp *wlp, struct wlp_device_info *info); - int (*xmit_frame)(struct wlp *, struct sk_buff *, - struct uwb_dev_addr *); - void (*stop_queue)(struct wlp *); - void (*start_queue)(struct wlp *); -}; - -/* sysfs */ - - -struct wlp_wss_attribute { - struct attribute attr; - ssize_t (*show)(struct wlp_wss *wss, char *buf); - ssize_t (*store)(struct wlp_wss *wss, const char *buf, size_t count); -}; - -#define WSS_ATTR(_name, _mode, _show, _store) \ -static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \ - _show, _store) - -extern int wlp_setup(struct wlp *, struct uwb_rc *); -extern void wlp_remove(struct wlp *); -extern ssize_t wlp_neighborhood_show(struct wlp *, char *); -extern int wlp_wss_setup(struct net_device *, struct wlp_wss *); -extern void wlp_wss_remove(struct wlp_wss *); -extern ssize_t wlp_wss_activate_show(struct wlp_wss *, char *); -extern ssize_t wlp_wss_activate_store(struct wlp_wss *, const char *, size_t); -extern ssize_t wlp_eda_show(struct wlp *, char *); -extern ssize_t wlp_eda_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_uuid_show(struct wlp *, char *); -extern ssize_t wlp_uuid_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_name_show(struct wlp *, char *); -extern ssize_t wlp_dev_name_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_manufacturer_show(struct wlp *, char *); -extern ssize_t wlp_dev_manufacturer_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_model_name_show(struct wlp *, char *); -extern ssize_t wlp_dev_model_name_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_model_nr_show(struct wlp *, char *); -extern ssize_t wlp_dev_model_nr_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_serial_show(struct wlp *, char *); -extern ssize_t wlp_dev_serial_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_prim_category_show(struct wlp *, char *); -extern ssize_t wlp_dev_prim_category_store(struct wlp *, const char *, - size_t); -extern ssize_t wlp_dev_prim_OUI_show(struct wlp *, char *); -extern ssize_t wlp_dev_prim_OUI_store(struct wlp *, const char *, size_t); -extern ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *, char *); -extern ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *, const char *, - size_t); -extern ssize_t wlp_dev_prim_subcat_show(struct wlp *, char *); -extern ssize_t wlp_dev_prim_subcat_store(struct wlp *, const char *, - size_t); -extern int wlp_receive_frame(struct device *, struct wlp *, struct sk_buff *, - struct uwb_dev_addr *); -extern int wlp_prepare_tx_frame(struct device *, struct wlp *, - struct sk_buff *, struct uwb_dev_addr *); -void wlp_reset_all(struct wlp *wlp); - -/** - * Initialize WSS - */ -static inline -void wlp_wss_init(struct wlp_wss *wss) -{ - mutex_init(&wss->mutex); -} - -static inline -void wlp_init(struct wlp *wlp) -{ - INIT_LIST_HEAD(&wlp->neighbors); - mutex_init(&wlp->mutex); - mutex_init(&wlp->nbmutex); - wlp_wss_init(&wlp->wss); -} - - -#endif /* #ifndef __LINUX__WLP_H_ */ diff --git a/trunk/init/main.c b/trunk/init/main.c index 672ae75b2059..3e17a3bafe60 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -648,7 +647,6 @@ asmlinkage void __init start_kernel(void) vmalloc_init(); vfs_caches_init_early(); cpuset_init_early(); - page_cgroup_init(); mem_init(); enable_debug_pagealloc(); cpu_hotplug_init(); diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c index 4895fde4eb93..3de6ea3ee740 100644 --- a/trunk/kernel/irq/chip.c +++ b/trunk/kernel/irq/chip.c @@ -127,7 +127,7 @@ int set_irq_type(unsigned int irq, unsigned int type) return 0; spin_lock_irqsave(&desc->lock, flags); - ret = __irq_set_trigger(desc, irq, flags); + ret = __irq_set_trigger(desc, irq, type); spin_unlock_irqrestore(&desc->lock, flags); return ret; } diff --git a/trunk/kernel/kexec.c b/trunk/kernel/kexec.c index ac0fde7b54d0..777ac458ac99 100644 --- a/trunk/kernel/kexec.c +++ b/trunk/kernel/kexec.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/trunk/lib/bitmap.c b/trunk/lib/bitmap.c index 1338469ac849..482df94ea21e 100644 --- a/trunk/lib/bitmap.c +++ b/trunk/lib/bitmap.c @@ -996,25 +996,3 @@ int bitmap_allocate_region(unsigned long *bitmap, int pos, int order) return 0; } EXPORT_SYMBOL(bitmap_allocate_region); - -/** - * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order. - * @dst: destination buffer - * @src: bitmap to copy - * @nbits: number of bits in the bitmap - * - * Require nbits % BITS_PER_LONG == 0. - */ -void bitmap_copy_le(void *dst, const unsigned long *src, int nbits) -{ - unsigned long *d = dst; - int i; - - for (i = 0; i < nbits/BITS_PER_LONG; i++) { - if (BITS_PER_LONG == 64) - d[i] = cpu_to_le64(src[i]); - else - d[i] = cpu_to_le32(src[i]); - } -} -EXPORT_SYMBOL(bitmap_copy_le); diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index 866dcc7eeb0c..d4a92b63e98e 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -1088,6 +1088,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) int node; if (unlikely((cont->parent) == NULL)) { + page_cgroup_init(); mem = &init_mem_cgroup; } else { mem = mem_cgroup_alloc(); diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index 164951c47305..3a6c4a658325 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -64,6 +64,8 @@ #include "internal.h" +#include "internal.h" + #ifndef CONFIG_NEED_MULTIPLE_NODES /* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr; diff --git a/trunk/mm/page_cgroup.c b/trunk/mm/page_cgroup.c index f59d797dc5a9..5d86550701f2 100644 --- a/trunk/mm/page_cgroup.c +++ b/trunk/mm/page_cgroup.c @@ -4,10 +4,7 @@ #include #include #include -#include #include -#include -#include static void __meminit __init_page_cgroup(struct page_cgroup *pc, unsigned long pfn) @@ -69,9 +66,6 @@ void __init page_cgroup_init(void) int nid, fail; - if (mem_cgroup_subsys.disabled) - return; - for_each_online_node(nid) { fail = alloc_node_page_cgroup(nid); if (fail) @@ -112,14 +106,9 @@ int __meminit init_section_page_cgroup(unsigned long pfn) nid = page_to_nid(pfn_to_page(pfn)); table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; - if (slab_is_available()) { - base = kmalloc_node(table_size, GFP_KERNEL, nid); - if (!base) - base = vmalloc_node(table_size, nid); - } else { - base = __alloc_bootmem_node_nopanic(NODE_DATA(nid), table_size, - PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); - } + base = kmalloc_node(table_size, GFP_KERNEL, nid); + if (!base) + base = vmalloc_node(table_size, nid); if (!base) { printk(KERN_ERR "page cgroup allocation failure\n"); @@ -146,16 +135,11 @@ void __free_page_cgroup(unsigned long pfn) if (!ms || !ms->page_cgroup) return; base = ms->page_cgroup + pfn; - if (is_vmalloc_addr(base)) { + ms->page_cgroup = NULL; + if (is_vmalloc_addr(base)) vfree(base); - ms->page_cgroup = NULL; - } else { - struct page *page = virt_to_page(base); - if (!PageReserved(page)) { /* Is bootmem ? */ - kfree(base); - ms->page_cgroup = NULL; - } - } + else + kfree(base); } int online_page_cgroup(unsigned long start_pfn, @@ -229,9 +213,6 @@ void __init page_cgroup_init(void) unsigned long pfn; int fail = 0; - if (mem_cgroup_subsys.disabled) - return; - for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) { if (!pfn_present(pfn)) continue; diff --git a/trunk/mm/tiny-shmem.c b/trunk/mm/tiny-shmem.c index 3e67d575ee6e..8d7a27a6335c 100644 --- a/trunk/mm/tiny-shmem.c +++ b/trunk/mm/tiny-shmem.c @@ -95,7 +95,6 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) put_memory: return ERR_PTR(error); } -EXPORT_SYMBOL_GPL(shmem_file_setup); /** * shmem_zero_setup - setup a shared anonymous mapping diff --git a/trunk/mm/vmalloc.c b/trunk/mm/vmalloc.c index 65ae576030da..0797589d51f8 100644 --- a/trunk/mm/vmalloc.c +++ b/trunk/mm/vmalloc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include